diff options
Diffstat (limited to 'src')
217 files changed, 11739 insertions, 5444 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index eea646a4..aee7eae9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -64,6 +64,8 @@ SYSTEMD_NM_CFLAGS_PATHS = \ -I$(top_srcdir)/src/systemd libsystemd_nm_la_SOURCES = \ + systemd/nm-sd.c \ + systemd/nm-sd.h \ systemd/nm-sd-adapt.c \ systemd/nm-sd-adapt.h \ systemd/src/basic/alloc-util.c \ @@ -71,6 +73,8 @@ libsystemd_nm_la_SOURCES = \ systemd/src/basic/async.h \ systemd/src/basic/escape.c \ systemd/src/basic/escape.h \ + systemd/src/basic/ether-addr-util.c \ + systemd/src/basic/ether-addr-util.h \ systemd/src/basic/fd-util.c \ systemd/src/basic/fd-util.h \ systemd/src/basic/fileio.c \ @@ -106,6 +110,7 @@ libsystemd_nm_la_SOURCES = \ systemd/src/basic/set.h \ systemd/src/basic/siphash24.c \ systemd/src/basic/siphash24.h \ + systemd/src/basic/socket-util.c \ systemd/src/basic/socket-util.h \ systemd/src/basic/sparse-endian.h \ systemd/src/basic/stdio-util.h \ @@ -138,14 +143,11 @@ libsystemd_nm_la_SOURCES = \ systemd/src/libsystemd-network/dhcp6-network.c \ systemd/src/libsystemd-network/dhcp6-option.c \ systemd/src/libsystemd-network/dhcp6-protocol.h \ - systemd/src/libsystemd-network/lldp-internal.c \ systemd/src/libsystemd-network/lldp-internal.h \ + systemd/src/libsystemd-network/lldp-neighbor.c \ + systemd/src/libsystemd-network/lldp-neighbor.h \ systemd/src/libsystemd-network/lldp-network.c \ systemd/src/libsystemd-network/lldp-network.h \ - systemd/src/libsystemd-network/lldp-port.c \ - systemd/src/libsystemd-network/lldp-port.h \ - systemd/src/libsystemd-network/lldp-tlv.c \ - systemd/src/libsystemd-network/lldp-tlv.h \ systemd/src/libsystemd-network/lldp.h \ systemd/src/libsystemd-network/network-internal.c \ systemd/src/libsystemd-network/network-internal.h \ @@ -156,6 +158,7 @@ libsystemd_nm_la_SOURCES = \ systemd/src/libsystemd-network/sd-ipv4acd.c \ systemd/src/libsystemd-network/sd-ipv4ll.c \ systemd/src/libsystemd-network/sd-lldp.c \ + systemd/src/libsystemd/sd-event/sd-event.c \ systemd/src/libsystemd/sd-id128/sd-id128.c \ systemd/src/shared/dns-domain.c \ systemd/src/shared/dns-domain.h \ @@ -287,6 +290,7 @@ libNetworkManager_la_SOURCES = \ \ dhcp-manager/nm-dhcp-client.c \ dhcp-manager/nm-dhcp-client.h \ + dhcp-manager/nm-dhcp-client-logging.h \ dhcp-manager/nm-dhcp-utils.c \ dhcp-manager/nm-dhcp-utils.h \ dhcp-manager/nm-dhcp-listener.c \ @@ -310,6 +314,8 @@ libNetworkManager_la_SOURCES = \ dnsmasq-manager/nm-dnsmasq-utils.c \ dnsmasq-manager/nm-dnsmasq-utils.h \ \ + platform/nmp-netns.c \ + platform/nmp-netns.h \ platform/nm-fake-platform.c \ platform/nm-fake-platform.h \ platform/nm-linux-platform.c \ @@ -462,6 +468,8 @@ nm_enum_types_sources = $(filter-out \ %/nm-device-private.h \ %/nm-rdisc-private.h \ %/wifi-utils-private.h \ + %/nm-dhcp-client-logging.h \ + %/nm-device-logging.h \ , $(libNetworkManager_la_SOURCES)) BUILT_SOURCES = $(GLIB_GENERATED) @@ -519,13 +527,16 @@ if WITH_LIBSOUP libNetworkManager_la_LIBADD += $(LIBSOUP_LIBS) endif -NetworkManager_LDFLAGS = -rdynamic +NetworkManager_LDFLAGS = \ + -rdynamic \ + -Wl,--version-script="$(srcdir)/NetworkManager.ver" ###################### libnm_iface_helper_la_SOURCES = \ dhcp-manager/nm-dhcp-client.c \ dhcp-manager/nm-dhcp-client.h \ + dhcp-manager/nm-dhcp-client-logging.h \ dhcp-manager/nm-dhcp-utils.c \ dhcp-manager/nm-dhcp-utils.h \ dhcp-manager/nm-dhcp-manager.c \ @@ -537,6 +548,8 @@ libnm_iface_helper_la_SOURCES = \ platform/nm-platform.h \ platform/nm-platform-utils.c \ platform/nm-platform-utils.h \ + platform/nmp-netns.c \ + platform/nmp-netns.h \ platform/nmp-object.c \ platform/nmp-object.h \ platform/wifi/wifi-utils-nl80211.c \ @@ -619,12 +632,13 @@ dbusservice_DATA = org.freedesktop.NetworkManager.conf EXTRA_DIST = \ $(dbusservice_DATA) \ - $(NetworkManager_DATA) + $(NetworkManager_DATA) \ + NetworkManager.ver rundir=$(runstatedir)/NetworkManager statedir=$(localstatedir)/lib/NetworkManager install-data-hook: - $(mkinstalldirs) -m 0700 $(DESTDIR)$(rundir) + $(mkinstalldirs) -m 0755 $(DESTDIR)$(rundir) $(mkinstalldirs) -m 0700 $(DESTDIR)$(statedir) $(mkinstalldirs) -m 0755 $(DESTDIR)$(pkglibdir) diff --git a/src/Makefile.in b/src/Makefile.in index 14ef31f7..df113412 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -188,8 +188,10 @@ am__libNetworkManager_la_SOURCES_DIST = devices/nm-device-bond.h \ devices/nm-device-factory.h devices/nm-device-generic.c \ devices/nm-device-generic.h devices/nm-device-logging.h \ devices/nm-device-private.h dhcp-manager/nm-dhcp-client.c \ - dhcp-manager/nm-dhcp-client.h dhcp-manager/nm-dhcp-utils.c \ - dhcp-manager/nm-dhcp-utils.h dhcp-manager/nm-dhcp-listener.c \ + dhcp-manager/nm-dhcp-client.h \ + dhcp-manager/nm-dhcp-client-logging.h \ + dhcp-manager/nm-dhcp-utils.c dhcp-manager/nm-dhcp-utils.h \ + dhcp-manager/nm-dhcp-listener.c \ dhcp-manager/nm-dhcp-listener.h dhcp-manager/nm-dhcp-manager.c \ dhcp-manager/nm-dhcp-manager.h dns-manager/nm-dns-dnsmasq.c \ dns-manager/nm-dns-dnsmasq.h dns-manager/nm-dns-unbound.c \ @@ -200,7 +202,8 @@ am__libNetworkManager_la_SOURCES_DIST = devices/nm-device-bond.h \ dnsmasq-manager/nm-dnsmasq-manager.c \ dnsmasq-manager/nm-dnsmasq-manager.h \ dnsmasq-manager/nm-dnsmasq-utils.c \ - dnsmasq-manager/nm-dnsmasq-utils.h platform/nm-fake-platform.c \ + dnsmasq-manager/nm-dnsmasq-utils.h platform/nmp-netns.c \ + platform/nmp-netns.h platform/nm-fake-platform.c \ platform/nm-fake-platform.h platform/nm-linux-platform.c \ platform/nm-linux-platform.h platform/nm-platform.c \ platform/nm-platform.h platform/nm-platform-utils.c \ @@ -278,27 +281,28 @@ am_libNetworkManager_la_OBJECTS = $(am__objects_1) $(am__objects_1) \ nm-dhcp-listener.lo nm-dhcp-manager.lo nm-dns-dnsmasq.lo \ nm-dns-unbound.lo nm-dns-manager.lo nm-dns-plugin.lo \ nm-dns-utils.lo nm-dnsmasq-manager.lo nm-dnsmasq-utils.lo \ - nm-fake-platform.lo nm-linux-platform.lo nm-platform.lo \ - nm-platform-utils.lo nmp-object.lo wifi-utils-nl80211.lo \ - wifi-utils.lo nm-fake-rdisc.lo nm-lndp-rdisc.lo nm-rdisc.lo \ - nm-ppp-manager.lo nm-agent-manager.lo nm-inotify-helper.lo \ - nm-secret-agent.lo nm-settings-connection.lo \ - nm-settings-plugin.lo nm-settings.lo nm-keyfile-connection.lo \ - plugin.lo reader.lo utils.lo writer.lo nm-supplicant-config.lo \ - nm-supplicant-interface.lo nm-supplicant-manager.lo \ - nm-supplicant-settings-verify.lo nm-vpn-connection.lo \ - nm-vpn-manager.lo nm-activation-request.lo \ - nm-active-connection.lo nm-audit-manager.lo nm-bus-manager.lo \ - nm-config.lo nm-config-data.lo nm-connection-provider.lo \ - nm-connectivity.lo nm-dcb.lo nm-route-manager.lo \ - nm-default-route-manager.lo nm-dhcp4-config.lo \ - nm-dhcp6-config.lo nm-dispatcher.lo nm-enum-types.lo \ - nm-exported-object.lo nm-firewall-manager.lo nm-ip4-config.lo \ - nm-ip6-config.lo nm-logging.lo nm-auth-manager.lo \ - nm-auth-subject.lo nm-auth-utils.lo nm-manager.lo \ - nm-multi-index.lo nm-policy.lo nm-rfkill-manager.lo \ - nm-session-monitor.lo nm-core-utils.lo NetworkManagerUtils.lo \ - $(am__objects_2) $(am__objects_3) $(am__objects_4) + nmp-netns.lo nm-fake-platform.lo nm-linux-platform.lo \ + nm-platform.lo nm-platform-utils.lo nmp-object.lo \ + wifi-utils-nl80211.lo wifi-utils.lo nm-fake-rdisc.lo \ + nm-lndp-rdisc.lo nm-rdisc.lo nm-ppp-manager.lo \ + nm-agent-manager.lo nm-inotify-helper.lo nm-secret-agent.lo \ + nm-settings-connection.lo nm-settings-plugin.lo nm-settings.lo \ + nm-keyfile-connection.lo plugin.lo reader.lo utils.lo \ + writer.lo nm-supplicant-config.lo nm-supplicant-interface.lo \ + nm-supplicant-manager.lo nm-supplicant-settings-verify.lo \ + nm-vpn-connection.lo nm-vpn-manager.lo \ + nm-activation-request.lo nm-active-connection.lo \ + nm-audit-manager.lo nm-bus-manager.lo nm-config.lo \ + nm-config-data.lo nm-connection-provider.lo nm-connectivity.lo \ + nm-dcb.lo nm-route-manager.lo nm-default-route-manager.lo \ + nm-dhcp4-config.lo nm-dhcp6-config.lo nm-dispatcher.lo \ + nm-enum-types.lo nm-exported-object.lo nm-firewall-manager.lo \ + nm-ip4-config.lo nm-ip6-config.lo nm-logging.lo \ + nm-auth-manager.lo nm-auth-subject.lo nm-auth-utils.lo \ + nm-manager.lo nm-multi-index.lo nm-policy.lo \ + nm-rfkill-manager.lo nm-session-monitor.lo nm-core-utils.lo \ + NetworkManagerUtils.lo $(am__objects_2) $(am__objects_3) \ + $(am__objects_4) libNetworkManager_la_OBJECTS = $(am_libNetworkManager_la_OBJECTS) libnm_iface_helper_la_DEPENDENCIES = \ $(top_builddir)/libnm-core/libnm-core.la \ @@ -308,11 +312,13 @@ libnm_iface_helper_la_DEPENDENCIES = \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am__libnm_iface_helper_la_SOURCES_DIST = \ dhcp-manager/nm-dhcp-client.c dhcp-manager/nm-dhcp-client.h \ + dhcp-manager/nm-dhcp-client-logging.h \ dhcp-manager/nm-dhcp-utils.c dhcp-manager/nm-dhcp-utils.h \ dhcp-manager/nm-dhcp-manager.c dhcp-manager/nm-dhcp-manager.h \ platform/nm-linux-platform.c platform/nm-linux-platform.h \ platform/nm-platform.c platform/nm-platform.h \ platform/nm-platform-utils.c platform/nm-platform-utils.h \ + platform/nmp-netns.c platform/nmp-netns.h \ platform/nmp-object.c platform/nmp-object.h \ platform/wifi/wifi-utils-nl80211.c \ platform/wifi/wifi-utils-nl80211.h \ @@ -330,16 +336,17 @@ am__libnm_iface_helper_la_SOURCES_DIST = \ platform/wifi/wifi-utils-wext.h am_libnm_iface_helper_la_OBJECTS = nm-dhcp-client.lo nm-dhcp-utils.lo \ nm-dhcp-manager.lo nm-linux-platform.lo nm-platform.lo \ - nm-platform-utils.lo nmp-object.lo wifi-utils-nl80211.lo \ - wifi-utils.lo nm-fake-rdisc.lo nm-lndp-rdisc.lo nm-rdisc.lo \ - nm-route-manager.lo nm-exported-object.lo nm-ip4-config.lo \ - nm-ip6-config.lo nm-enum-types.lo nm-logging.lo \ - nm-multi-index.lo nm-core-utils.lo NetworkManagerUtils.lo \ - $(am__objects_4) + nm-platform-utils.lo nmp-netns.lo nmp-object.lo \ + wifi-utils-nl80211.lo wifi-utils.lo nm-fake-rdisc.lo \ + nm-lndp-rdisc.lo nm-rdisc.lo nm-route-manager.lo \ + nm-exported-object.lo nm-ip4-config.lo nm-ip6-config.lo \ + nm-enum-types.lo nm-logging.lo nm-multi-index.lo \ + nm-core-utils.lo NetworkManagerUtils.lo $(am__objects_4) libnm_iface_helper_la_OBJECTS = $(am_libnm_iface_helper_la_OBJECTS) libsystemd_nm_la_DEPENDENCIES = $(am__DEPENDENCIES_1) -am_libsystemd_nm_la_OBJECTS = libsystemd_nm_la-nm-sd-adapt.lo \ - libsystemd_nm_la-alloc-util.lo libsystemd_nm_la-escape.lo \ +am_libsystemd_nm_la_OBJECTS = libsystemd_nm_la-nm-sd.lo \ + libsystemd_nm_la-nm-sd-adapt.lo libsystemd_nm_la-alloc-util.lo \ + libsystemd_nm_la-escape.lo libsystemd_nm_la-ether-addr-util.lo \ libsystemd_nm_la-fd-util.lo libsystemd_nm_la-fileio.lo \ libsystemd_nm_la-fs-util.lo libsystemd_nm_la-hash-funcs.lo \ libsystemd_nm_la-hashmap.lo libsystemd_nm_la-hexdecoct.lo \ @@ -348,6 +355,7 @@ am_libsystemd_nm_la_OBJECTS = libsystemd_nm_la-nm-sd-adapt.lo \ libsystemd_nm_la-mempool.lo libsystemd_nm_la-parse-util.lo \ libsystemd_nm_la-path-util.lo libsystemd_nm_la-prioq.lo \ libsystemd_nm_la-random-util.lo libsystemd_nm_la-siphash24.lo \ + libsystemd_nm_la-socket-util.lo \ libsystemd_nm_la-string-table.lo \ libsystemd_nm_la-string-util.lo libsystemd_nm_la-strv.lo \ libsystemd_nm_la-time-util.lo libsystemd_nm_la-utf8.lo \ @@ -358,17 +366,16 @@ am_libsystemd_nm_la_OBJECTS = libsystemd_nm_la-nm-sd-adapt.lo \ libsystemd_nm_la-dhcp-packet.lo \ libsystemd_nm_la-dhcp6-network.lo \ libsystemd_nm_la-dhcp6-option.lo \ - libsystemd_nm_la-lldp-internal.lo \ - libsystemd_nm_la-lldp-network.lo libsystemd_nm_la-lldp-port.lo \ - libsystemd_nm_la-lldp-tlv.lo \ + libsystemd_nm_la-lldp-neighbor.lo \ + libsystemd_nm_la-lldp-network.lo \ libsystemd_nm_la-network-internal.lo \ libsystemd_nm_la-sd-dhcp-client.lo \ libsystemd_nm_la-sd-dhcp-lease.lo \ libsystemd_nm_la-sd-dhcp6-client.lo \ libsystemd_nm_la-sd-dhcp6-lease.lo \ libsystemd_nm_la-sd-ipv4acd.lo libsystemd_nm_la-sd-ipv4ll.lo \ - libsystemd_nm_la-sd-lldp.lo libsystemd_nm_la-sd-id128.lo \ - libsystemd_nm_la-dns-domain.lo + libsystemd_nm_la-sd-lldp.lo libsystemd_nm_la-sd-event.lo \ + libsystemd_nm_la-sd-id128.lo libsystemd_nm_la-dns-domain.lo libsystemd_nm_la_OBJECTS = $(am_libsystemd_nm_la_OBJECTS) am__installdirs = "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(sbindir)" \ "$(DESTDIR)$(dbusservicedir)" @@ -852,6 +859,8 @@ SYSTEMD_NM_CFLAGS_PATHS = \ -I$(top_srcdir)/src/systemd libsystemd_nm_la_SOURCES = \ + systemd/nm-sd.c \ + systemd/nm-sd.h \ systemd/nm-sd-adapt.c \ systemd/nm-sd-adapt.h \ systemd/src/basic/alloc-util.c \ @@ -859,6 +868,8 @@ libsystemd_nm_la_SOURCES = \ systemd/src/basic/async.h \ systemd/src/basic/escape.c \ systemd/src/basic/escape.h \ + systemd/src/basic/ether-addr-util.c \ + systemd/src/basic/ether-addr-util.h \ systemd/src/basic/fd-util.c \ systemd/src/basic/fd-util.h \ systemd/src/basic/fileio.c \ @@ -894,6 +905,7 @@ libsystemd_nm_la_SOURCES = \ systemd/src/basic/set.h \ systemd/src/basic/siphash24.c \ systemd/src/basic/siphash24.h \ + systemd/src/basic/socket-util.c \ systemd/src/basic/socket-util.h \ systemd/src/basic/sparse-endian.h \ systemd/src/basic/stdio-util.h \ @@ -926,14 +938,11 @@ libsystemd_nm_la_SOURCES = \ systemd/src/libsystemd-network/dhcp6-network.c \ systemd/src/libsystemd-network/dhcp6-option.c \ systemd/src/libsystemd-network/dhcp6-protocol.h \ - systemd/src/libsystemd-network/lldp-internal.c \ systemd/src/libsystemd-network/lldp-internal.h \ + systemd/src/libsystemd-network/lldp-neighbor.c \ + systemd/src/libsystemd-network/lldp-neighbor.h \ systemd/src/libsystemd-network/lldp-network.c \ systemd/src/libsystemd-network/lldp-network.h \ - systemd/src/libsystemd-network/lldp-port.c \ - systemd/src/libsystemd-network/lldp-port.h \ - systemd/src/libsystemd-network/lldp-tlv.c \ - systemd/src/libsystemd-network/lldp-tlv.h \ systemd/src/libsystemd-network/lldp.h \ systemd/src/libsystemd-network/network-internal.c \ systemd/src/libsystemd-network/network-internal.h \ @@ -944,6 +953,7 @@ libsystemd_nm_la_SOURCES = \ systemd/src/libsystemd-network/sd-ipv4acd.c \ systemd/src/libsystemd-network/sd-ipv4ll.c \ systemd/src/libsystemd-network/sd-lldp.c \ + systemd/src/libsystemd/sd-event/sd-event.c \ systemd/src/libsystemd/sd-id128/sd-id128.c \ systemd/src/shared/dns-domain.c \ systemd/src/shared/dns-domain.h \ @@ -1048,8 +1058,10 @@ libNetworkManager_la_SOURCES = $(nm_device_headers) \ devices/nm-device-factory.h devices/nm-device-generic.c \ devices/nm-device-generic.h devices/nm-device-logging.h \ devices/nm-device-private.h dhcp-manager/nm-dhcp-client.c \ - dhcp-manager/nm-dhcp-client.h dhcp-manager/nm-dhcp-utils.c \ - dhcp-manager/nm-dhcp-utils.h dhcp-manager/nm-dhcp-listener.c \ + dhcp-manager/nm-dhcp-client.h \ + dhcp-manager/nm-dhcp-client-logging.h \ + dhcp-manager/nm-dhcp-utils.c dhcp-manager/nm-dhcp-utils.h \ + dhcp-manager/nm-dhcp-listener.c \ dhcp-manager/nm-dhcp-listener.h dhcp-manager/nm-dhcp-manager.c \ dhcp-manager/nm-dhcp-manager.h dns-manager/nm-dns-dnsmasq.c \ dns-manager/nm-dns-dnsmasq.h dns-manager/nm-dns-unbound.c \ @@ -1060,7 +1072,8 @@ libNetworkManager_la_SOURCES = $(nm_device_headers) \ dnsmasq-manager/nm-dnsmasq-manager.c \ dnsmasq-manager/nm-dnsmasq-manager.h \ dnsmasq-manager/nm-dnsmasq-utils.c \ - dnsmasq-manager/nm-dnsmasq-utils.h platform/nm-fake-platform.c \ + dnsmasq-manager/nm-dnsmasq-utils.h platform/nmp-netns.c \ + platform/nmp-netns.h platform/nm-fake-platform.c \ platform/nm-fake-platform.h platform/nm-linux-platform.c \ platform/nm-linux-platform.h platform/nm-platform.c \ platform/nm-platform.h platform/nm-platform-utils.c \ @@ -1130,6 +1143,8 @@ nm_enum_types_sources = $(filter-out \ %/nm-device-private.h \ %/nm-rdisc-private.h \ %/wifi-utils-private.h \ + %/nm-dhcp-client-logging.h \ + %/nm-device-logging.h \ , $(libNetworkManager_la_SOURCES)) BUILT_SOURCES = $(GLIB_GENERATED) @@ -1139,17 +1154,23 @@ libNetworkManager_la_LIBADD = \ $(GLIB_LIBS) $(GUDEV_LIBS) $(LIBNL_LIBS) $(SYSTEMD_LOGIN_LIBS) \ $(SYSTEMD_JOURNAL_LIBS) $(LIBNDP_LIBS) $(LIBDL) $(LIBM) \ $(SELINUX_LIBS) $(LIBAUDIT_LIBS) $(am__append_9) -NetworkManager_LDFLAGS = -rdynamic +NetworkManager_LDFLAGS = \ + -rdynamic \ + -Wl,--version-script="$(srcdir)/NetworkManager.ver" + ###################### libnm_iface_helper_la_SOURCES = dhcp-manager/nm-dhcp-client.c \ - dhcp-manager/nm-dhcp-client.h dhcp-manager/nm-dhcp-utils.c \ - dhcp-manager/nm-dhcp-utils.h dhcp-manager/nm-dhcp-manager.c \ - dhcp-manager/nm-dhcp-manager.h platform/nm-linux-platform.c \ - platform/nm-linux-platform.h platform/nm-platform.c \ - platform/nm-platform.h platform/nm-platform-utils.c \ - platform/nm-platform-utils.h platform/nmp-object.c \ - platform/nmp-object.h platform/wifi/wifi-utils-nl80211.c \ + dhcp-manager/nm-dhcp-client.h \ + dhcp-manager/nm-dhcp-client-logging.h \ + dhcp-manager/nm-dhcp-utils.c dhcp-manager/nm-dhcp-utils.h \ + dhcp-manager/nm-dhcp-manager.c dhcp-manager/nm-dhcp-manager.h \ + platform/nm-linux-platform.c platform/nm-linux-platform.h \ + platform/nm-platform.c platform/nm-platform.h \ + platform/nm-platform-utils.c platform/nm-platform-utils.h \ + platform/nmp-netns.c platform/nmp-netns.h \ + platform/nmp-object.c platform/nmp-object.h \ + platform/wifi/wifi-utils-nl80211.c \ platform/wifi/wifi-utils-nl80211.h \ platform/wifi/wifi-utils-private.h platform/wifi/wifi-utils.c \ platform/wifi/wifi-utils.h rdisc/nm-fake-rdisc.c \ @@ -1197,7 +1218,8 @@ dbusservicedir = $(DBUS_SYS_DIR) dbusservice_DATA = org.freedesktop.NetworkManager.conf EXTRA_DIST = \ $(dbusservice_DATA) \ - $(NetworkManager_DATA) + $(NetworkManager_DATA) \ + NetworkManager.ver rundir = $(runstatedir)/NetworkManager statedir = $(localstatedir)/lib/NetworkManager @@ -1387,6 +1409,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-dhcp6-option.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-dns-domain.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-escape.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-ether-addr-util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-fd-util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-fileio.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-fs-util.Plo@am__quote@ @@ -1396,13 +1419,12 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-hostname-util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-in-addr-util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-io-util.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-lldp-internal.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-lldp-neighbor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-lldp-network.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-lldp-port.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-lldp-tlv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-mempool.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-network-internal.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-nm-sd-adapt.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-nm-sd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-parse-util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-path-util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-prioq.Plo@am__quote@ @@ -1411,11 +1433,13 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-sd-dhcp-lease.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-sd-dhcp6-client.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-sd-dhcp6-lease.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-sd-event.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-sd-id128.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-sd-ipv4acd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-sd-ipv4ll.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-sd-lldp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-siphash24.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-socket-util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-string-table.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-string-util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystemd_nm_la-strv.Plo@am__quote@ @@ -1508,6 +1532,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-supplicant-settings-verify.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-vpn-connection.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-vpn-manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nmp-netns.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nmp-object.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reader.Plo@am__quote@ @@ -1671,6 +1696,13 @@ nm-dnsmasq-utils.lo: dnsmasq-manager/nm-dnsmasq-utils.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-dnsmasq-utils.lo `test -f 'dnsmasq-manager/nm-dnsmasq-utils.c' || echo '$(srcdir)/'`dnsmasq-manager/nm-dnsmasq-utils.c +nmp-netns.lo: platform/nmp-netns.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nmp-netns.lo -MD -MP -MF $(DEPDIR)/nmp-netns.Tpo -c -o nmp-netns.lo `test -f 'platform/nmp-netns.c' || echo '$(srcdir)/'`platform/nmp-netns.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nmp-netns.Tpo $(DEPDIR)/nmp-netns.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='platform/nmp-netns.c' object='nmp-netns.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nmp-netns.lo `test -f 'platform/nmp-netns.c' || echo '$(srcdir)/'`platform/nmp-netns.c + nm-fake-platform.lo: platform/nm-fake-platform.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-fake-platform.lo -MD -MP -MF $(DEPDIR)/nm-fake-platform.Tpo -c -o nm-fake-platform.lo `test -f 'platform/nm-fake-platform.c' || echo '$(srcdir)/'`platform/nm-fake-platform.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-fake-platform.Tpo $(DEPDIR)/nm-fake-platform.Plo @@ -1874,6 +1906,13 @@ wifi-utils-wext.lo: platform/wifi/wifi-utils-wext.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o wifi-utils-wext.lo `test -f 'platform/wifi/wifi-utils-wext.c' || echo '$(srcdir)/'`platform/wifi/wifi-utils-wext.c +libsystemd_nm_la-nm-sd.lo: systemd/nm-sd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsystemd_nm_la-nm-sd.lo -MD -MP -MF $(DEPDIR)/libsystemd_nm_la-nm-sd.Tpo -c -o libsystemd_nm_la-nm-sd.lo `test -f 'systemd/nm-sd.c' || echo '$(srcdir)/'`systemd/nm-sd.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsystemd_nm_la-nm-sd.Tpo $(DEPDIR)/libsystemd_nm_la-nm-sd.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='systemd/nm-sd.c' object='libsystemd_nm_la-nm-sd.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsystemd_nm_la-nm-sd.lo `test -f 'systemd/nm-sd.c' || echo '$(srcdir)/'`systemd/nm-sd.c + libsystemd_nm_la-nm-sd-adapt.lo: systemd/nm-sd-adapt.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsystemd_nm_la-nm-sd-adapt.lo -MD -MP -MF $(DEPDIR)/libsystemd_nm_la-nm-sd-adapt.Tpo -c -o libsystemd_nm_la-nm-sd-adapt.lo `test -f 'systemd/nm-sd-adapt.c' || echo '$(srcdir)/'`systemd/nm-sd-adapt.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsystemd_nm_la-nm-sd-adapt.Tpo $(DEPDIR)/libsystemd_nm_la-nm-sd-adapt.Plo @@ -1895,6 +1934,13 @@ libsystemd_nm_la-escape.lo: systemd/src/basic/escape.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsystemd_nm_la-escape.lo `test -f 'systemd/src/basic/escape.c' || echo '$(srcdir)/'`systemd/src/basic/escape.c +libsystemd_nm_la-ether-addr-util.lo: systemd/src/basic/ether-addr-util.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsystemd_nm_la-ether-addr-util.lo -MD -MP -MF $(DEPDIR)/libsystemd_nm_la-ether-addr-util.Tpo -c -o libsystemd_nm_la-ether-addr-util.lo `test -f 'systemd/src/basic/ether-addr-util.c' || echo '$(srcdir)/'`systemd/src/basic/ether-addr-util.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsystemd_nm_la-ether-addr-util.Tpo $(DEPDIR)/libsystemd_nm_la-ether-addr-util.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='systemd/src/basic/ether-addr-util.c' object='libsystemd_nm_la-ether-addr-util.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsystemd_nm_la-ether-addr-util.lo `test -f 'systemd/src/basic/ether-addr-util.c' || echo '$(srcdir)/'`systemd/src/basic/ether-addr-util.c + libsystemd_nm_la-fd-util.lo: systemd/src/basic/fd-util.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsystemd_nm_la-fd-util.lo -MD -MP -MF $(DEPDIR)/libsystemd_nm_la-fd-util.Tpo -c -o libsystemd_nm_la-fd-util.lo `test -f 'systemd/src/basic/fd-util.c' || echo '$(srcdir)/'`systemd/src/basic/fd-util.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsystemd_nm_la-fd-util.Tpo $(DEPDIR)/libsystemd_nm_la-fd-util.Plo @@ -2000,6 +2046,13 @@ libsystemd_nm_la-siphash24.lo: systemd/src/basic/siphash24.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsystemd_nm_la-siphash24.lo `test -f 'systemd/src/basic/siphash24.c' || echo '$(srcdir)/'`systemd/src/basic/siphash24.c +libsystemd_nm_la-socket-util.lo: systemd/src/basic/socket-util.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsystemd_nm_la-socket-util.lo -MD -MP -MF $(DEPDIR)/libsystemd_nm_la-socket-util.Tpo -c -o libsystemd_nm_la-socket-util.lo `test -f 'systemd/src/basic/socket-util.c' || echo '$(srcdir)/'`systemd/src/basic/socket-util.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsystemd_nm_la-socket-util.Tpo $(DEPDIR)/libsystemd_nm_la-socket-util.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='systemd/src/basic/socket-util.c' object='libsystemd_nm_la-socket-util.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsystemd_nm_la-socket-util.lo `test -f 'systemd/src/basic/socket-util.c' || echo '$(srcdir)/'`systemd/src/basic/socket-util.c + libsystemd_nm_la-string-table.lo: systemd/src/basic/string-table.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsystemd_nm_la-string-table.lo -MD -MP -MF $(DEPDIR)/libsystemd_nm_la-string-table.Tpo -c -o libsystemd_nm_la-string-table.lo `test -f 'systemd/src/basic/string-table.c' || echo '$(srcdir)/'`systemd/src/basic/string-table.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsystemd_nm_la-string-table.Tpo $(DEPDIR)/libsystemd_nm_la-string-table.Plo @@ -2091,12 +2144,12 @@ libsystemd_nm_la-dhcp6-option.lo: systemd/src/libsystemd-network/dhcp6-option.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsystemd_nm_la-dhcp6-option.lo `test -f 'systemd/src/libsystemd-network/dhcp6-option.c' || echo '$(srcdir)/'`systemd/src/libsystemd-network/dhcp6-option.c -libsystemd_nm_la-lldp-internal.lo: systemd/src/libsystemd-network/lldp-internal.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsystemd_nm_la-lldp-internal.lo -MD -MP -MF $(DEPDIR)/libsystemd_nm_la-lldp-internal.Tpo -c -o libsystemd_nm_la-lldp-internal.lo `test -f 'systemd/src/libsystemd-network/lldp-internal.c' || echo '$(srcdir)/'`systemd/src/libsystemd-network/lldp-internal.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsystemd_nm_la-lldp-internal.Tpo $(DEPDIR)/libsystemd_nm_la-lldp-internal.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='systemd/src/libsystemd-network/lldp-internal.c' object='libsystemd_nm_la-lldp-internal.lo' libtool=yes @AMDEPBACKSLASH@ +libsystemd_nm_la-lldp-neighbor.lo: systemd/src/libsystemd-network/lldp-neighbor.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsystemd_nm_la-lldp-neighbor.lo -MD -MP -MF $(DEPDIR)/libsystemd_nm_la-lldp-neighbor.Tpo -c -o libsystemd_nm_la-lldp-neighbor.lo `test -f 'systemd/src/libsystemd-network/lldp-neighbor.c' || echo '$(srcdir)/'`systemd/src/libsystemd-network/lldp-neighbor.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsystemd_nm_la-lldp-neighbor.Tpo $(DEPDIR)/libsystemd_nm_la-lldp-neighbor.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='systemd/src/libsystemd-network/lldp-neighbor.c' object='libsystemd_nm_la-lldp-neighbor.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsystemd_nm_la-lldp-internal.lo `test -f 'systemd/src/libsystemd-network/lldp-internal.c' || echo '$(srcdir)/'`systemd/src/libsystemd-network/lldp-internal.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsystemd_nm_la-lldp-neighbor.lo `test -f 'systemd/src/libsystemd-network/lldp-neighbor.c' || echo '$(srcdir)/'`systemd/src/libsystemd-network/lldp-neighbor.c libsystemd_nm_la-lldp-network.lo: systemd/src/libsystemd-network/lldp-network.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsystemd_nm_la-lldp-network.lo -MD -MP -MF $(DEPDIR)/libsystemd_nm_la-lldp-network.Tpo -c -o libsystemd_nm_la-lldp-network.lo `test -f 'systemd/src/libsystemd-network/lldp-network.c' || echo '$(srcdir)/'`systemd/src/libsystemd-network/lldp-network.c @@ -2105,20 +2158,6 @@ libsystemd_nm_la-lldp-network.lo: systemd/src/libsystemd-network/lldp-network.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsystemd_nm_la-lldp-network.lo `test -f 'systemd/src/libsystemd-network/lldp-network.c' || echo '$(srcdir)/'`systemd/src/libsystemd-network/lldp-network.c -libsystemd_nm_la-lldp-port.lo: systemd/src/libsystemd-network/lldp-port.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsystemd_nm_la-lldp-port.lo -MD -MP -MF $(DEPDIR)/libsystemd_nm_la-lldp-port.Tpo -c -o libsystemd_nm_la-lldp-port.lo `test -f 'systemd/src/libsystemd-network/lldp-port.c' || echo '$(srcdir)/'`systemd/src/libsystemd-network/lldp-port.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsystemd_nm_la-lldp-port.Tpo $(DEPDIR)/libsystemd_nm_la-lldp-port.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='systemd/src/libsystemd-network/lldp-port.c' object='libsystemd_nm_la-lldp-port.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsystemd_nm_la-lldp-port.lo `test -f 'systemd/src/libsystemd-network/lldp-port.c' || echo '$(srcdir)/'`systemd/src/libsystemd-network/lldp-port.c - -libsystemd_nm_la-lldp-tlv.lo: systemd/src/libsystemd-network/lldp-tlv.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsystemd_nm_la-lldp-tlv.lo -MD -MP -MF $(DEPDIR)/libsystemd_nm_la-lldp-tlv.Tpo -c -o libsystemd_nm_la-lldp-tlv.lo `test -f 'systemd/src/libsystemd-network/lldp-tlv.c' || echo '$(srcdir)/'`systemd/src/libsystemd-network/lldp-tlv.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsystemd_nm_la-lldp-tlv.Tpo $(DEPDIR)/libsystemd_nm_la-lldp-tlv.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='systemd/src/libsystemd-network/lldp-tlv.c' object='libsystemd_nm_la-lldp-tlv.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsystemd_nm_la-lldp-tlv.lo `test -f 'systemd/src/libsystemd-network/lldp-tlv.c' || echo '$(srcdir)/'`systemd/src/libsystemd-network/lldp-tlv.c - libsystemd_nm_la-network-internal.lo: systemd/src/libsystemd-network/network-internal.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsystemd_nm_la-network-internal.lo -MD -MP -MF $(DEPDIR)/libsystemd_nm_la-network-internal.Tpo -c -o libsystemd_nm_la-network-internal.lo `test -f 'systemd/src/libsystemd-network/network-internal.c' || echo '$(srcdir)/'`systemd/src/libsystemd-network/network-internal.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsystemd_nm_la-network-internal.Tpo $(DEPDIR)/libsystemd_nm_la-network-internal.Plo @@ -2175,6 +2214,13 @@ libsystemd_nm_la-sd-lldp.lo: systemd/src/libsystemd-network/sd-lldp.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsystemd_nm_la-sd-lldp.lo `test -f 'systemd/src/libsystemd-network/sd-lldp.c' || echo '$(srcdir)/'`systemd/src/libsystemd-network/sd-lldp.c +libsystemd_nm_la-sd-event.lo: systemd/src/libsystemd/sd-event/sd-event.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsystemd_nm_la-sd-event.lo -MD -MP -MF $(DEPDIR)/libsystemd_nm_la-sd-event.Tpo -c -o libsystemd_nm_la-sd-event.lo `test -f 'systemd/src/libsystemd/sd-event/sd-event.c' || echo '$(srcdir)/'`systemd/src/libsystemd/sd-event/sd-event.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsystemd_nm_la-sd-event.Tpo $(DEPDIR)/libsystemd_nm_la-sd-event.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='systemd/src/libsystemd/sd-event/sd-event.c' object='libsystemd_nm_la-sd-event.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsystemd_nm_la-sd-event.lo `test -f 'systemd/src/libsystemd/sd-event/sd-event.c' || echo '$(srcdir)/'`systemd/src/libsystemd/sd-event/sd-event.c + libsystemd_nm_la-sd-id128.lo: systemd/src/libsystemd/sd-id128/sd-id128.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystemd_nm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsystemd_nm_la-sd-id128.lo -MD -MP -MF $(DEPDIR)/libsystemd_nm_la-sd-id128.Tpo -c -o libsystemd_nm_la-sd-id128.lo `test -f 'systemd/src/libsystemd/sd-id128/sd-id128.c' || echo '$(srcdir)/'`systemd/src/libsystemd/sd-id128/sd-id128.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsystemd_nm_la-sd-id128.Tpo $(DEPDIR)/libsystemd_nm_la-sd-id128.Plo @@ -2708,7 +2754,7 @@ include $(GLIB_MAKEFILE) @GNOME_CODE_COVERAGE_RULES@ install-data-hook: - $(mkinstalldirs) -m 0700 $(DESTDIR)$(rundir) + $(mkinstalldirs) -m 0755 $(DESTDIR)$(rundir) $(mkinstalldirs) -m 0700 $(DESTDIR)$(statedir) $(mkinstalldirs) -m 0755 $(DESTDIR)$(pkglibdir) diff --git a/src/NetworkManager.ver b/src/NetworkManager.ver new file mode 100644 index 00000000..b4397b9c --- /dev/null +++ b/src/NetworkManager.ver @@ -0,0 +1,9 @@ +{ +global: + nm*; + _nm*; + NM*; + _NM*; +local: + *; +}; diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index 50fe4efd..09ed25c5 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -127,7 +127,8 @@ get_new_connection_name (const GSList *existing, } static char * -get_new_connection_ifname (const GSList *existing, +get_new_connection_ifname (NMPlatform *platform, + const GSList *existing, const char *prefix) { int i; @@ -138,7 +139,7 @@ get_new_connection_ifname (const GSList *existing, for (i = 0; i < 500; i++) { name = g_strdup_printf ("%s%d", prefix, i); - if (nm_platform_link_get_by_ifname (NM_PLATFORM_GET, name)) + if (nm_platform_link_get_by_ifname (platform, name)) goto next; for (iter = existing, found = FALSE; iter; iter = g_slist_next (iter)) { @@ -205,7 +206,8 @@ nm_utils_get_ip_config_method (NMConnection *connection, } void -nm_utils_complete_generic (NMConnection *connection, +nm_utils_complete_generic (NMPlatform *platform, + NMConnection *connection, const char *ctype, const GSList *existing, const char *preferred_id, @@ -241,7 +243,7 @@ nm_utils_complete_generic (NMConnection *connection, /* Add an interface name, if requested */ if (ifname_prefix && !nm_setting_connection_get_interface_name (s_con)) { - ifname = get_new_connection_ifname (existing, ifname_prefix); + ifname = get_new_connection_ifname (platform, existing, ifname_prefix); g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_INTERFACE_NAME, ifname, NULL); g_free (ifname); } diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h index b3c384da..9b5b9106 100644 --- a/src/NetworkManagerUtils.h +++ b/src/NetworkManagerUtils.h @@ -28,7 +28,8 @@ const char *nm_utils_get_shared_wifi_permission (NMConnection *connection); -void nm_utils_complete_generic (NMConnection *connection, +void nm_utils_complete_generic (NMPlatform *platform, + NMConnection *connection, const char *ctype, const GSList *existing, const char *preferred_id, diff --git a/src/devices/adsl/nm-atm-manager.c b/src/devices/adsl/nm-atm-manager.c index a3fa4901..67085752 100644 --- a/src/devices/adsl/nm-atm-manager.c +++ b/src/devices/adsl/nm-atm-manager.c @@ -117,7 +117,7 @@ adsl_add (NMAtmManager *self, GUdevDevice *udev_device) nm_log_dbg (LOGD_HW, "(%s): found ATM device", ifname); atm_index_path = g_strdup_printf ("/sys/class/atm/%s/atmindex", - ASSERT_VALID_PATH_COMPONENT (ifname)); + NM_ASSERT_VALID_PATH_COMPONENT (ifname)); atm_index = (int) nm_platform_sysctl_get_int_checked (NM_PLATFORM_GET, atm_index_path, 10, 0, G_MAXINT, diff --git a/src/devices/adsl/nm-device-adsl.c b/src/devices/adsl/nm-device-adsl.c index e7a91e0a..ebb7a319 100644 --- a/src/devices/adsl/nm-device-adsl.c +++ b/src/devices/adsl/nm-device-adsl.c @@ -125,7 +125,8 @@ complete_connection (NMDevice *device, if (s_adsl && !nm_setting_verify (NM_SETTING (s_adsl), NULL, error)) return FALSE; - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_ADSL_SETTING_NAME, existing_connections, NULL, @@ -535,7 +536,7 @@ carrier_update_cb (gpointer user_data) char *path; path = g_strdup_printf ("/sys/class/atm/%s/carrier", - ASSERT_VALID_PATH_COMPONENT (nm_device_get_iface (NM_DEVICE (self)))); + NM_ASSERT_VALID_PATH_COMPONENT (nm_device_get_iface (NM_DEVICE (self)))); carrier = (int) nm_platform_sysctl_get_int_checked (NM_PLATFORM_GET, path, 10, 0, 1, -1); g_free (path); diff --git a/src/devices/bluetooth/nm-bluez-device.c b/src/devices/bluetooth/nm-bluez-device.c index 71226813..a009746d 100644 --- a/src/devices/bluetooth/nm-bluez-device.c +++ b/src/devices/bluetooth/nm-bluez-device.c @@ -246,9 +246,8 @@ pan_connection_check_create (NMBluezDevice *self) priv->pan_connection = added; nm_log_dbg (LOGD_BT, "bluez[%s] added new Bluetooth connection for NAP device: '%s' (%s)", priv->path, id, uuid); } else { - nm_log_warn (LOGD_BT, "bluez[%s] couldn't add new Bluetooth connection for NAP device: '%s' (%s): %d / %s", - priv->path, id, uuid, error ? error->code : -1, - (error && error->message) ? error->message : "(unknown)"); + nm_log_warn (LOGD_BT, "bluez[%s] couldn't add new Bluetooth connection for NAP device: '%s' (%s): %s", + priv->path, id, uuid, error->message); g_clear_error (&error); } diff --git a/src/devices/bluetooth/nm-bluez-manager.c b/src/devices/bluetooth/nm-bluez-manager.c index f66b5abe..766ecc0a 100644 --- a/src/devices/bluetooth/nm-bluez-manager.c +++ b/src/devices/bluetooth/nm-bluez-manager.c @@ -38,6 +38,16 @@ #include "nm-platform.h" #include "nm-dbus-compat.h" +#define _NMLOG_DOMAIN LOGD_BT +#define _NMLOG_PREFIX_NAME "bluez" +#define _NMLOG(level, ...) \ + G_STMT_START { \ + nm_log ((level), _NMLOG_DOMAIN, \ + "%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME": " \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } G_STMT_END + typedef struct { int bluez_version; @@ -146,12 +156,12 @@ manager_bdaddr_added_cb (NMBluez4Manager *bluez_mgr, if (!device) return; - nm_log_info (LOGD_BT, "BT device %s (%s) added (%s%s%s)", - name, - bdaddr, - has_dun ? "DUN" : "", - has_dun && has_nap ? " " : "", - has_nap ? "NAP" : ""); + _LOGI ("BT device %s (%s) added (%s%s%s)", + name, + bdaddr, + has_dun ? "DUN" : "", + has_dun && has_nap ? " " : "", + has_nap ? "NAP" : ""); g_signal_emit_by_name (self, NM_DEVICE_FACTORY_DEVICE_ADDED, device); g_object_unref (device); } @@ -163,7 +173,7 @@ setup_version_number (NMBluezManager *self, int bluez_version) g_return_if_fail (!priv->bluez_version); - nm_log_info (LOGD_BT, "use BlueZ version %d", bluez_version); + _LOGI ("use BlueZ version %d", bluez_version); priv->bluez_version = bluez_version; @@ -235,7 +245,7 @@ check_bluez_and_try_setup_final_step (NMBluezManager *self, int bluez_version, c setup_bluez5 (self); break; default: - nm_log_dbg (LOGD_BT, "detecting BlueZ version failed: %s", reason); + _LOGD ("detecting BlueZ version failed: %s", reason); /* cancel current attempts to detect the version. */ cleanup_checking (self, FALSE); diff --git a/src/devices/bluetooth/nm-bluez4-adapter.c b/src/devices/bluetooth/nm-bluez4-adapter.c index deeebcb6..9d8fd210 100644 --- a/src/devices/bluetooth/nm-bluez4-adapter.c +++ b/src/devices/bluetooth/nm-bluez4-adapter.c @@ -203,7 +203,7 @@ get_properties_cb (GObject *proxy, GAsyncResult *result, gpointer user_data) properties = g_variant_get_child_value (ret, 0); - g_variant_lookup (properties, "Address", "s", &priv->address); + (void) g_variant_lookup (properties, "Address", "s", &priv->address); if (g_variant_lookup (properties, "Devices", "^ao", &devices)) { for (i = 0; devices[i]; i++) device_created (priv->proxy, devices[i], self); diff --git a/src/devices/bluetooth/nm-bluez5-manager.c b/src/devices/bluetooth/nm-bluez5-manager.c index e44e87d8..66d171bf 100644 --- a/src/devices/bluetooth/nm-bluez5-manager.c +++ b/src/devices/bluetooth/nm-bluez5-manager.c @@ -213,6 +213,7 @@ get_managed_objects_cb (GDBusProxy *proxy, G_VARIANT_TYPE_DICTIONARY)) { device_added (proxy, path, self); } + g_variant_unref (ifaces); } g_variant_unref (variant); @@ -231,8 +232,7 @@ on_proxy_acquired (GObject *object, priv->proxy = g_dbus_proxy_new_for_bus_finish (res, &error); if (!priv->proxy) { - nm_log_warn (LOGD_BT, "Couldn't acquire object manager proxy: %s", - error && error->message ? error->message : "(unknown)"); + nm_log_warn (LOGD_BT, "Couldn't acquire object manager proxy: %s", error->message); g_clear_error (&error); return; } diff --git a/src/devices/bluetooth/nm-bluez5-manager.h b/src/devices/bluetooth/nm-bluez5-manager.h index ae5512f8..1c531090 100644 --- a/src/devices/bluetooth/nm-bluez5-manager.h +++ b/src/devices/bluetooth/nm-bluez5-manager.h @@ -1,4 +1,4 @@ -/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ +/* -*- 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 diff --git a/src/devices/bluetooth/nm-device-bt.c b/src/devices/bluetooth/nm-device-bt.c index e151b795..eef4ed0a 100644 --- a/src/devices/bluetooth/nm-device-bt.c +++ b/src/devices/bluetooth/nm-device-bt.c @@ -20,12 +20,13 @@ #include "nm-default.h" +#include "nm-device-bt.h" + #include <stdio.h> #include <string.h> #include "nm-bluez-common.h" #include "nm-bluez-device.h" -#include "nm-device-bt.h" #include "nm-device-private.h" #include "ppp-manager/nm-ppp-manager.h" #include "nm-setting-connection.h" @@ -39,6 +40,7 @@ #include "nm-utils.h" #include "nm-bt-error.h" #include "nm-bt-enum-types.h" +#include "nm-platform.h" #include "nmdbus-device-bt.h" @@ -315,7 +317,8 @@ complete_connection (NMDevice *device, return FALSE; } - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_BLUETOOTH_SETTING_NAME, existing_connections, preferred, @@ -497,8 +500,8 @@ modem_ip4_config_result (NMModem *modem, if (error) { _LOGW (LOGD_MB | LOGD_IP4 | LOGD_BT, - "retrieving IP4 configuration failed: (%d) %s", - error->code, error->message ? error->message : "(unknown)"); + "retrieving IP4 configuration failed: %s", + error->message); nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); } else @@ -728,8 +731,7 @@ bluez_connect_cb (GObject *object, res, &error); if (!device) { - _LOGW (LOGD_BT, "Error connecting with bluez: %s", - error && error->message ? error->message : "(unknown)"); + _LOGW (LOGD_BT, "Error connecting with bluez: %s", error->message); g_clear_error (&error); nm_device_state_changed (NM_DEVICE (self), diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c index cef104e6..b88b2511 100644 --- a/src/devices/nm-device-bond.c +++ b/src/devices/nm-device-bond.c @@ -97,7 +97,8 @@ complete_connection (NMDevice *device, { NMSettingBond *s_bond; - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_BOND_SETTING_NAME, existing_connections, NULL, diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c index cc72b003..c35d2863 100644 --- a/src/devices/nm-device-bridge.c +++ b/src/devices/nm-device-bridge.c @@ -103,7 +103,8 @@ complete_connection (NMDevice *device, { NMSettingBridge *s_bridge; - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_BRIDGE_SETTING_NAME, existing_connections, NULL, diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c index 2fb84276..6225ae7b 100644 --- a/src/devices/nm-device-ethernet.c +++ b/src/devices/nm-device-ethernet.c @@ -158,7 +158,7 @@ _update_s390_subchannels (NMDeviceEthernet *self) dev = (GUdevDevice *) 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, str_if_set (nm_device_get_iface (NM_DEVICE (self)), "(null)")); + ifindex, nm_device_get_iface (NM_DEVICE (self)) ?: "(null)"); goto out; } g_object_ref (dev); @@ -177,7 +177,7 @@ _update_s390_subchannels (NMDeviceEthernet *self) dir = g_dir_open (parent_path, 0, &error); if (!dir) { _LOGW (LOGD_DEVICE | LOGD_HW, "failed to open directory '%s': %s", - parent_path, error && error->message ? error->message : "(unknown)"); + parent_path, error->message); g_clear_error (&error); goto out; } @@ -597,13 +597,13 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface, if (!success) { _LOGE (LOGD_DEVICE | LOGD_ETHER, "Activation: (ethernet) couldn't send security configuration to the supplicant: %s", - error ? error->message : "<BUG>"); + error->message); g_clear_error (&error); } } else { _LOGE (LOGD_DEVICE | LOGD_ETHER, "Activation: (ethernet) couldn't build security configuration: %s", - error ? error->message : "<BUG>"); + error->message); g_clear_error (&error); } @@ -721,7 +721,7 @@ supplicant_connection_timeout_cb (gpointer user_data) NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); NMDevice *device = NM_DEVICE (self); NMActRequest *req; - NMConnection *connection; + NMSettingsConnection *connection; guint64 timestamp = 0; gboolean new_secrets = TRUE; @@ -737,14 +737,14 @@ supplicant_connection_timeout_cb (gpointer user_data) req = nm_device_get_act_request (device); g_assert (req); - connection = nm_act_request_get_applied_connection (req); + connection = nm_act_request_get_settings_connection (req); g_assert (connection); /* Ask for new secrets only if we've never activated this connection * before. If we've connected before, don't bother the user with dialogs, * just retry or fail, and if we never connect the user can fix the * password somewhere else. */ - if (nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (connection), ×tamp)) + if (nm_settings_connection_get_timestamp (connection, ×tamp)) new_secrets = !timestamp; if (handle_auth_or_fail (self, req, new_secrets) == NM_ACT_STAGE_RETURN_POSTPONE) @@ -1187,7 +1187,7 @@ wake_on_lan_enable (NMDevice *device) } wol = NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE; found: - return nmp_utils_ethtool_set_wake_on_lan (nm_device_get_iface (device), wol, password); + return nm_platform_ethtool_set_wake_on_lan (NM_PLATFORM_GET, nm_device_get_iface (device), wol, password); } /****************************************************************/ @@ -1388,7 +1388,8 @@ complete_connection (NMDevice *device, /* Default to an ethernet-only connection, but if a PPPoE setting was given * then PPPoE should be our connection type. */ - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, s_pppoe ? NM_SETTING_PPPOE_SETTING_NAME : NM_SETTING_WIRED_SETTING_NAME, existing_connections, NULL, @@ -1498,6 +1499,11 @@ update_connection (NMDevice *device, NMConnection *connection) nm_connection_add_setting (connection, (NMSetting *) s_wired); } + g_object_set (nm_connection_get_setting_connection (connection), + NM_SETTING_CONNECTION_TYPE, nm_connection_get_setting_pppoe (connection) + ? NM_SETTING_PPPOE_SETTING_NAME + : NM_SETTING_WIRED_SETTING_NAME, NULL); + /* If the device reports a permanent address, use that for the MAC address * and the current MAC, if different, is the cloned MAC. */ @@ -1533,7 +1539,7 @@ get_link_speed (NMDevice *device) NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); guint32 speed; - if (!nmp_utils_ethtool_get_link_speed (nm_device_get_iface (device), &speed)) + if (!nm_platform_ethtool_get_link_speed (NM_PLATFORM_GET, nm_device_get_iface (device), &speed)) return; if (priv->speed == speed) return; diff --git a/src/devices/nm-device-factory.c b/src/devices/nm-device-factory.c index bd0ec002..5ce4333f 100644 --- a/src/devices/nm-device-factory.c +++ b/src/devices/nm-device-factory.c @@ -355,7 +355,7 @@ read_device_factory_paths (void) if (!dir) { nm_log_warn (LOGD_HW, "device plugin: failed to open directory %s: %s", NMPLUGINDIR, - (error && error->message) ? error->message : "(unknown)"); + error->message); g_clear_error (&error); return NULL; } @@ -499,7 +499,7 @@ nm_device_factory_manager_load_factories (NMDeviceFactoryManagerFactoryFunc call factory = create_func (&error); if (!factory) { nm_log_warn (LOGD_HW, "(%s): failed to initialize device factory: %s", - item, error ? error->message : "unknown"); + item, NM_G_ERROR_MSG (error)); g_clear_error (&error); g_module_close (plugin); continue; diff --git a/src/devices/nm-device-infiniband.c b/src/devices/nm-device-infiniband.c index 79bcb57c..a27af314 100644 --- a/src/devices/nm-device-infiniband.c +++ b/src/devices/nm-device-infiniband.c @@ -85,7 +85,7 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) transport_mode = nm_setting_infiniband_get_transport_mode (s_infiniband); mode_path = g_strdup_printf ("/sys/class/net/%s/mode", - ASSERT_VALID_PATH_COMPONENT (nm_device_get_iface (dev))); + NM_ASSERT_VALID_PATH_COMPONENT (nm_device_get_iface (dev))); if (!g_file_test (mode_path, G_FILE_TEST_EXISTS)) { g_free (mode_path); @@ -166,7 +166,8 @@ complete_connection (NMDevice *device, const char *setting_mac; const char *hw_address; - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_INFINIBAND_SETTING_NAME, existing_connections, NULL, diff --git a/src/devices/nm-device-ip-tunnel.c b/src/devices/nm-device-ip-tunnel.c index 0ba813eb..089b1035 100644 --- a/src/devices/nm-device-ip-tunnel.c +++ b/src/devices/nm-device-ip-tunnel.c @@ -338,7 +338,8 @@ complete_connection (NMDevice *device, { NMSettingIPTunnel *s_ip_tunnel; - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_IP_TUNNEL_SETTING_NAME, existing_connections, NULL, @@ -788,6 +789,12 @@ ip4_config_pre_commit (NMDevice *device, NMIP4Config *config) nm_ip4_config_set_mtu (config, mtu, NM_IP_CONFIG_SOURCE_USER); } +static NMDeviceCapabilities +get_generic_capabilities (NMDevice *dev) +{ + return NM_DEVICE_CAP_IS_SOFTWARE; +} + static void unrealize_notify (NMDevice *device) { @@ -876,6 +883,7 @@ nm_device_ip_tunnel_class_init (NMDeviceIPTunnelClass *klass) device_class->update_connection = update_connection; device_class->check_connection_compatible = check_connection_compatible; device_class->create_and_realize = create_and_realize; + device_class->get_generic_capabilities = get_generic_capabilities; device_class->ip4_config_pre_commit = ip4_config_pre_commit; device_class->realize_start_notify = realize_start_notify; device_class->unrealize_notify = unrealize_notify; diff --git a/src/devices/nm-device-logging.h b/src/devices/nm-device-logging.h index 6255d6f3..1be17073 100644 --- a/src/devices/nm-device-logging.h +++ b/src/devices/nm-device-logging.h @@ -34,9 +34,9 @@ _nm_device_log_self_to_device (t *self) \ #undef _NMLOG_ENABLED #define _NMLOG_ENABLED(level, domain) ( nm_logging_enabled ((level), (domain)) ) #define _NMLOG(level, domain, ...) \ - nm_log_obj ((level), (domain), (self), \ + nm_log_obj ((level), (domain), (self), "device", \ "(%s): " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - (self) ? str_if_set (nm_device_get_iface (_nm_device_log_self_to_device (self)), "(null)") : "(none)" \ + (self) ? (nm_device_get_iface (_nm_device_log_self_to_device (self)) ?: "(null)") : "(none)" \ _NM_UTILS_MACRO_REST(__VA_ARGS__)) #endif /* __NETWORKMANAGER_DEVICE_LOGGING_H__ */ diff --git a/src/devices/nm-device-macvlan.c b/src/devices/nm-device-macvlan.c index 2dc9d4f6..cd02cb8e 100644 --- a/src/devices/nm-device-macvlan.c +++ b/src/devices/nm-device-macvlan.c @@ -420,7 +420,8 @@ complete_connection (NMDevice *device, { NMSettingMacvlan *s_macvlan; - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_MACVLAN_SETTING_NAME, existing_connections, NULL, diff --git a/src/devices/nm-device-tun.c b/src/devices/nm-device-tun.c index a8ae3edc..eac2fb82 100644 --- a/src/devices/nm-device-tun.c +++ b/src/devices/nm-device-tun.c @@ -121,7 +121,8 @@ complete_connection (NMDevice *device, { NMSettingTun *s_tun; - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_TUN_SETTING_NAME, existing_connections, NULL, diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c index e6e3708b..4d606e9d 100644 --- a/src/devices/nm-device-vlan.c +++ b/src/devices/nm-device-vlan.c @@ -439,7 +439,8 @@ complete_connection (NMDevice *device, { NMSettingVlan *s_vlan; - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_VLAN_SETTING_NAME, existing_connections, NULL, diff --git a/src/devices/nm-device-vxlan.c b/src/devices/nm-device-vxlan.c index 79942458..d308d47a 100644 --- a/src/devices/nm-device-vxlan.c +++ b/src/devices/nm-device-vxlan.c @@ -365,7 +365,8 @@ complete_connection (NMDevice *device, { NMSettingVxlan *s_vxlan; - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_VXLAN_SETTING_NAME, existing_connections, NULL, diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index cdd3f7cb..529b3cd8 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -70,13 +70,6 @@ _LOG_DECLARE_SELF (NMDevice); #include "nmdbus-device.h" -static void ip_check_ping_watch_cb (GPid pid, gint status, gpointer user_data); -static gboolean ip_config_valid (NMDeviceState state); -static NMActStageReturn dhcp4_start (NMDevice *self, NMConnection *connection, NMDeviceStateReason *reason); -static gboolean dhcp6_start (NMDevice *self, gboolean wait_for_ll, NMDeviceStateReason *reason); -static void nm_device_start_ip_check (NMDevice *self); -static void realize_start_setup (NMDevice *self, const NMPlatformLink *plink); - G_DEFINE_ABSTRACT_TYPE (NMDevice, nm_device, NM_TYPE_EXPORTED_OBJECT) #define NM_DEVICE_GET_PRIVATE(o) ((o)->priv) @@ -414,6 +407,12 @@ static void _set_state_full (NMDevice *self, static gboolean queued_ip4_config_change (gpointer user_data); static gboolean queued_ip6_config_change (gpointer user_data); +static void ip_check_ping_watch_cb (GPid pid, gint status, gpointer user_data); +static gboolean ip_config_valid (NMDeviceState state); +static NMActStageReturn dhcp4_start (NMDevice *self, NMConnection *connection, NMDeviceStateReason *reason); +static gboolean dhcp6_start (NMDevice *self, gboolean wait_for_ll, NMDeviceStateReason *reason); +static void nm_device_start_ip_check (NMDevice *self); +static void realize_start_setup (NMDevice *self, const NMPlatformLink *plink); /***********************************************************/ @@ -1236,8 +1235,7 @@ update_dynamic_ip_setup (NMDevice *self) nm_lldp_listener_stop (priv->lldp_listener); addr = nm_platform_link_get_address (NM_PLATFORM_GET, priv->ifindex, &addr_length); - if (!nm_lldp_listener_start (priv->lldp_listener, nm_device_get_ifindex (self), - nm_device_get_iface (self), addr, addr_length, &error)) { + if (!nm_lldp_listener_start (priv->lldp_listener, nm_device_get_ifindex (self), &error)) { _LOGD (LOGD_DEVICE, "LLDP listener %p could not be restarted: %s", priv->lldp_listener, error->message); g_clear_error (&error); @@ -2883,7 +2881,7 @@ nm_device_generate_connection (NMDevice *self, NMDevice *master) &error)) { _LOGE (LOGD_DEVICE, "master device '%s' failed to update slave connection: %s", - nm_device_get_iface (master), error ? error->message : "(unknown error)"); + nm_device_get_iface (master), error->message); g_error_free (error); g_object_unref (connection); return NULL; @@ -3164,7 +3162,7 @@ recheck_available (gpointer user_data) } if (new_state > NM_DEVICE_STATE_UNKNOWN) { - _LOGD (LOGD_DEVICE, "device is %savailable, %s %s", + _LOGD (LOGD_DEVICE, "is %savailable, %s %s", now_available ? "" : "not ", new_state == NM_DEVICE_STATE_UNAVAILABLE ? "no change required for" : "will transition to", state_to_string (new_state == NM_DEVICE_STATE_UNAVAILABLE ? state : new_state)); @@ -3565,8 +3563,7 @@ activate_stage2_device_config (NMDevice *self) addr = nm_platform_link_get_address (NM_PLATFORM_GET, priv->ifindex, &addr_length); - if (nm_lldp_listener_start (priv->lldp_listener, nm_device_get_ifindex (self), - nm_device_get_iface (self), addr, addr_length, &error)) + if (nm_lldp_listener_start (priv->lldp_listener, nm_device_get_ifindex (self), &error)) _LOGD (LOGD_DEVICE, "LLDP listener %p started", priv->lldp_listener); else { _LOGD (LOGD_DEVICE, "LLDP listener %p could not be started: %s", @@ -4675,10 +4672,7 @@ reserve_shared_ip (NMDevice *self, NMSettingIPConfig *s_ip4, NMPlatformIP4Addres } } nm_platform_ip4_address_set_addr (address, start + count, 24); - - g_hash_table_insert (shared_ips, - GUINT_TO_POINTER (address->address), - GUINT_TO_POINTER (TRUE)); + g_hash_table_add (shared_ips, GUINT_TO_POINTER (address->address)); } return TRUE; @@ -5852,7 +5846,8 @@ 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_device_get_ip_ifindex (self), + 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), @@ -6631,7 +6626,7 @@ start_sharing (NMDevice *self, NMIP4Config *config) if (!nm_dnsmasq_manager_start (priv->dnsmasq_manager, config, &error)) { _LOGE (LOGD_SHARING, "share: (%s) failed to start dnsmasq: %s", - ip_iface, (error && error->message) ? error->message : "(unknown)"); + ip_iface, error->message); g_error_free (error); nm_act_request_set_shared (req, FALSE); return FALSE; @@ -7145,6 +7140,7 @@ nm_device_reactivate_ip4_config (NMDevice *self, if (priv->ip4_state != IP_NONE) { g_clear_object (&priv->con_ip4_config); + g_clear_object (&priv->ext_ip4_config); priv->con_ip4_config = nm_ip4_config_new (nm_device_get_ip_ifindex (self)); nm_ip4_config_merge_setting (priv->con_ip4_config, s_ip4_new, @@ -7175,6 +7171,7 @@ nm_device_reactivate_ip6_config (NMDevice *self, if (priv->ip6_state != IP_NONE) { g_clear_object (&priv->con_ip6_config); + g_clear_object (&priv->ext_ip6_config); priv->con_ip6_config = nm_ip6_config_new (nm_device_get_ip_ifindex (self)); nm_ip6_config_merge_setting (priv->con_ip6_config, s_ip6_new, @@ -7374,7 +7371,10 @@ impl_device_reapply (NMDevice *self, if (settings && g_variant_n_children (settings)) { /* New settings specified inline. */ - connection = nm_simple_connection_new_from_dbus (settings, &error); + connection = _nm_simple_connection_new_from_dbus (settings, + NM_SETTING_PARSE_FLAGS_STRICT + | NM_SETTING_PARSE_FLAGS_NORMALIZE, + &error); if (!connection) { g_prefix_error (&error, "The settings specified are invalid: "); nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, context, error->message); @@ -7740,7 +7740,7 @@ nm_device_queue_activation (NMDevice *self, NMActRequest *req) must_queue = _carrier_wait_check_act_request_must_queue (self, req); - if (!priv->act_request && !must_queue) { + if (!priv->act_request && !must_queue && nm_device_is_real (self)) { /* Just activate immediately */ if (!_device_activate (self, req)) g_assert_not_reached (); @@ -7926,9 +7926,10 @@ _replace_vpn_config_in_list (GSList **plist, GObject *old, GObject *new) { GSList *old_link; - /* Below, assert that we have an @old instance to replace and that - * @new is not yet tracked. But still, behave correctly in any - * case. */ + /* Below, assert that @new is not yet tracked, but still behave + * correctly in any case. Don't complain for missing @old since + * it could have been removed when the parent device became + * unmanaged. */ if ( old && (old_link = g_slist_find (*plist, old))) { @@ -7936,7 +7937,7 @@ _replace_vpn_config_in_list (GSList **plist, GObject *old, GObject *new) if (new) old_link->data = g_object_ref (new); else - *plist = g_slist_remove_link (*plist, old_link); + *plist = g_slist_delete_link (*plist, old_link); g_object_unref (old); } return TRUE; @@ -7947,12 +7948,9 @@ _replace_vpn_config_in_list (GSList **plist, GObject *old, GObject *new) *plist = g_slist_append (*plist, g_object_ref (new)); else g_return_val_if_reached (TRUE); - g_return_val_if_fail (!old, TRUE); return TRUE; } - /* return FALSE if both @old and @new are unset. */ - g_return_val_if_fail (!old, FALSE); return FALSE; } @@ -8434,7 +8432,7 @@ nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware) g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); - _LOGD (LOGD_HW, "bringing up device."); + _LOGD (LOGD_HW, "bringing up device"); if (NM_DEVICE_GET_CLASS (self)->bring_up) { if (!NM_DEVICE_GET_CLASS (self)->bring_up (self, no_firmware)) @@ -8508,7 +8506,7 @@ nm_device_take_down (NMDevice *self, gboolean block) g_return_if_fail (NM_IS_DEVICE (self)); - _LOGD (LOGD_HW, "taking down device."); + _LOGD (LOGD_HW, "taking down device"); if (NM_DEVICE_GET_CLASS (self)->take_down) { if (!NM_DEVICE_GET_CLASS (self)->take_down (self)) @@ -9668,14 +9666,13 @@ nm_device_recheck_available_connections (NMDevice *self) connection = NM_CONNECTION (iter->data); if (nm_device_check_connection_available (self, - connection, - NM_DEVICE_CHECK_CON_AVAILABLE_NONE, - NULL)) { + connection, + NM_DEVICE_CHECK_CON_AVAILABLE_NONE, + NULL)) { if (available_connections_add (self, connection)) changed = TRUE; - } else { - if (prune_list && g_hash_table_remove (prune_list, connection)) - changed = TRUE; + if (prune_list) + g_hash_table_remove (prune_list, connection); } } @@ -9697,39 +9694,55 @@ nm_device_recheck_available_connections (NMDevice *self) } /** - * nm_device_get_available_connections: + * nm_device_get_best_connection: * @self: the #NMDevice * @specific_object: a specific object path if any + * @error: reason why no connection was returned * - * Returns a list of connections available to activate on the device, taking - * into account any device-specific details given by @specific_object (like - * WiFi access point path). + * Returns a connection that's most suitable for user-initiated activation + * of a device, optionally with a given specific object. * - * Returns: caller-owned #GPtrArray of #NMConnections + * Returns: the #NMSettingsConnection or %NULL (setting an @error) */ -GPtrArray * -nm_device_get_available_connections (NMDevice *self, const char *specific_object) +NMSettingsConnection * +nm_device_get_best_connection (NMDevice *self, + const char *specific_object, + GError **error) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMSettingsConnection *connection = NULL; + NMSettingsConnection *candidate; + guint64 best_timestamp = 0; GHashTableIter iter; - guint num_available; - NMConnection *connection = NULL; - GPtrArray *array = NULL; - num_available = g_hash_table_size (priv->available_connections); - if (num_available > 0) { - array = g_ptr_array_sized_new (num_available); - g_hash_table_iter_init (&iter, priv->available_connections); - while (g_hash_table_iter_next (&iter, (gpointer) &connection, NULL)) { - /* If a specific object is given, only include connections that are - * compatible with it. - */ - if ( !specific_object /* << Optimization: we know that the connection is available without @specific_object. */ - || nm_device_check_connection_available (self, connection, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST, specific_object)) - g_ptr_array_add (array, connection); + g_hash_table_iter_init (&iter, priv->available_connections); + while (g_hash_table_iter_next (&iter, (gpointer) &candidate, NULL)) { + guint64 candidate_timestamp = 0; + + /* If a specific object is given, only include connections that are + * compatible with it. + */ + if ( specific_object /* << Optimization: we know that the connection is available without @specific_object. */ + && !nm_device_check_connection_available (self, + NM_CONNECTION (candidate), + _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST, + specific_object)) + continue; + + nm_settings_connection_get_timestamp (candidate, &candidate_timestamp); + if (!connection || (candidate_timestamp > best_timestamp)) { + connection = candidate; + best_timestamp = candidate_timestamp; } } - return array; + + if (!connection) { + g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_CONNECTION, + "The device '%s' has no connections available for activation.", + nm_device_get_iface (self)); + } + + return connection; } static void @@ -9838,12 +9851,15 @@ nm_device_add_pending_action (NMDevice *self, const char *action, gboolean asser gboolean nm_device_remove_pending_action (NMDevice *self, const char *action, gboolean assert_is_pending) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMDevicePrivate *priv; GSList *iter, *next; guint count = 0; + g_return_val_if_fail (self, FALSE); g_return_val_if_fail (action, FALSE); + priv = NM_DEVICE_GET_PRIVATE (self); + for (iter = priv->pending_actions; iter; iter = next) { next = iter->next; if (!strcmp (action, iter->data)) { @@ -10352,7 +10368,7 @@ _set_state_full (NMDevice *self, if ( (priv->state == state) && ( state != NM_DEVICE_STATE_UNAVAILABLE || !priv->firmware_missing)) { - _LOGD (LOGD_DEVICE, "device state change: %s -> %s (reason '%s') [%d %d %d]%s", + _LOGD (LOGD_DEVICE, "state change: %s -> %s (reason '%s') [%d %d %d]%s", state_to_string (old_state), state_to_string (state), reason_to_string (reason), @@ -10363,7 +10379,7 @@ _set_state_full (NMDevice *self, return; } - _LOGI (LOGD_DEVICE, "device state change: %s -> %s (reason '%s') [%d %d %d]", + _LOGI (LOGD_DEVICE, "state change: %s -> %s (reason '%s') [%d %d %d]", state_to_string (old_state), state_to_string (state), reason_to_string (reason), @@ -10389,7 +10405,8 @@ _set_state_full (NMDevice *self, if (state <= NM_DEVICE_STATE_UNAVAILABLE) { if (available_connections_del_all (self)) available_connections_notify (self); - _clear_queued_act_request (priv); + if (old_state > NM_DEVICE_STATE_UNAVAILABLE) + _clear_queued_act_request (priv); } /* Update the available connections list when a device first becomes available */ diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index 9b9edda4..bd657e68 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -529,8 +529,9 @@ gboolean nm_device_add_pending_action (NMDevice *device, const char *action, gboolean nm_device_remove_pending_action (NMDevice *device, const char *action, gboolean assert_is_pending); gboolean nm_device_has_pending_action (NMDevice *device); -GPtrArray *nm_device_get_available_connections (NMDevice *device, - const char *specific_object); +NMSettingsConnection *nm_device_get_best_connection (NMDevice *device, + const char *specific_object, + GError **error); gboolean nm_device_check_connection_available (NMDevice *device, NMConnection *connection, diff --git a/src/devices/nm-lldp-listener.c b/src/devices/nm-lldp-listener.c index 81827817..e678dc67 100644 --- a/src/devices/nm-lldp-listener.c +++ b/src/devices/nm-lldp-listener.c @@ -20,33 +20,71 @@ #include "nm-default.h" +#include "nm-lldp-listener.h" + #include <net/ethernet.h> +#include <errno.h> -#include "sd-lldp.h" -#include "lldp.h" -#include "nm-lldp-listener.h" #include "nm-platform.h" #include "nm-utils.h" +#include "sd-lldp.h" + +#include "nm-sd-adapt.h" +#include "lldp.h" + #define MAX_NEIGHBORS 4096 -#define MIN_UPDATE_INTERVAL 2 +#define MIN_UPDATE_INTERVAL_NS (2 * NM_UTILS_NS_PER_SECOND) + +#define LLDP_MAC_NEAREST_BRIDGE ((const struct ether_addr *) ((uint8_t[ETH_ALEN]) { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e })) +#define LLDP_MAC_NEAREST_NON_TPMR_BRIDGE ((const struct ether_addr *) ((uint8_t[ETH_ALEN]) { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 })) +#define LLDP_MAC_NEAREST_CUSTOMER_BRIDGE ((const struct ether_addr *) ((uint8_t[ETH_ALEN]) { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 })) + +typedef enum { + LLDP_ATTR_TYPE_NONE, + LLDP_ATTR_TYPE_UINT32, + LLDP_ATTR_TYPE_STRING, +} LldpAttrType; + +typedef enum { + /* the order of the enum values determines the order of the fields in + * the variant. */ + LLDP_ATTR_ID_PORT_DESCRIPTION, + LLDP_ATTR_ID_SYSTEM_NAME, + LLDP_ATTR_ID_SYSTEM_DESCRIPTION, + LLDP_ATTR_ID_SYSTEM_CAPABILITIES, + LLDP_ATTR_ID_IEEE_802_1_PVID, + LLDP_ATTR_ID_IEEE_802_1_PPVID, + LLDP_ATTR_ID_IEEE_802_1_PPVID_FLAGS, + LLDP_ATTR_ID_IEEE_802_1_VID, + LLDP_ATTR_ID_IEEE_802_1_VLAN_NAME, + _LLDP_PROP_ID_COUNT, +} LldpAttrId; + +typedef struct { + LldpAttrType attr_type; + union { + guint32 v_uint32; + char *v_string; + }; +} LldpAttrData; typedef struct { char *iface; int ifindex; sd_lldp *lldp_handle; GHashTable *lldp_neighbors; - guint timer; - guint num_pending_events; + + /* the timestamp in nsec until which we delay updates. */ + gint64 ratelimit_next; + guint ratelimit_id; + GVariant *variant; } NMLldpListenerPrivate; -enum { - PROP_0, +NM_GOBJECT_PROPERTIES_DEFINE (NMLldpListener, PROP_NEIGHBORS, - - LAST_PROP -}; +); G_DEFINE_TYPE (NMLldpListener, nm_lldp_listener, G_TYPE_OBJECT) @@ -58,12 +96,14 @@ typedef struct { char *chassis_id; char *port_id; - int dest; + struct ether_addr destination_address; + + bool valid:1; - GHashTable *tlvs; -} LLDPNeighbor; + LldpAttrData attrs[_LLDP_PROP_ID_COUNT]; -static void process_lldp_neighbors (NMLldpListener *self); + GVariant *variant; +} LldpNeighbor; /*****************************************************************************/ @@ -89,43 +129,139 @@ static void process_lldp_neighbors (NMLldpListener *self); } \ } G_STMT_END \ +#define LOG_NEIGH_FMT "CHASSIS=%s%s%s PORT=%s%s%s" +#define LOG_NEIGH_ARG(neigh) NM_PRINT_FMT_QUOTE_STRING ((neigh)->chassis_id), NM_PRINT_FMT_QUOTE_STRING ((neigh)->port_id) + /*****************************************************************************/ +static gboolean +ether_addr_equal (const struct ether_addr *a1, const struct ether_addr *a2) +{ + nm_assert (a1); + nm_assert (a2); + + G_STATIC_ASSERT_EXPR (sizeof (*a1) == ETH_ALEN); + return memcmp (a1, a2, ETH_ALEN) == 0; +} + +static guint32 +_access_uint8 (const void *data) +{ + return *((const guint8 *) data); +} + +static guint32 +_access_uint16 (const void *data) +{ + guint16 v; + + memcpy (&v, data, sizeof (v)); + return ntohs (v); +} + +/*****************************************************************************/ + +NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_lldp_attr_id_to_name, LldpAttrId, + NM_UTILS_LOOKUP_DEFAULT_WARN (NULL), + NM_UTILS_LOOKUP_STR_ITEM (LLDP_ATTR_ID_PORT_DESCRIPTION, NM_LLDP_ATTR_PORT_DESCRIPTION), + NM_UTILS_LOOKUP_STR_ITEM (LLDP_ATTR_ID_SYSTEM_NAME, NM_LLDP_ATTR_SYSTEM_NAME), + NM_UTILS_LOOKUP_STR_ITEM (LLDP_ATTR_ID_SYSTEM_DESCRIPTION, NM_LLDP_ATTR_SYSTEM_DESCRIPTION), + NM_UTILS_LOOKUP_STR_ITEM (LLDP_ATTR_ID_SYSTEM_CAPABILITIES, NM_LLDP_ATTR_SYSTEM_CAPABILITIES), + NM_UTILS_LOOKUP_STR_ITEM (LLDP_ATTR_ID_IEEE_802_1_PVID, NM_LLDP_ATTR_IEEE_802_1_PVID), + NM_UTILS_LOOKUP_STR_ITEM (LLDP_ATTR_ID_IEEE_802_1_PPVID, NM_LLDP_ATTR_IEEE_802_1_PPVID), + NM_UTILS_LOOKUP_STR_ITEM (LLDP_ATTR_ID_IEEE_802_1_PPVID_FLAGS, NM_LLDP_ATTR_IEEE_802_1_PPVID_FLAGS), + NM_UTILS_LOOKUP_STR_ITEM (LLDP_ATTR_ID_IEEE_802_1_VID, NM_LLDP_ATTR_IEEE_802_1_VID), + NM_UTILS_LOOKUP_STR_ITEM (LLDP_ATTR_ID_IEEE_802_1_VLAN_NAME, NM_LLDP_ATTR_IEEE_802_1_VLAN_NAME), + NM_UTILS_LOOKUP_ITEM_IGNORE (_LLDP_PROP_ID_COUNT), +); + +_NM_UTILS_LOOKUP_DEFINE (static, _lldp_attr_id_to_type, LldpAttrId, LldpAttrType, + NM_UTILS_LOOKUP_DEFAULT_WARN (LLDP_ATTR_TYPE_NONE), + NM_UTILS_LOOKUP_ITEM (LLDP_ATTR_ID_PORT_DESCRIPTION, LLDP_ATTR_TYPE_STRING), + NM_UTILS_LOOKUP_ITEM (LLDP_ATTR_ID_SYSTEM_NAME, LLDP_ATTR_TYPE_STRING), + NM_UTILS_LOOKUP_ITEM (LLDP_ATTR_ID_SYSTEM_DESCRIPTION, LLDP_ATTR_TYPE_STRING), + NM_UTILS_LOOKUP_ITEM (LLDP_ATTR_ID_SYSTEM_CAPABILITIES, LLDP_ATTR_TYPE_UINT32), + NM_UTILS_LOOKUP_ITEM (LLDP_ATTR_ID_IEEE_802_1_PVID, LLDP_ATTR_TYPE_UINT32), + NM_UTILS_LOOKUP_ITEM (LLDP_ATTR_ID_IEEE_802_1_PPVID, LLDP_ATTR_TYPE_UINT32), + NM_UTILS_LOOKUP_ITEM (LLDP_ATTR_ID_IEEE_802_1_PPVID_FLAGS, LLDP_ATTR_TYPE_UINT32), + NM_UTILS_LOOKUP_ITEM (LLDP_ATTR_ID_IEEE_802_1_VID, LLDP_ATTR_TYPE_UINT32), + NM_UTILS_LOOKUP_ITEM (LLDP_ATTR_ID_IEEE_802_1_VLAN_NAME, LLDP_ATTR_TYPE_STRING), + NM_UTILS_LOOKUP_ITEM_IGNORE (_LLDP_PROP_ID_COUNT), +); + static void -gvalue_destroy (gpointer data) +_lldp_attr_set_str (LldpAttrData *pdata, LldpAttrId attr_id, const char *v_string) { - GValue *value = (GValue *) data; + nm_assert (pdata); + nm_assert (_lldp_attr_id_to_type (attr_id) == LLDP_ATTR_TYPE_STRING); + + pdata = &pdata[attr_id]; - g_value_unset (value); - g_slice_free (GValue, value); + /* we ignore duplicate fields silently. */ + if (pdata->attr_type != LLDP_ATTR_TYPE_NONE) + return; + pdata->attr_type = LLDP_ATTR_TYPE_STRING; + pdata->v_string = g_strdup (v_string ?: ""); } -static GValue * -gvalue_new_nstr (const char *str, guint16 len) +static void +_lldp_attr_set_str_ptr (LldpAttrData *pdata, LldpAttrId attr_id, const void *str, gsize len) { - GValue *value; + const char *s = str; + const char *tmp; + gsize len0 = len; + gs_free char *str_free = NULL; + + nm_assert (pdata); + nm_assert (_lldp_attr_id_to_type (attr_id) == LLDP_ATTR_TYPE_STRING); + + pdata = &pdata[attr_id]; + + /* we ignore duplicate fields silently. */ + if (pdata->attr_type != LLDP_ATTR_TYPE_NONE) + return; + + pdata->attr_type = LLDP_ATTR_TYPE_STRING; - value = g_slice_new0 (GValue); - g_value_init (value, G_TYPE_STRING); - g_value_take_string (value, strndup (str, len)); - return value; + /* truncate at first NUL, including removing trailing NULs*/ + tmp = memchr (s, '\0', len); + if (tmp) + len = tmp - s; + + if (!len) { + pdata->v_string = g_strdup (""); + return; + } + + if (len0 <= len || s[len] != '\0') { + /* hmpf, g_strescape needs a trailing NUL. Need to clone */ + s = str_free = g_strndup (s, len); + } + + pdata->v_string = g_strescape (s, NULL); } -static GValue * -gvalue_new_uint (guint val) +static void +_lldp_attr_set_uint32 (LldpAttrData *pdata, LldpAttrId attr_id, guint32 v_uint32) { - GValue *value; + nm_assert (pdata); + nm_assert (_lldp_attr_id_to_type (attr_id) == LLDP_ATTR_TYPE_UINT32); + + pdata = &pdata[attr_id]; - value = g_slice_new0 (GValue); - g_value_init (value, G_TYPE_UINT); - g_value_set_uint (value, val); - return value; + /* we ignore duplicate fields silently. */ + if (pdata->attr_type != LLDP_ATTR_TYPE_NONE) + return; + pdata->attr_type = LLDP_ATTR_TYPE_UINT32; + pdata->v_uint32 = v_uint32; } +/*****************************************************************************/ + static guint lldp_neighbor_id_hash (gconstpointer ptr) { - const LLDPNeighbor *neigh = ptr; + const LldpNeighbor *neigh = ptr; guint hash; hash = 23423423u + ((guint) (neigh->chassis_id ? g_str_hash (neigh->chassis_id) : 12321u)); @@ -135,303 +271,453 @@ lldp_neighbor_id_hash (gconstpointer ptr) return hash; } +static int +lldp_neighbor_id_cmp (gconstpointer a, gconstpointer b) +{ + const LldpNeighbor *x = a, *y = b; + int c; + + if (x->chassis_id_type != y->chassis_id_type) + return x->chassis_id_type < y->chassis_id_type ? -1 : 1; + if (x->port_id_type != y->port_id_type) + return x->port_id_type < y->port_id_type ? -1 : 1; + c = g_strcmp0 (x->chassis_id, y->chassis_id); + if (c == 0) + c = g_strcmp0 (x->port_id, y->port_id); + return c < 0 ? -1 : (c > 0 ? 1 : 0); +} + static gboolean lldp_neighbor_id_equal (gconstpointer a, gconstpointer b) { - const LLDPNeighbor *x = a, *y = b; - - return x->chassis_id_type == y->chassis_id_type && - x->port_id_type == y->port_id_type && - !g_strcmp0 (x->chassis_id, y->chassis_id) && - !g_strcmp0 (x->port_id, y->port_id); + return lldp_neighbor_id_cmp (a, b) == 0; } static void -lldp_neighbor_free (LLDPNeighbor *neighbor) +lldp_neighbor_free (LldpNeighbor *neighbor) { + LldpAttrId attr_id; + if (neighbor) { g_free (neighbor->chassis_id); g_free (neighbor->port_id); - g_hash_table_unref (neighbor->tlvs); - g_slice_free (LLDPNeighbor, neighbor); + for (attr_id = 0; attr_id < _LLDP_PROP_ID_COUNT; attr_id++) { + if (neighbor->attrs[attr_id].attr_type == LLDP_ATTR_TYPE_STRING) + g_free (neighbor->attrs[attr_id].v_string); + } + g_clear_pointer (&neighbor->variant, g_variant_unref); + g_slice_free (LldpNeighbor, neighbor); } } static void -lldp_neighbor_freep (LLDPNeighbor **ptr) +lldp_neighbor_freep (LldpNeighbor **ptr) { lldp_neighbor_free (*ptr); } static gboolean -lldp_neighbor_equal (LLDPNeighbor *a, LLDPNeighbor *b) +lldp_neighbor_equal (LldpNeighbor *a, LldpNeighbor *b) { - GHashTableIter iter; - gpointer k, v; + LldpAttrId attr_id; - g_return_val_if_fail (a && a->tlvs, FALSE); - g_return_val_if_fail (b && b->tlvs, FALSE); + nm_assert (a); + nm_assert (b); if ( a->chassis_id_type != b->chassis_id_type || a->port_id_type != b->port_id_type - || a->dest != b->dest - || g_strcmp0 (a->chassis_id, b->chassis_id) - || g_strcmp0 (a->port_id, b->port_id)) - return FALSE; - - if (g_hash_table_size (a->tlvs) != g_hash_table_size (b->tlvs)) + || ether_addr_equal (&a->destination_address, &b->destination_address) + || !nm_streq0 (a->chassis_id, b->chassis_id) + || !nm_streq0 (a->port_id, b->port_id)) return FALSE; - g_hash_table_iter_init (&iter, a->tlvs); - while (g_hash_table_iter_next (&iter, &k, &v)) { - GValue *value_a, *value_b; - - value_a = v; - value_b = g_hash_table_lookup (b->tlvs, k); - - if (!value_b) + for (attr_id = 0; attr_id < _LLDP_PROP_ID_COUNT; attr_id++) { + if (a->attrs[attr_id].attr_type != b->attrs[attr_id].attr_type) return FALSE; - - g_return_val_if_fail (G_VALUE_TYPE (value_a) == G_VALUE_TYPE (value_b), FALSE); - - if (G_VALUE_HOLDS_STRING (value_a)) { - if (g_strcmp0 (g_value_get_string (value_a), g_value_get_string (value_b))) + switch (a->attrs[attr_id].attr_type) { + case LLDP_ATTR_TYPE_UINT32: + if (a->attrs[attr_id].v_uint32 != b->attrs[attr_id].v_uint32) return FALSE; - } else if (G_VALUE_HOLDS_UINT (value_a)) { - if (g_value_get_uint (value_a) != g_value_get_uint (value_b)) + break; + case LLDP_ATTR_TYPE_STRING: + if (!nm_streq (a->attrs[attr_id].v_string, b->attrs[attr_id].v_string)) return FALSE; - } else - g_return_val_if_reached (FALSE); + break; + default: + nm_assert (a->attrs[attr_id].attr_type == LLDP_ATTR_TYPE_NONE); + break; + } } return TRUE; } -static gboolean -lldp_hash_table_equal (GHashTable *a, GHashTable *b) +static LldpNeighbor * +lldp_neighbor_new (sd_lldp_neighbor *neighbor_sd, GError **error) { - GHashTableIter iter; - gpointer val; - - g_return_val_if_fail (a, FALSE); - g_return_val_if_fail (b, FALSE); + nm_auto (lldp_neighbor_freep) LldpNeighbor *neigh = NULL; + uint8_t chassis_id_type, port_id_type; + uint16_t data16; + uint8_t *data8; + const void *chassis_id, *port_id; + gsize chassis_id_len, port_id_len, len; + const char *str; + int r; + + r = sd_lldp_neighbor_get_chassis_id (neighbor_sd, &chassis_id_type, + &chassis_id, &chassis_id_len); + if (r < 0) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "failed reading chassis-id: %s", g_strerror (-r)); + return NULL; + } + if (chassis_id_len < 1) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "empty chassis-id"); + return NULL; + } - if (g_hash_table_size (a) != g_hash_table_size (b)) - return FALSE; + r = sd_lldp_neighbor_get_port_id (neighbor_sd, &port_id_type, + &port_id, &port_id_len); + if (r < 0) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "failed reading port-id: %s", g_strerror (-r)); + return NULL; + } + if (port_id_len < 1) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "empty port-id"); + return NULL; + } - g_hash_table_iter_init (&iter, a); - while (g_hash_table_iter_next (&iter, NULL, &val)) { - LLDPNeighbor *neigh_a, *neigh_b; + neigh = g_slice_new0 (LldpNeighbor); + neigh->chassis_id_type = chassis_id_type; + neigh->port_id_type = port_id_type; - neigh_a = val; - neigh_b = g_hash_table_lookup (b, val); + r = sd_lldp_neighbor_get_destination_address (neighbor_sd, &neigh->destination_address); + if (r < 0) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "failed getting destination address: %s", g_strerror (-r)); + goto out; + } - if (!neigh_b) - return FALSE; + switch (chassis_id_type) { + case LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS: + case LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME: + case LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED: + case LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT: + neigh->chassis_id = g_strndup ((const char *) chassis_id, chassis_id_len); + break; + case LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS: + neigh->chassis_id = nm_utils_hwaddr_ntoa (chassis_id, chassis_id_len); + break; + default: + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "unsupported chassis-id type %d", chassis_id_type); + goto out; + } - if (!lldp_neighbor_equal (neigh_a, neigh_b)) - return FALSE; + switch (port_id_type) { + case LLDP_PORT_SUBTYPE_INTERFACE_ALIAS: + case LLDP_PORT_SUBTYPE_INTERFACE_NAME: + case LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED: + case LLDP_PORT_SUBTYPE_PORT_COMPONENT: + neigh->port_id = strndup ((char *) port_id, port_id_len); + break; + case LLDP_PORT_SUBTYPE_MAC_ADDRESS: + neigh->port_id = nm_utils_hwaddr_ntoa (port_id, port_id_len); + break; + default: + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "unsupported port-id type %d", port_id_type); + goto out; } - return TRUE; -} + if (sd_lldp_neighbor_get_port_description (neighbor_sd, &str) == 0) + _lldp_attr_set_str (neigh->attrs, LLDP_ATTR_ID_PORT_DESCRIPTION, str); -static gboolean -lldp_timeout (gpointer user_data) -{ - NMLldpListener *self = user_data; - NMLldpListenerPrivate *priv; + if (sd_lldp_neighbor_get_system_name (neighbor_sd, &str) == 0) + _lldp_attr_set_str (neigh->attrs, LLDP_ATTR_ID_SYSTEM_NAME, str); - g_return_val_if_fail (NM_IS_LLDP_LISTENER (self), G_SOURCE_REMOVE); + if (sd_lldp_neighbor_get_system_description (neighbor_sd, &str) == 0) + _lldp_attr_set_str (neigh->attrs, LLDP_ATTR_ID_SYSTEM_DESCRIPTION, str); - priv = NM_LLDP_LISTENER_GET_PRIVATE (self); + if (sd_lldp_neighbor_get_system_capabilities (neighbor_sd, &data16) == 0) + _lldp_attr_set_uint32 (neigh->attrs, LLDP_ATTR_ID_SYSTEM_CAPABILITIES, data16); - priv->timer = 0; + r = sd_lldp_neighbor_tlv_rewind (neighbor_sd); + if (r < 0) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "failed reading tlv (rewind): %s", g_strerror (-r)); + goto out; + } + do { + guint8 oui[3]; + guint8 subtype; + + r = sd_lldp_neighbor_tlv_get_oui (neighbor_sd, oui, &subtype); + if (r < 0) { + if (r == -ENXIO) + continue; + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "failed reading tlv: %s", g_strerror (-r)); + goto out; + } - if (priv->num_pending_events) - process_lldp_neighbors (self); + if (!( memcmp (oui, LLDP_OUI_802_1, sizeof (oui)) == 0 + && NM_IN_SET (subtype, + LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID, + LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID, + LLDP_OUI_802_1_SUBTYPE_VLAN_NAME))) + continue; + + if (sd_lldp_neighbor_tlv_get_raw (neighbor_sd, (void *) &data8, &len) < 0) + continue; + + /* skip over leading TLV, OUI and subtype */ +#ifdef WITH_MORE_ASSERTS + { + guint8 check_hdr[] = { + 0xfe | (((len - 2) >> 8) & 0x01), ((len - 2) & 0xFF), + oui[0], oui[1], oui[2], + subtype + }; + + nm_assert (len > 2 + 3 +1); + nm_assert (memcmp (data8, check_hdr, sizeof check_hdr) == 0); + } +#endif + if (len <= 6) + continue; + data8 += 6; + len -= 6; + + /*if (memcmp (oui, LLDP_OUI_802_1, sizeof (oui)) == 0)*/ + { + switch (subtype) { + case LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID: + if (len != 2) + continue; + _lldp_attr_set_uint32 (neigh->attrs, LLDP_ATTR_ID_IEEE_802_1_PVID, + _access_uint16 (data8)); + break; + case LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID: + if (len != 3) + continue; + _lldp_attr_set_uint32 (neigh->attrs, LLDP_ATTR_ID_IEEE_802_1_PPVID_FLAGS, + _access_uint8 (&data8[0])); + _lldp_attr_set_uint32 (neigh->attrs, LLDP_ATTR_ID_IEEE_802_1_PPVID, + _access_uint16 (&data8[1])); + break; + case LLDP_OUI_802_1_SUBTYPE_VLAN_NAME: { + int l; + + if (len <= 3) + continue; + + l = data8[2]; + if (len != 3 + l) + continue; + + _lldp_attr_set_uint32 (neigh->attrs, LLDP_ATTR_ID_IEEE_802_1_VID, + _access_uint16 (&data8[0])); + _lldp_attr_set_str_ptr (neigh->attrs, LLDP_ATTR_ID_IEEE_802_1_VLAN_NAME, + &data8[3], len); + break; + } + default: + g_assert_not_reached (); + } + } + } while (sd_lldp_neighbor_tlv_next (neighbor_sd) > 0); - return G_SOURCE_REMOVE; + neigh->valid = TRUE; + +out: + return nm_unauto (&neigh); } -static void -process_lldp_neighbors (NMLldpListener *self) +static GVariant * +lldp_neighbor_to_variant (LldpNeighbor *neigh) { - NMLldpListenerPrivate *priv = NM_LLDP_LISTENER_GET_PRIVATE (self); - nm_auto_free sd_lldp_packet **packets = NULL; - GHashTable *hash; - int num, i; - - g_return_if_fail (priv->lldp_handle); - - num = sd_lldp_get_packets (priv->lldp_handle, &packets); - if (num < 0) { - _LOGD ("process: error %d retrieving neighbor packets for %s", - num, priv->iface); - return; + GVariantBuilder builder; + const char *dest_str; + LldpAttrId attr_id; + + if (neigh->variant) + return neigh->variant; + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); + + g_variant_builder_add (&builder, "{sv}", + NM_LLDP_ATTR_CHASSIS_ID_TYPE, + g_variant_new_uint32 (neigh->chassis_id_type)); + g_variant_builder_add (&builder, "{sv}", + NM_LLDP_ATTR_CHASSIS_ID, + g_variant_new_string (neigh->chassis_id)); + g_variant_builder_add (&builder, "{sv}", + NM_LLDP_ATTR_PORT_ID_TYPE, + g_variant_new_uint32 (neigh->port_id_type)); + g_variant_builder_add (&builder, "{sv}", + NM_LLDP_ATTR_PORT_ID, + g_variant_new_string (neigh->port_id)); + + if (ether_addr_equal (&neigh->destination_address, LLDP_MAC_NEAREST_BRIDGE)) + dest_str = NM_LLDP_DEST_NEAREST_BRIDGE; + else if (ether_addr_equal (&neigh->destination_address, LLDP_MAC_NEAREST_NON_TPMR_BRIDGE)) + dest_str = NM_LLDP_DEST_NEAREST_NON_TPMR_BRIDGE; + else if (ether_addr_equal (&neigh->destination_address, LLDP_MAC_NEAREST_CUSTOMER_BRIDGE)) + dest_str = NM_LLDP_DEST_NEAREST_CUSTOMER_BRIDGE; + else + dest_str = NULL; + if (dest_str) { + g_variant_builder_add (&builder, "{sv}", + NM_LLDP_ATTR_DESTINATION, + g_variant_new_string (dest_str)); } - hash = g_hash_table_new_full (lldp_neighbor_id_hash, lldp_neighbor_id_equal, - (GDestroyNotify) lldp_neighbor_free, NULL); - - for (i = 0; packets && i < num; i++) { - nm_auto (lldp_neighbor_freep) LLDPNeighbor *neigh = NULL; - uint8_t chassis_id_type, port_id_type, *chassis_id, *port_id, data8; - uint16_t chassis_id_len, port_id_len, len, data16; - GValue *value; - char *str; - int r; - - if (i >= MAX_NEIGHBORS) - goto next_packet; - - r = sd_lldp_packet_read_chassis_id (packets[i], &chassis_id_type, - &chassis_id, &chassis_id_len); - if (r < 0) - goto next_packet; - - r = sd_lldp_packet_read_port_id (packets[i], &port_id_type, - &port_id, &port_id_len); - if (r < 0) - goto next_packet; - - neigh = g_slice_new0 (LLDPNeighbor); - neigh->tlvs = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, gvalue_destroy); - neigh->chassis_id_type = chassis_id_type; - neigh->port_id_type = port_id_type; - sd_lldp_packet_get_destination_type (packets[i], &neigh->dest); - - if (chassis_id_len < 1) - goto next_packet; - - switch (chassis_id_type) { - case LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS: - case LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME: - case LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED: - case LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT: - neigh->chassis_id = g_strndup ((const char *) chassis_id, chassis_id_len); - break; - case LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS: - neigh->chassis_id = nm_utils_hwaddr_ntoa (chassis_id, chassis_id_len); - break; - default: - _LOGD ("process: unsupported chassis ID type %d", chassis_id_type); - goto next_packet; - } - - if (port_id_len < 1) - goto next_packet; + for (attr_id = 0; attr_id < _LLDP_PROP_ID_COUNT; attr_id++) { + const LldpAttrData *data = &neigh->attrs[attr_id]; - switch (port_id_type) { - case LLDP_PORT_SUBTYPE_INTERFACE_ALIAS: - case LLDP_PORT_SUBTYPE_INTERFACE_NAME: - case LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED: - case LLDP_PORT_SUBTYPE_PORT_COMPONENT: - neigh->port_id = strndup ((char *) port_id, port_id_len); + nm_assert (NM_IN_SET (data->attr_type, _lldp_attr_id_to_type (attr_id), LLDP_ATTR_TYPE_NONE)); + switch (data->attr_type) { + case LLDP_ATTR_TYPE_UINT32: + g_variant_builder_add (&builder, "{sv}", + _lldp_attr_id_to_name (attr_id), + g_variant_new_uint32 (data->v_uint32)); break; - case LLDP_PORT_SUBTYPE_MAC_ADDRESS: - neigh->port_id = nm_utils_hwaddr_ntoa (port_id, port_id_len); + case LLDP_ATTR_TYPE_STRING: + g_variant_builder_add (&builder, "{sv}", + _lldp_attr_id_to_name (attr_id), + g_variant_new_string (data->v_string)); break; default: - _LOGD ("process: unsupported port ID type %d", port_id_type); - goto next_packet; - } - - if (sd_lldp_packet_read_port_description (packets[i], &str, &len) == 0) { - value = gvalue_new_nstr (str, len); - g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_PORT_DESCRIPTION, value); - } - - if (sd_lldp_packet_read_system_name (packets[i], &str, &len) == 0) { - value = gvalue_new_nstr (str, len); - g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_SYSTEM_NAME, value); - } - - if (sd_lldp_packet_read_system_description (packets[i], &str, &len) == 0) { - value = gvalue_new_nstr (str, len); - g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_SYSTEM_DESCRIPTION, value); - } - - if (sd_lldp_packet_read_system_capability (packets[i], &data16) == 0) { - value = gvalue_new_uint (data16); - g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_SYSTEM_CAPABILITIES, value); - } - - if (sd_lldp_packet_read_port_vlan_id (packets[i], &data16) == 0) { - value = gvalue_new_uint (data16); - g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_PVID, value); + break; } + } - if (sd_lldp_packet_read_port_protocol_vlan_id (packets[i], &data8, &data16) == 0) { - value = gvalue_new_uint (data16); - g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_PPVID, value); + return (neigh->variant = g_variant_ref_sink (g_variant_builder_end (&builder))); +} - value = gvalue_new_uint (data8); - g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_PPVID_FLAGS, value); - } +/*****************************************************************************/ - if (sd_lldp_packet_read_vlan_name (packets[i], &data16, &str, &len) == 0) { - value = gvalue_new_uint (data16); - g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_VID, value); +static void +data_changed_notify (NMLldpListener *self, NMLldpListenerPrivate *priv) +{ + nm_clear_g_variant (&priv->variant); + _notify (self, PROP_NEIGHBORS); +} - value = gvalue_new_nstr (str, len); - g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_VLAN_NAME, value); - } +static gboolean +data_changed_timeout (gpointer user_data) +{ + NMLldpListener *self = user_data; + NMLldpListenerPrivate *priv; - _LOGD ("process: new neigh: CHASSIS='%s' PORT='%s'", - neigh->chassis_id, neigh->port_id); + g_return_val_if_fail (NM_IS_LLDP_LISTENER (self), G_SOURCE_REMOVE); - g_hash_table_add (hash, neigh); - neigh = NULL; -next_packet: - sd_lldp_packet_unref (packets[i]); - } + priv = NM_LLDP_LISTENER_GET_PRIVATE (self); - if (lldp_hash_table_equal (priv->lldp_neighbors, hash)) { - g_hash_table_destroy (hash); - } else { - g_hash_table_destroy (priv->lldp_neighbors); - priv->lldp_neighbors = hash; - nm_clear_g_variant (&priv->variant); - g_object_notify (G_OBJECT (self), NM_LLDP_LISTENER_NEIGHBORS); - } + priv->ratelimit_id = 0; + priv->ratelimit_next = nm_utils_get_monotonic_timestamp_ns() + MIN_UPDATE_INTERVAL_NS; + data_changed_notify (self, priv); + return G_SOURCE_REMOVE; +} - /* Since the processing of the neighbor list is potentially - * expensive when there are many neighbors, coalesce multiple - * events arriving in short time. - */ - priv->timer = g_timeout_add_seconds (MIN_UPDATE_INTERVAL, lldp_timeout, self); - priv->num_pending_events = 0; +static void +data_changed_schedule (NMLldpListener *self) +{ + NMLldpListenerPrivate *priv = NM_LLDP_LISTENER_GET_PRIVATE (self); + gint64 now; + + now = nm_utils_get_monotonic_timestamp_ns (); + if (now >= priv->ratelimit_next) { + nm_clear_g_source (&priv->ratelimit_id); + priv->ratelimit_next = now + MIN_UPDATE_INTERVAL_NS; + data_changed_notify (self, priv); + } else if (!priv->ratelimit_id) + priv->ratelimit_id = g_timeout_add (NM_UTILS_NS_TO_MSEC_CEIL (priv->ratelimit_next - now), data_changed_timeout, self); } static void -lldp_event_handler (sd_lldp *lldp, int event, void *userdata) +process_lldp_neighbor (NMLldpListener *self, sd_lldp_neighbor *neighbor_sd, gboolean neighbor_valid) { - NMLldpListener *self = userdata; NMLldpListenerPrivate *priv; + nm_auto (lldp_neighbor_freep) LldpNeighbor *neigh = NULL; + LldpNeighbor *neigh_old; + gs_free_error GError *parse_error = NULL; + GError **p_parse_error; + gboolean changed = FALSE; g_return_if_fail (NM_IS_LLDP_LISTENER (self)); priv = NM_LLDP_LISTENER_GET_PRIVATE (self); - if (priv->timer > 0) { - priv->num_pending_events++; + g_return_if_fail (priv->lldp_handle); + g_return_if_fail (neighbor_sd); + + p_parse_error = _LOGT_ENABLED () ? &parse_error : NULL; + + neigh = lldp_neighbor_new (neighbor_sd, p_parse_error); + if (!neigh) { + _LOGT ("process: failed to parse neighbor: %s", parse_error->message); + return; + } + + if (!neigh->valid) + neighbor_valid = FALSE; + + neigh_old = g_hash_table_lookup (priv->lldp_neighbors, neigh); + if (neigh_old) { + if (!neighbor_valid) { + _LOGT ("process: %s neigh: "LOG_NEIGH_FMT"%s%s%s", + "remove", LOG_NEIGH_ARG (neigh), + NM_PRINT_FMT_QUOTED (parse_error, " (failed to parse: ", parse_error->message, ")", "")); + + g_hash_table_remove (priv->lldp_neighbors, neigh_old); + changed = TRUE; + goto done; + } else if (lldp_neighbor_equal (neigh_old, neigh)) + return; + } else if (!neighbor_valid) { + if (parse_error) + _LOGT ("process: failed to parse neighbor: %s", parse_error->message); + return; + } + + /* ensure that we have at most MAX_NEIGHBORS entires */ + if ( !neigh_old /* only matters in the "add" case. */ + && (g_hash_table_size (priv->lldp_neighbors) + 1 > MAX_NEIGHBORS)) { + _LOGT ("process: ignore neighbor due to overall limit of %d", MAX_NEIGHBORS); return; } - process_lldp_neighbors (self); + _LOGD ("process: %s neigh: "LOG_NEIGH_FMT, + neigh_old ? "update" : "new", + LOG_NEIGH_ARG (neigh)); + + changed = TRUE; + g_hash_table_add (priv->lldp_neighbors, nm_unauto (&neigh)); + +done: + if (changed) + data_changed_schedule (self); +} + +static void +lldp_event_handler (sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n, void *userdata) +{ + process_lldp_neighbor (userdata, n, event != SD_LLDP_EVENT_REMOVED); } gboolean -nm_lldp_listener_start (NMLldpListener *self, int ifindex, const char *iface, - const guint8 *mac, guint mac_len, GError **error) +nm_lldp_listener_start (NMLldpListener *self, int ifindex, GError **error) { NMLldpListenerPrivate *priv; int ret; g_return_val_if_fail (NM_IS_LLDP_LISTENER (self), FALSE); g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (iface, FALSE); g_return_val_if_fail (!error || !*error, FALSE); priv = NM_LLDP_LISTENER_GET_PRIVATE (self); @@ -442,43 +728,38 @@ nm_lldp_listener_start (NMLldpListener *self, int ifindex, const char *iface, return FALSE; } - if (!mac || mac_len != ETH_ALEN) { + ret = sd_lldp_new (&priv->lldp_handle, ifindex); + if (ret < 0) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, - "unsupported device"); + "initialization failed"); return FALSE; } - ret = sd_lldp_new (ifindex, iface, (struct ether_addr *) mac, &priv->lldp_handle); - if (ret) { + 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, - "initialization failed"); - return FALSE; + "set callback failed"); + goto err; } + priv->ifindex = ifindex; + ret = sd_lldp_attach_event (priv->lldp_handle, NULL, 0); - if (ret) { + if (ret < 0) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "attach event failed"); goto err_free; } - ret = sd_lldp_set_callback (priv->lldp_handle, lldp_event_handler, self); - if (ret) { - g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, - "set callback failed"); - goto err; - } - ret = sd_lldp_start (priv->lldp_handle); - if (ret) { + if (ret < 0) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "start failed"); goto err; } - priv->ifindex = ifindex; - priv->iface = strdup (iface); _LOGD ("start"); + return TRUE; err: @@ -486,6 +767,7 @@ err: err_free: sd_lldp_unref (priv->lldp_handle); priv->lldp_handle = NULL; + priv->ifindex = 0; return FALSE; } @@ -494,6 +776,7 @@ nm_lldp_listener_stop (NMLldpListener *self) { NMLldpListenerPrivate *priv; guint size; + gboolean changed = FALSE; g_return_if_fail (NM_IS_LLDP_LISTENER (self)); priv = NM_LLDP_LISTENER_GET_PRIVATE (self); @@ -503,19 +786,20 @@ nm_lldp_listener_stop (NMLldpListener *self) sd_lldp_stop (priv->lldp_handle); sd_lldp_detach_event (priv->lldp_handle); sd_lldp_unref (priv->lldp_handle); - g_clear_pointer (&priv->iface, g_free); priv->lldp_handle = NULL; size = g_hash_table_size (priv->lldp_neighbors); g_hash_table_remove_all (priv->lldp_neighbors); - if (size) { - nm_clear_g_variant (&priv->variant); - g_object_notify (G_OBJECT (self), NM_LLDP_LISTENER_NEIGHBORS); - } + if (size || priv->ratelimit_id) + changed = TRUE; } - nm_clear_g_source (&priv->timer); + nm_clear_g_source (&priv->ratelimit_id); + priv->ratelimit_next = 0; priv->ifindex = 0; + + if (changed) + data_changed_notify (self, priv); } gboolean @@ -532,78 +816,23 @@ nm_lldp_listener_is_running (NMLldpListener *self) GVariant * nm_lldp_listener_get_neighbors (NMLldpListener *self) { - GVariantBuilder array_builder, neigh_builder; - GHashTableIter iter; NMLldpListenerPrivate *priv; - LLDPNeighbor *neigh; - char *dest_str = NULL; + GVariantBuilder array_builder; + GList *neighbors, *iter; - priv = NM_LLDP_LISTENER_GET_PRIVATE (self); - - if (priv->variant) - goto out; - - g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aa{sv}")); - g_hash_table_iter_init (&iter, priv->lldp_neighbors); - - while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &neigh)) { - GHashTableIter val_iter; - gpointer key, val; - - g_variant_builder_init (&neigh_builder, G_VARIANT_TYPE ("a{sv}")); - - g_variant_builder_add (&neigh_builder, "{sv}", - NM_LLDP_ATTR_CHASSIS_ID_TYPE, - g_variant_new_uint32 (neigh->chassis_id_type)); - g_variant_builder_add (&neigh_builder, "{sv}", - NM_LLDP_ATTR_CHASSIS_ID, - g_variant_new_string (neigh->chassis_id)); - g_variant_builder_add (&neigh_builder, "{sv}", - NM_LLDP_ATTR_PORT_ID_TYPE, - g_variant_new_uint32 (neigh->port_id_type)); - g_variant_builder_add (&neigh_builder, "{sv}", - NM_LLDP_ATTR_PORT_ID, - g_variant_new_string (neigh->port_id)); - - switch (neigh->dest) { - case SD_LLDP_DESTINATION_TYPE_NEAREST_BRIDGE: - dest_str = NM_LLDP_DEST_NEAREST_BRIDGE; - break; - case SD_LLDP_DESTINATION_TYPE_NEAREST_NON_TPMR_BRIDGE: - dest_str = NM_LLDP_DEST_NEAREST_NON_TPMR_BRIDGE; - break; - case SD_LLDP_DESTINATION_TYPE_NEAREST_CUSTOMER_BRIDGE: - dest_str = NM_LLDP_DEST_NEAREST_CUSTOMER_BRIDGE; - break; - } - - if (dest_str) { - g_variant_builder_add (&neigh_builder, "{sv}", - NM_LLDP_ATTR_DESTINATION, - g_variant_new_string (dest_str)); - } + g_return_val_if_fail (NM_IS_LLDP_LISTENER (self), FALSE); - g_hash_table_iter_init (&val_iter, neigh->tlvs); - while (g_hash_table_iter_next (&val_iter, &key, &val)) { - GValue *item = val; - - if (G_VALUE_HOLDS_STRING (item)) { - g_variant_builder_add (&neigh_builder, "{sv}", - key, - g_variant_new_string (g_value_get_string (item))); - } else if (G_VALUE_HOLDS_UINT (item)) { - g_variant_builder_add (&neigh_builder, "{sv}", - key, - g_variant_new_uint32 (g_value_get_uint (item))); - } - } + priv = NM_LLDP_LISTENER_GET_PRIVATE (self); - g_variant_builder_add (&array_builder, "a{sv}", &neigh_builder); + if (!priv->variant) { + g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aa{sv}")); + neighbors = g_hash_table_get_keys (priv->lldp_neighbors); + neighbors = g_list_sort (neighbors, lldp_neighbor_id_cmp); + for (iter = neighbors; iter; iter = iter->next) + g_variant_builder_add_value (&array_builder, lldp_neighbor_to_variant (iter->data)); + g_list_free (neighbors); + priv->variant = g_variant_ref_sink (g_variant_builder_end (&array_builder)); } - - priv->variant = g_variant_ref_sink (g_variant_builder_end (&array_builder)); - -out: return priv->variant; } @@ -676,12 +905,13 @@ nm_lldp_listener_class_init (NMLldpListenerClass *klass) object_class->finalize = finalize; object_class->get_property = get_property; - g_object_class_install_property - (object_class, PROP_NEIGHBORS, - g_param_spec_variant (NM_LLDP_LISTENER_NEIGHBORS, "", "", - G_VARIANT_TYPE ("aa{sv}"), - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_NEIGHBORS] = + g_param_spec_variant (NM_LLDP_LISTENER_NEIGHBORS, "", "", + G_VARIANT_TYPE ("aa{sv}"), + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); } diff --git a/src/devices/nm-lldp-listener.h b/src/devices/nm-lldp-listener.h index 10c43e7c..df02fd63 100644 --- a/src/devices/nm-lldp-listener.h +++ b/src/devices/nm-lldp-listener.h @@ -42,8 +42,7 @@ typedef struct { GType nm_lldp_listener_get_type (void); NMLldpListener *nm_lldp_listener_new (void); -gboolean nm_lldp_listener_start (NMLldpListener *self, int ifindex, const char *iface, - const guint8 *mac, guint mac_len, GError **error); +gboolean nm_lldp_listener_start (NMLldpListener *self, int ifindex, GError **error); void nm_lldp_listener_stop (NMLldpListener *self); gboolean nm_lldp_listener_is_running (NMLldpListener *self); diff --git a/src/devices/team/nm-device-team.c b/src/devices/team/nm-device-team.c index c3d48b41..60842c18 100644 --- a/src/devices/team/nm-device-team.c +++ b/src/devices/team/nm-device-team.c @@ -107,7 +107,8 @@ complete_connection (NMDevice *device, { NMSettingTeam *s_team; - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_TEAM_SETTING_NAME, existing_connections, NULL, diff --git a/src/devices/tests/test-arping.c b/src/devices/tests/test-arping.c index 36e17631..72d28a7a 100644 --- a/src/devices/tests/test-arping.c +++ b/src/devices/tests/test-arping.c @@ -41,8 +41,8 @@ fixture_setup (test_fixture *fixture, gconstpointer user_data) { /* create veth pair. */ nmtstp_run_command_check ("ip link add dev %s type veth peer name %s", IFACE_VETH0, IFACE_VETH1); - fixture->ifindex0 = nmtstp_assert_wait_for_link (IFACE_VETH0, NM_LINK_TYPE_VETH, 100)->ifindex; - fixture->ifindex1 = nmtstp_assert_wait_for_link (IFACE_VETH1, NM_LINK_TYPE_VETH, 100)->ifindex; + fixture->ifindex0 = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, IFACE_VETH0, NM_LINK_TYPE_VETH, 100)->ifindex; + fixture->ifindex1 = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, IFACE_VETH1, NM_LINK_TYPE_VETH, 100)->ifindex; g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, fixture->ifindex0, NULL)); g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, fixture->ifindex1, NULL)); @@ -80,7 +80,7 @@ test_arping_common (test_fixture *fixture, TestInfo *info) for (i = 0; info->peer_addresses[i]; i++) { nmtstp_ip4_address_add (FALSE, fixture->ifindex1, info->peer_addresses[i], - 24, 0, 3600, 1800, NULL); + 24, 0, 3600, 1800, 0, NULL); } loop = g_main_loop_new (NULL, FALSE); diff --git a/src/devices/tests/test-lldp.c b/src/devices/tests/test-lldp.c index dfae58b1..85c3b510 100644 --- a/src/devices/tests/test-lldp.c +++ b/src/devices/tests/test-lldp.c @@ -27,18 +27,327 @@ #include <sys/types.h> #include "nm-lldp-listener.h" +#include "nm-sd.h" + +#include "nm-sd-adapt.h" +#include "lldp.h" + #include "test-common.h" +#include "nm-test-utils.h" + +/*****************************************************************************/ + +static GVariant * +get_lldp_neighbor (GVariant *neighbors, + int chassis_id_type, + const char *chassis_id, + int port_id_type, + const char *port_id) +{ + GVariantIter iter; + GVariant *variant; + GVariant *result = NULL; + + nmtst_assert_variant_is_of_type (neighbors, G_VARIANT_TYPE ("aa{sv}")); + + g_assert (chassis_id_type >= -1 && chassis_id_type <= G_MAXUINT8); + g_assert (port_id_type >= -1 && port_id_type <= G_MAXUINT8); + + g_variant_iter_init (&iter, neighbors); + while (g_variant_iter_next (&iter, "@a{sv}", &variant)) { + gs_unref_variant GVariant *v_chassis_id_type = NULL; + gs_unref_variant GVariant *v_chassis_id = NULL; + gs_unref_variant GVariant *v_port_id_type = NULL; + gs_unref_variant GVariant *v_port_id = NULL; + + v_chassis_id_type = g_variant_lookup_value (variant, NM_LLDP_ATTR_CHASSIS_ID_TYPE, G_VARIANT_TYPE_UINT32); + g_assert (v_chassis_id_type); + + v_chassis_id = g_variant_lookup_value (variant, NM_LLDP_ATTR_CHASSIS_ID, G_VARIANT_TYPE_STRING); + g_assert (v_chassis_id); + + v_port_id_type = g_variant_lookup_value (variant, NM_LLDP_ATTR_PORT_ID_TYPE, G_VARIANT_TYPE_UINT32); + g_assert (v_port_id_type); + + v_port_id = g_variant_lookup_value (variant, NM_LLDP_ATTR_PORT_ID, G_VARIANT_TYPE_STRING); + g_assert (v_port_id); + + if ( nm_streq (g_variant_get_string (v_chassis_id, NULL), chassis_id) + && nm_streq (g_variant_get_string (v_port_id, NULL), port_id) + && NM_IN_SET (chassis_id_type, -1, g_variant_get_uint32 (v_chassis_id_type)) + && NM_IN_SET (port_id_type, -1, g_variant_get_uint32 (v_port_id_type))) { + g_assert (!result); + result = variant; + } else + g_variant_unref (variant); + } + + return result; +} + typedef struct { int ifindex; int fd; guint8 mac[ETH_ALEN]; -} test_fixture; +} TestRecvFixture; + +typedef struct { + gsize frame_len; + const uint8_t *frame; +} TestRecvFrame; +#define TEST_RECV_FRAME_DEFINE(name, ...) \ + static const guint8 _##name##_v[] = { __VA_ARGS__ }; \ + static const TestRecvFrame name = { \ + .frame_len = sizeof (_##name##_v), \ + .frame = _##name##_v, \ + } + +typedef struct { + guint expected_num_called; + gsize frames_len; + const TestRecvFrame *frames[10]; + void (*check) (GMainLoop *loop, NMLldpListener *listener); +} TestRecvData; +#define TEST_RECV_DATA_DEFINE(name, _expected_num_called, _check, ...) \ + static const TestRecvData name = { \ + .expected_num_called = _expected_num_called, \ + .check = _check, \ + .frames_len = NM_NARG (__VA_ARGS__), \ + .frames = { __VA_ARGS__ }, \ + } #define TEST_IFNAME "nm-tap-test0" +TEST_RECV_FRAME_DEFINE (_test_recv_data0_frame0, + /* Ethernet header */ + 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC */ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */ + 0x88, 0xcc, /* Ethertype */ + /* LLDP mandatory TLVs */ + 0x02, 0x07, 0x04, 0x00, 0x01, 0x02, /* Chassis: MAC, 00:01:02:03:04:05 */ + 0x03, 0x04, 0x05, + 0x04, 0x04, 0x05, 0x31, 0x2f, 0x33, /* Port: interface name, "1/3" */ + 0x06, 0x02, 0x00, 0x78, /* TTL: 120 seconds */ + /* LLDP optional TLVs */ + 0x08, 0x04, 0x50, 0x6f, 0x72, 0x74, /* Port Description: "Port" */ + 0x0a, 0x03, 0x53, 0x59, 0x53, /* System Name: "SYS" */ + 0x0c, 0x04, 0x66, 0x6f, 0x6f, 0x00, /* System Description: "foo" (NULL-terminated) */ + 0x00, 0x00 /* End Of LLDPDU */ +); + +static void +_test_recv_data0_check (GMainLoop *loop, NMLldpListener *listener) +{ + GVariant *neighbors, *attr; + gs_unref_variant GVariant *neighbor = NULL; + + neighbors = nm_lldp_listener_get_neighbors (listener); + nmtst_assert_variant_is_of_type (neighbors, G_VARIANT_TYPE ("aa{sv}")); + g_assert_cmpint (g_variant_n_children (neighbors), ==, 1); + + neighbor = get_lldp_neighbor (neighbors, + LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS, "00:01:02:03:04:05", + LLDP_PORT_SUBTYPE_INTERFACE_NAME, "1/3"); + g_assert (neighbor); + g_assert_cmpint (g_variant_n_children (neighbor), ==, 4 + 4); + + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_PORT_DESCRIPTION, G_VARIANT_TYPE_STRING); + nmtst_assert_variant_string (attr, "Port"); + nm_clear_g_variant (&attr); + + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_SYSTEM_NAME, G_VARIANT_TYPE_STRING); + nmtst_assert_variant_string (attr, "SYS"); + nm_clear_g_variant (&attr); + + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_DESTINATION, G_VARIANT_TYPE_STRING); + nmtst_assert_variant_string (attr, NM_LLDP_DEST_NEAREST_NON_TPMR_BRIDGE); + nm_clear_g_variant (&attr); + + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_SYSTEM_DESCRIPTION, G_VARIANT_TYPE_STRING); + nmtst_assert_variant_string (attr, "foo"); + nm_clear_g_variant (&attr); +} + +TEST_RECV_DATA_DEFINE (_test_recv_data0, 1, _test_recv_data0_check, &_test_recv_data0_frame0); +TEST_RECV_DATA_DEFINE (_test_recv_data0_twice, 1, _test_recv_data0_check, &_test_recv_data0_frame0, &_test_recv_data0_frame0); + + +TEST_RECV_FRAME_DEFINE (_test_recv_data1_frame0, + /* lldp.detailed.pcap from + * https://wiki.wireshark.org/SampleCaptures#Link_Layer_Discovery_Protocol_.28LLDP.29 */ + + /* ethernet header */ + 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e, /* destination mac */ + 0x00, 0x01, 0x30, 0xf9, 0xad, 0xa0, /* source mac */ + 0x88, 0xcc, /* ethernet type */ + + 0x02, 0x07, 0x04, 0x00, 0x01, 0x30, /* Chassis Subtype */ + 0xf9, 0xad, 0xa0, + 0x04, 0x04, 0x05, 0x31, 0x2f, 0x31, /* Port Subtype */ + 0x06, 0x02, 0x00, 0x78, /* Time To Live */ + 0x08, 0x17, 0x53, 0x75, 0x6d, 0x6d, /* Port Description */ + 0x69, 0x74, 0x33, 0x30, 0x30, 0x2d, + 0x34, 0x38, 0x2d, 0x50, 0x6f, 0x72, + 0x74, 0x20, 0x31, 0x30, 0x30, 0x31, + 0x00, + 0x0a, 0x0d, 0x53, 0x75, 0x6d, 0x6d, /* System Name */ + 0x69, 0x74, 0x33, 0x30, 0x30, 0x2d, + 0x34, 0x38, 0x00, + 0x0c, 0x4c, 0x53, 0x75, 0x6d, 0x6d, /* System Description */ + 0x69, 0x74, 0x33, 0x30, 0x30, 0x2d, + 0x34, 0x38, 0x20, 0x2d, 0x20, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x20, 0x37, 0x2e, 0x34, 0x65, 0x2e, + 0x31, 0x20, 0x28, 0x42, 0x75, 0x69, + 0x6c, 0x64, 0x20, 0x35, 0x29, 0x20, + 0x62, 0x79, 0x20, 0x52, 0x65, 0x6c, + 0x65, 0x61, 0x73, 0x65, 0x5f, 0x4d, + 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, + 0x30, 0x35, 0x2f, 0x32, 0x37, 0x2f, + 0x30, 0x35, 0x20, 0x30, 0x34, 0x3a, + 0x35, 0x33, 0x3a, 0x31, 0x31, 0x00, + 0x0e, 0x04, 0x00, 0x14, 0x00, 0x14, /* Capabilities */ + 0x10, 0x0e, 0x07, 0x06, 0x00, 0x01, /* Management Address */ + 0x30, 0xf9, 0xad, 0xa0, 0x02, 0x00, + 0x00, 0x03, 0xe9, 0x00, + 0xfe, 0x07, 0x00, 0x12, 0x0f, 0x02, /* IEEE 802.3 - Power Via MDI */ + 0x07, 0x01, 0x00, + 0xfe, 0x09, 0x00, 0x12, 0x0f, 0x01, /* IEEE 802.3 - MAC/PHY Configuration/Status */ + 0x03, 0x6c, 0x00, 0x00, 0x10, + 0xfe, 0x09, 0x00, 0x12, 0x0f, 0x03, /* IEEE 802.3 - Link Aggregation */ + 0x01, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x06, 0x00, 0x12, 0x0f, 0x04, /* IEEE 802.3 - Maximum Frame Size */ + 0x05, 0xf2, + 0xfe, 0x06, 0x00, 0x80, 0xc2, 0x01, /* IEEE 802.1 - Port VLAN ID */ + 0x01, 0xe8, + 0xfe, 0x07, 0x00, 0x80, 0xc2, 0x02, /* IEEE 802.1 - Port and Protocol VLAN ID */ + 0x01, 0x00, 0x00, + 0xfe, 0x17, 0x00, 0x80, 0xc2, 0x03, /* IEEE 802.1 - VLAN Name */ + 0x01, 0xe8, 0x10, 0x76, 0x32, 0x2d, + 0x30, 0x34, 0x38, 0x38, 0x2d, 0x30, + 0x33, 0x2d, 0x30, 0x35, 0x30, 0x35, + 0x00, + 0xfe, 0x05, 0x00, 0x80, 0xc2, 0x04, /* IEEE 802.1 - Protocol Identity */ + 0x00, + 0x00, 0x00 /* End of LLDPDU */ +); + static void -fixture_setup (test_fixture *fixture, gconstpointer user_data) +_test_recv_data1_check (GMainLoop *loop, NMLldpListener *listener) +{ + GVariant *neighbors, *attr; + gs_unref_variant GVariant *neighbor = NULL; + + neighbors = nm_lldp_listener_get_neighbors (listener); + nmtst_assert_variant_is_of_type (neighbors, G_VARIANT_TYPE ("aa{sv}")); + g_assert_cmpint (g_variant_n_children (neighbors), ==, 1); + + neighbor = get_lldp_neighbor (neighbors, + LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS, "00:01:30:F9:AD:A0", + LLDP_PORT_SUBTYPE_INTERFACE_NAME, "1/1"); + g_assert (neighbor); + g_assert_cmpint (g_variant_n_children (neighbor), ==, 4 + 10); + + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_DESTINATION, G_VARIANT_TYPE_STRING); + nmtst_assert_variant_string (attr, NM_LLDP_DEST_NEAREST_BRIDGE); + nm_clear_g_variant (&attr); + + /* unsupported: Time To Live */ + + /* Port Description */ + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_PORT_DESCRIPTION, G_VARIANT_TYPE_STRING); + nmtst_assert_variant_string (attr, "Summit300-48-Port 1001"); + nm_clear_g_variant (&attr); + + /* System Name */ + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_SYSTEM_NAME, G_VARIANT_TYPE_STRING); + nmtst_assert_variant_string (attr, "Summit300-48"); + nm_clear_g_variant (&attr); + + /* System Description */ + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_SYSTEM_DESCRIPTION, G_VARIANT_TYPE_STRING); + nmtst_assert_variant_string (attr, "Summit300-48 - Version 7.4e.1 (Build 5) by Release_Master 05/27/05 04:53:11"); + nm_clear_g_variant (&attr); + + /* Capabilities */ + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_SYSTEM_CAPABILITIES, G_VARIANT_TYPE_UINT32); + nmtst_assert_variant_uint32 (attr, 20); + nm_clear_g_variant (&attr); + + /* unsupported: Management Address */ + /* unsupported: IEEE 802.3 - Power Via MDI */ + /* unsupported: IEEE 802.3 - MAC/PHY Configuration/Status */ + /* unsupported: IEEE 802.3 - Link Aggregation */ + /* unsupported: IEEE 802.3 - Maximum Frame Size*/ + + /* IEEE 802.1 - Port VLAN ID */ + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_IEEE_802_1_PVID, G_VARIANT_TYPE_UINT32); + nmtst_assert_variant_uint32 (attr, 488); + nm_clear_g_variant (&attr); + + /* IEEE 802.1 - Port and Protocol VLAN ID */ + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_IEEE_802_1_PPVID, G_VARIANT_TYPE_UINT32); + nmtst_assert_variant_uint32 (attr, 0); + nm_clear_g_variant (&attr); + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_IEEE_802_1_PPVID_FLAGS, G_VARIANT_TYPE_UINT32); + nmtst_assert_variant_uint32 (attr, 1); + nm_clear_g_variant (&attr); + + /* IEEE 802.1 - VLAN Name */ + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_IEEE_802_1_VLAN_NAME, G_VARIANT_TYPE_STRING); + nmtst_assert_variant_string (attr, "v2-0488-03-0505"); + nm_clear_g_variant (&attr); + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_IEEE_802_1_VID, G_VARIANT_TYPE_UINT32); + nmtst_assert_variant_uint32 (attr, 488); + nm_clear_g_variant (&attr); + + /* unsupported: IEEE 802.1 - Protocol Identity */ +} + +TEST_RECV_DATA_DEFINE (_test_recv_data1, 1, _test_recv_data1_check, &_test_recv_data1_frame0); + +TEST_RECV_FRAME_DEFINE (_test_recv_data2_frame0_ttl1, + /* Ethernet header */ + 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC */ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */ + 0x88, 0xcc, /* Ethertype */ + /* LLDP mandatory TLVs */ + 0x02, 0x07, 0x04, 0x00, 0x01, 0x02, /* Chassis: MAC, 00:01:02:03:04:05 */ + 0x03, 0x04, 0x05, + 0x04, 0x04, 0x05, 0x31, 0x2f, 0x33, /* Port: interface name, "1/3" */ + 0x06, 0x02, 0x00, 0x01, /* TTL: 1 seconds */ + /* LLDP optional TLVs */ + 0x08, 0x04, 0x50, 0x6f, 0x72, 0x74, /* Port Description: "Port" */ + 0x0a, 0x03, 0x53, 0x59, 0x53, /* System Name: "SYS" */ + 0x0c, 0x04, 0x66, 0x6f, 0x6f, 0x00, /* System Description: "foo" (NULL-terminated) */ + 0x00, 0x00 /* End Of LLDPDU */ +); + +static void +_test_recv_data2_ttl1_check (GMainLoop *loop, NMLldpListener *listener) +{ + gulong notify_id; + GVariant *neighbors; + + _test_recv_data0_check (loop, listener); + + /* wait for signal. */ + notify_id = g_signal_connect (listener, "notify::" NM_LLDP_LISTENER_NEIGHBORS, + nmtst_main_loop_quit_on_notify, loop); + if (!nmtst_main_loop_run (loop, 5000)) + g_assert_not_reached (); + nm_clear_g_signal_handler (listener, ¬ify_id); + + neighbors = nm_lldp_listener_get_neighbors (listener); + nmtst_assert_variant_is_of_type (neighbors, G_VARIANT_TYPE ("aa{sv}")); + g_assert_cmpint (g_variant_n_children (neighbors), ==, 0); +} + +TEST_RECV_DATA_DEFINE (_test_recv_data2_ttl1, 1, _test_recv_data2_ttl1_check, &_test_recv_data2_frame0_ttl1); + +static void +_test_recv_fixture_setup (TestRecvFixture *fixture, gconstpointer user_data) { const NMPlatformLink *link; struct ifreq ifr = { }; @@ -48,7 +357,7 @@ fixture_setup (test_fixture *fixture, gconstpointer user_data) g_assert (fd >= 0); ifr.ifr_flags = IFF_TAP | IFF_NO_PI; - strncpy (ifr.ifr_name, TEST_IFNAME, IFNAMSIZ); + nm_utils_ifname_cpy (ifr.ifr_name, TEST_IFNAME); g_assert (ioctl (fd, TUNSETIFF, &ifr) >= 0); /* Bring the interface up */ @@ -58,9 +367,7 @@ fixture_setup (test_fixture *fixture, gconstpointer user_data) g_assert (ioctl (s, SIOCSIFFLAGS, &ifr) >= 0); close (s); - nm_platform_process_events (NM_PLATFORM_GET); - link = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, TEST_IFNAME); - g_assert (link); + link = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, TEST_IFNAME, NM_LINK_TYPE_TAP, 100); fixture->ifindex = link->ifindex; fixture->fd = fd; memcpy (fixture->mac, link->addr.data, ETH_ALEN); @@ -68,149 +375,66 @@ fixture_setup (test_fixture *fixture, gconstpointer user_data) typedef struct { int num_called; -} TestInfo; - -static gboolean -loop_quit (gpointer user_data) -{ - g_main_loop_quit ((GMainLoop *) user_data); - return G_SOURCE_REMOVE; -} +} TestRecvCallbackInfo; static void lldp_neighbors_changed (NMLldpListener *lldp_listener, GParamSpec *pspec, gpointer user_data) { - TestInfo *info = user_data; + TestRecvCallbackInfo *info = user_data; info->num_called++; } -static GVariant * -get_lldp_neighbor_attribute (GVariant *neighbors, - const char *chassis, const char *port, - const char *name) -{ - GVariantIter iter, attrs_iter; - GVariant *variant, *attr_variant; - const char *attr_name; - - g_return_val_if_fail (g_variant_is_of_type (neighbors, - G_VARIANT_TYPE ("aa{sv}")), - NULL); - g_variant_iter_init (&iter, neighbors); - - while (g_variant_iter_next (&iter, "@a{sv}", &variant)) { - gs_unref_variant GVariant *chassis_v = NULL; - gs_unref_variant GVariant *port_v = NULL; - gs_unref_variant GVariant *attr_v = NULL; - - g_variant_iter_init (&attrs_iter, variant); - while (g_variant_iter_next (&attrs_iter, "{&sv}", &attr_name, &attr_variant)) { - if (!g_strcmp0 (attr_name, NM_LLDP_ATTR_CHASSIS_ID)) { - g_assert (!chassis_v); - chassis_v = attr_variant; - } else if (!g_strcmp0 (attr_name, NM_LLDP_ATTR_PORT_ID)) { - g_assert (!port_v); - port_v = attr_variant; - } else if (!g_strcmp0 (attr_name, name)) { - g_assert (!attr_v); - attr_v = attr_variant; - } else - g_variant_unref (attr_variant); - } - - g_variant_unref (variant); - - if ( chassis_v - && port_v - && g_variant_is_of_type (chassis_v, G_VARIANT_TYPE_STRING) - && g_variant_is_of_type (port_v, G_VARIANT_TYPE_STRING) - && !g_strcmp0 (chassis, g_variant_get_string (chassis_v, NULL)) - && !g_strcmp0 (port, g_variant_get_string (port_v, NULL))) - return g_variant_ref (attr_v); - } - - /* neighbor not found */ - return NULL; -} - static void -test_receive_frame (test_fixture *fixture, gconstpointer user_data) +test_recv (TestRecvFixture *fixture, gconstpointer user_data) { + const TestRecvData *data = user_data; gs_unref_object NMLldpListener *listener = NULL; GMainLoop *loop; - TestInfo info = { }; - GVariant *neighbors, *attr; - uint8_t frame[] = { - /* Ethernet header */ - 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC */ - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */ - 0x88, 0xcc, /* Ethertype */ - /* LLDP mandatory TLVs */ - 0x02, 0x07, 0x04, 0x00, 0x01, 0x02, /* Chassis: MAC, 00:01:02:03:04:05 */ - 0x03, 0x04, 0x05, - 0x04, 0x04, 0x05, 0x31, 0x2f, 0x33, /* Port: interface name, "1/3" */ - 0x06, 0x02, 0x00, 0x78, /* TTL: 120 seconds */ - /* LLDP optional TLVs */ - 0x08, 0x04, 0x50, 0x6f, 0x72, 0x74, /* Port Description: "Port" */ - 0x0a, 0x03, 0x53, 0x59, 0x53, /* System Name: "SYS" */ - 0x0c, 0x04, 0x66, 0x6f, 0x6f, 0x00, /* System Description: "foo" (NULL-terminated) */ - 0x00, 0x00 /* End Of LLDPDU */ - }; + TestRecvCallbackInfo info = { }; + gsize i_frames; + gulong notify_id; + GError *error = NULL; + guint sd_id; listener = nm_lldp_listener_new (); g_assert (listener != NULL); - g_assert (nm_lldp_listener_start (listener, fixture->ifindex, TEST_IFNAME, fixture->mac, ETH_ALEN, NULL)); + g_assert (nm_lldp_listener_start (listener, fixture->ifindex, &error)); + g_assert_no_error (error); - g_signal_connect (listener, "notify::" NM_LLDP_LISTENER_NEIGHBORS, - (GCallback) lldp_neighbors_changed, &info); + notify_id = g_signal_connect (listener, "notify::" NM_LLDP_LISTENER_NEIGHBORS, + (GCallback) lldp_neighbors_changed, &info); loop = g_main_loop_new (NULL, FALSE); - g_timeout_add_seconds (1, loop_quit, loop); + sd_id = nm_sd_event_attach_default (); + + for (i_frames = 0; i_frames < data->frames_len; i_frames++) { + const TestRecvFrame *f = data->frames[i_frames]; - g_assert (write (fixture->fd, frame, sizeof (frame)) == sizeof (frame)); - g_assert (write (fixture->fd, frame, sizeof (frame)) == sizeof (frame)); + g_assert (write (fixture->fd, f->frame, f->frame_len) == f->frame_len); + } - g_main_loop_run (loop); + if (nmtst_main_loop_run (loop, 500)) + g_assert_not_reached (); - g_assert_cmpint (info.num_called, ==, 1); - neighbors = nm_lldp_listener_get_neighbors (listener); - g_assert (neighbors != NULL); - - /* Check port description */ - attr = get_lldp_neighbor_attribute (neighbors, "00:01:02:03:04:05", "1/3", - NM_LLDP_ATTR_PORT_DESCRIPTION); - g_assert (attr != NULL); - g_assert (g_variant_is_of_type (attr, G_VARIANT_TYPE_STRING)); - g_assert_cmpstr (g_variant_get_string (attr, NULL), ==, "Port"); - nm_clear_g_variant (&attr); + g_assert_cmpint (info.num_called, ==, data->expected_num_called); - /* Check system name */ - attr = get_lldp_neighbor_attribute (neighbors, "00:01:02:03:04:05", "1/3", - NM_LLDP_ATTR_SYSTEM_NAME); - g_assert (attr != NULL); - g_assert (g_variant_is_of_type (attr, G_VARIANT_TYPE_STRING)); - g_assert_cmpstr (g_variant_get_string (attr, NULL), ==, "SYS"); - nm_clear_g_variant (&attr); + nm_clear_g_signal_handler (listener, ¬ify_id); - /* Check destination */ - attr = get_lldp_neighbor_attribute (neighbors, "00:01:02:03:04:05", "1/3", - NM_LLDP_ATTR_DESTINATION); - g_assert (attr != NULL); - g_assert (g_variant_is_of_type (attr, G_VARIANT_TYPE_STRING)); - g_assert_cmpstr (g_variant_get_string (attr, NULL), ==, - NM_LLDP_DEST_NEAREST_NON_TPMR_BRIDGE); - nm_clear_g_variant (&attr); + data->check (loop, listener); + nm_clear_g_source (&sd_id); g_clear_pointer (&loop, g_main_loop_unref); } static void -fixture_teardown (test_fixture *fixture, gconstpointer user_data) +_test_recv_fixture_teardown (TestRecvFixture *fixture, gconstpointer user_data) { nm_platform_link_delete (NM_PLATFORM_GET, fixture->ifindex); } +/*****************************************************************************/ + void init_tests (int *argc, char ***argv) { @@ -220,6 +444,10 @@ init_tests (int *argc, char ***argv) void setup_tests (void) { - g_test_add ("/lldp/receive_frame", test_fixture, NULL, fixture_setup, - test_receive_frame, fixture_teardown); +#define _TEST_ADD_RECV(testpath, testdata) \ + g_test_add (testpath, TestRecvFixture, testdata, _test_recv_fixture_setup, test_recv, _test_recv_fixture_teardown) + _TEST_ADD_RECV ("/lldp/recv/0", &_test_recv_data0); + _TEST_ADD_RECV ("/lldp/recv/0_twice", &_test_recv_data0_twice); + _TEST_ADD_RECV ("/lldp/recv/1", &_test_recv_data1); + _TEST_ADD_RECV ("/lldp/recv/2_ttl1", &_test_recv_data2_ttl1); } diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c index 11da011e..6fbc63a1 100644 --- a/src/devices/wifi/nm-device-olpc-mesh.c +++ b/src/devices/wifi/nm-device-olpc-mesh.c @@ -138,7 +138,8 @@ complete_connection (NMDevice *device, } - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_OLPC_MESH_SETTING_NAME, existing_connections, NULL, diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index da2a0f4a..95a89eab 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -845,7 +845,8 @@ complete_connection (NMDevice *device, str_ssid = nm_utils_ssid_to_utf8 (ssid->data, ssid->len); - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_WIRELESS_SETTING_NAME, existing_connections, str_ssid, @@ -2491,7 +2492,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) if (config == NULL) { _LOGE (LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi) couldn't build wireless configuration: %s", - error ? error->message : "<BUG>"); + error->message); g_clear_error (&error); *reason = NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED; goto out; @@ -2506,7 +2507,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) if (!nm_supplicant_interface_set_config (priv->sup_iface, config, &error)) { _LOGE (LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi) couldn't send wireless configuration to the supplicant: %s", - error ? error->message : "<BUG>"); + error->message); g_clear_error (&error); *reason = NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED; goto out; diff --git a/src/devices/wifi/nm-wifi-ap.c b/src/devices/wifi/nm-wifi-ap.c index 307825c6..a0c25709 100644 --- a/src/devices/wifi/nm-wifi-ap.c +++ b/src/devices/wifi/nm-wifi-ap.c @@ -741,7 +741,7 @@ nm_ap_dump (NMAccessPoint *self, nm_log_dbg (LOGD_WIFI_SCAN, "%s[%s%c] %-32s[%s%u %3u%% %c W:%04X R:%04X] [%3u] %s%s", prefix, - str_if_set (priv->address, "(none)"), + priv->address ?: "(none)", mode_to_char (self), priv->ssid ? nm_utils_escape_ssid (priv->ssid->data, priv->ssid->len) : "(none)", chan > 99 ? "" : (chan > 9 ? " " : " "), diff --git a/src/devices/wifi/tests/test-wifi-ap-utils.c b/src/devices/wifi/tests/test-wifi-ap-utils.c index 01990bee..838368c4 100644 --- a/src/devices/wifi/tests/test-wifi-ap-utils.c +++ b/src/devices/wifi/tests/test-wifi-ap-utils.c @@ -37,7 +37,7 @@ if (expected) { \ if (!success) { \ g_assert (error != NULL); \ - g_warning ("Failed to complete connection: (%d) %s", error->code, error->message); \ + g_warning ("Failed to complete connection: %s", error->message); \ } \ g_assert (success == TRUE); \ g_assert (error == NULL); \ diff --git a/src/devices/wwan/nm-device-modem.c b/src/devices/wwan/nm-device-modem.c index e9c4f02e..a8361c49 100644 --- a/src/devices/wwan/nm-device-modem.c +++ b/src/devices/wwan/nm-device-modem.c @@ -157,8 +157,8 @@ modem_ip4_config_result (NMModem *modem, g_return_if_fail (nm_device_activate_ip4_state_in_conf (device) == TRUE); if (error) { - _LOGW (LOGD_MB | LOGD_IP4, "retrieving IPv4 configuration failed: (%d) %s", - error->code, error->message ? error->message : "(unknown)"); + _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); } else { @@ -184,8 +184,7 @@ 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: (%d) %s", - error->code, error->message ? error->message : "(unknown)"); + _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); return; diff --git a/src/devices/wwan/nm-modem-broadband.c b/src/devices/wwan/nm-modem-broadband.c index 6343416c..769e6a27 100644 --- a/src/devices/wwan/nm-modem-broadband.c +++ b/src/devices/wwan/nm-modem-broadband.c @@ -464,7 +464,7 @@ connect_context_step (NMModemBroadband *self) 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 ? error->message : "unknown error"); + error->message); g_clear_error (&error); g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED); @@ -647,7 +647,8 @@ complete_connection (NMModem *_self, if (!nm_setting_gsm_get_number (s_gsm)) g_object_set (G_OBJECT (s_gsm), NM_SETTING_GSM_NUMBER, "*99#", NULL); - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_GSM_SETTING_NAME, existing_connections, NULL, @@ -670,7 +671,8 @@ complete_connection (NMModem *_self, if (!nm_setting_cdma_get_number (s_cdma)) g_object_set (G_OBJECT (s_cdma), NM_SETTING_CDMA_NUMBER, "#777", NULL); - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_CDMA_SETTING_NAME, existing_connections, NULL, @@ -734,7 +736,7 @@ set_power_state_low_ready (MMModem *modem, /* 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)), - error && error->message ? error->message : "(unknown)"); + NM_G_ERROR_MSG (error)); g_clear_error (&error); } @@ -759,7 +761,7 @@ modem_disable_ready (MMModem *modem_iface, } else { nm_log_warn (LOGD_MB, "(%s): failed to disable modem: %s", nm_modem_get_uid (NM_MODEM (self)), - error && error->message ? error->message : "(unknown)"); + NM_G_ERROR_MSG (error)); nm_modem_set_prev_state (NM_MODEM (self), "disable failed"); g_clear_error (&error); } @@ -778,7 +780,7 @@ modem_enable_ready (MMModem *modem_iface, 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)), - error && error->message ? error->message : "(unknown)"); + NM_G_ERROR_MSG (error)); nm_modem_set_prev_state (NM_MODEM (self), "enable failed"); g_clear_error (&error); } @@ -1259,7 +1261,7 @@ get_sim_ready (MMModem *modem, } else { nm_log_warn (LOGD_MB, "(%s): failed to retrieve SIM object: %s", nm_modem_get_uid (NM_MODEM (self)), - error && error->message ? error->message : "(unknown)"); + NM_G_ERROR_MSG (error)); } g_clear_error (&error); g_object_unref (self); diff --git a/src/devices/wwan/nm-modem-manager.c b/src/devices/wwan/nm-modem-manager.c index 79082c41..e26321b0 100644 --- a/src/devices/wwan/nm-modem-manager.c +++ b/src/devices/wwan/nm-modem-manager.c @@ -145,7 +145,7 @@ modem_object_added (MMManager *modem_manager, handle_new_modem (self, modem); else { nm_log_warn (LOGD_MB, "failed to create modem: %s", - error ? error->message : "(unknown)"); + error->message); } g_clear_error (&error); } diff --git a/src/devices/wwan/nm-modem.c b/src/devices/wwan/nm-modem.c index c1736ecf..2a8a9d1e 100644 --- a/src/devices/wwan/nm-modem.c +++ b/src/devices/wwan/nm-modem.c @@ -545,10 +545,9 @@ ppp_stage3_ip_config_start (NMModem *self, ret = NM_ACT_STAGE_RETURN_POSTPONE; } else { - nm_log_err (LOGD_PPP, "(%s): error starting PPP: (%d) %s", + nm_log_err (LOGD_PPP, "(%s): error starting PPP: %s", nm_modem_get_uid (self), - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); + error->message); g_error_free (error); nm_exported_object_clear_and_unexport (&priv->ppp_manager); diff --git a/src/dhcp-manager/nm-dhcp-client-logging.h b/src/dhcp-manager/nm-dhcp-client-logging.h new file mode 100644 index 00000000..bb4f2f4a --- /dev/null +++ b/src/dhcp-manager/nm-dhcp-client-logging.h @@ -0,0 +1,55 @@ +/* -*- 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) 2016 Red Hat, Inc. + */ + +#ifndef __NETWORKMANAGER_DHCP_CLIENT_LOGGING_H__ +#define __NETWORKMANAGER_DHCP_CLIENT_LOGGING_H__ + +#include "nm-default.h" +#include "nm-dhcp-client.h" + +#define _NMLOG_PREFIX_NAME "dhcp" +#define _NMLOG_DOMAIN LOGD_DHCP +#define _NMLOG(level, ...) \ + G_STMT_START { \ + const NMLogLevel _level = (level); \ + \ + /* we check first for LOGD_DHCP instead of the correct domain. + * In the worst case, we guess wrong and enter the block. + * + * Same for the _NMLOG_ENABLED() macro. Probably it would be more + * expensive to determine the correct value then what we could + * safe. */ \ + if (nm_logging_enabled (_level, _NMLOG_DOMAIN)) { \ + NMDhcpClient *_self = (NMDhcpClient *) (self); \ + const char *__ifname = _self ? nm_dhcp_client_get_iface (_self) : NULL; \ + const NMLogDomain _domain = !_self \ + ? LOGD_DHCP \ + : (nm_dhcp_client_get_ipv6 (_self) ? LOGD_DHCP6 : LOGD_DHCP4); \ + \ + nm_log (_level, _domain, \ + "%s%s%s%s%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, \ + (_domain == LOGD_DHCP4 ? "4" : (_domain == LOGD_DHCP6 ? "6" : "")), \ + NM_PRINT_FMT_QUOTED (__ifname, " (", __ifname, ")", "") \ + _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ + } \ + } G_STMT_END + +#endif /* __NETWORKMANAGER_DHCP_CLIENT_LOGGING_H__ */ diff --git a/src/dhcp-manager/nm-dhcp-client.c b/src/dhcp-manager/nm-dhcp-client.c index 0aeb6118..b8161ab5 100644 --- a/src/dhcp-manager/nm-dhcp-client.c +++ b/src/dhcp-manager/nm-dhcp-client.c @@ -35,6 +35,8 @@ #include "nm-dhcp-utils.h" #include "nm-platform.h" +#include "nm-dhcp-client-logging.h" + typedef struct { char * iface; int ifindex; @@ -204,7 +206,7 @@ state_to_string (NMDhcpState state) } static NMDhcpState -reason_to_state (const char *iface, const char *reason) +reason_to_state (NMDhcpClient *self, const char *iface, const char *reason) { if (g_ascii_strcasecmp (reason, "bound") == 0 || g_ascii_strcasecmp (reason, "bound6") == 0 || @@ -226,7 +228,7 @@ reason_to_state (const char *iface, const char *reason) g_ascii_strcasecmp (reason, "abend") == 0) return NM_DHCP_STATE_FAIL; - nm_log_dbg (LOGD_DHCP, "(%s): unmapped DHCP state '%s'", iface, reason); + _LOGD ("unmapped DHCP state '%s'", reason); return NM_DHCP_STATE_UNKNOWN; } @@ -319,13 +321,10 @@ nm_dhcp_client_set_state (NMDhcpClient *self, event_id = g_strdup_printf ("%s|%s", iaid, start); } - nm_log_info (priv->ipv6 ? LOGD_DHCP6 : LOGD_DHCP4, - "(%s): DHCPv%c state changed %s -> %s%s%s%s", - priv->iface, - priv->ipv6 ? '6' : '4', - state_to_string (priv->state), - state_to_string (new_state), - NM_PRINT_FMT_QUOTED (event_id, ", event ID=\"", event_id, "\"", "")); + _LOGI ("state changed %s -> %s%s%s%s", + state_to_string (priv->state), + state_to_string (new_state), + NM_PRINT_FMT_QUOTED (event_id, ", event ID=\"", event_id, "\"", "")); priv->state = new_state; g_signal_emit (G_OBJECT (self), @@ -343,10 +342,7 @@ transaction_timeout (gpointer user_data) NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self); priv->timeout_id = 0; - nm_log_warn (priv->ipv6 ? LOGD_DHCP6 : LOGD_DHCP4, - "(%s): DHCPv%c request timed out.", - priv->iface, - priv->ipv6 ? '6' : '4'); + _LOGW ("request timed out"); nm_dhcp_client_set_state (self, NM_DHCP_STATE_TIMEOUT, NULL, NULL); return G_SOURCE_REMOVE; } @@ -357,29 +353,20 @@ daemon_watch_cb (GPid pid, gint status, gpointer user_data) NMDhcpClient *self = NM_DHCP_CLIENT (user_data); NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self); NMDhcpState new_state; - guint64 log_domain; - guint ip_ver; g_return_if_fail (priv->watch_id); priv->watch_id = 0; - log_domain = priv->ipv6 ? LOGD_DHCP6 : LOGD_DHCP4; - ip_ver = priv->ipv6 ? 6 : 4; - if (WIFEXITED (status)) - nm_log_info (log_domain, "(%s): DHCPv%d client pid %d exited with status %d", - priv->iface, ip_ver, pid, WEXITSTATUS (status)); + _LOGI ("client pid %d exited with status %d", pid, WEXITSTATUS (status)); else if (WIFSIGNALED (status)) - nm_log_info (log_domain, "(%s): DHCPv%d client pid %d killed by signal %d", - priv->iface, ip_ver, pid, WTERMSIG (status)); + _LOGI ("client pid %d killed by signal %d", pid, WTERMSIG (status)); else if (WIFSTOPPED(status)) - nm_log_info (log_domain, "(%s): DHCPv%d client pid %d stopped by signal %d", - priv->iface, ip_ver, pid, WSTOPSIG (status)); + _LOGI ("client pid %d stopped by signal %d", pid, WSTOPSIG (status)); else if (WIFCONTINUED (status)) - nm_log_info (log_domain, "(%s): DHCPv%d client pid %d resumed (by SIGCONT)", - priv->iface, ip_ver, pid); + _LOGI ("client pid %d resumed (by SIGCONT)", pid); else - nm_log_warn (LOGD_DHCP, "DHCP client died abnormally"); + _LOGW ("client died abnormally"); if (!WIFEXITED (status)) new_state = NM_DHCP_STATE_FAIL; @@ -426,6 +413,7 @@ nm_dhcp_client_start_ip4 (NMDhcpClient *self, const char *last_ip4_address) { NMDhcpClientPrivate *priv; + gs_unref_bytes GBytes *tmp = NULL; g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), FALSE); @@ -434,10 +422,11 @@ nm_dhcp_client_start_ip4 (NMDhcpClient *self, g_return_val_if_fail (priv->ipv6 == FALSE, FALSE); g_return_val_if_fail (priv->uuid != NULL, FALSE); - nm_log_info (LOGD_DHCP, "Activation (%s) Beginning DHCPv4 transaction (timeout in %d seconds)", - priv->iface, priv->timeout); + _LOGI ("activation: beginning transaction (timeout in %d seconds)", priv->timeout); - nm_dhcp_client_set_client_id (self, dhcp_client_id ? nm_dhcp_utils_client_id_string_to_bytes (dhcp_client_id) : NULL); + if (dhcp_client_id) + tmp = nm_dhcp_utils_client_id_string_to_bytes (dhcp_client_id); + nm_dhcp_client_set_client_id (self, tmp); g_clear_pointer (&priv->hostname, g_free); priv->hostname = g_strdup (hostname); @@ -506,7 +495,7 @@ generate_duid_from_machine_id (void) } if (!success) { - nm_log_warn (LOGD_DHCP6, "Failed to read " SYSCONFDIR "/machine-id " + nm_log_warn (LOGD_DHCP6, "dhcp6: failed to read " SYSCONFDIR "/machine-id " "or " LOCALSTATEDIR "/lib/dbus/machine-id to generate " "DHCPv6 DUID; creating non-persistent random DUID."); @@ -546,7 +535,7 @@ get_duid (NMDhcpClient *self) if (nm_logging_enabled (LOGL_DEBUG, LOGD_DHCP6)) { str = nm_dhcp_utils_duid_to_string (duid); - nm_log_dbg (LOGD_DHCP6, "Generated DUID %s", str); + _LOGD ("generated DUID %s", str); g_free (str); } } @@ -583,9 +572,9 @@ nm_dhcp_client_start_ip6 (NMDhcpClient *self, if (!priv->duid) priv->duid = NM_DHCP_CLIENT_GET_CLASS (self)->get_duid (self); - if (nm_logging_enabled (LOGL_DEBUG, LOGD_DHCP)) { + if (nm_logging_enabled (LOGL_DEBUG, LOGD_DHCP6)) { str = nm_dhcp_utils_duid_to_string (priv->duid); - nm_log_dbg (LOGD_DHCP, "(%s): DHCPv6 DUID is '%s'", priv->iface, str); + _LOGD ("DUID is '%s'", str); g_free (str); } @@ -594,8 +583,8 @@ nm_dhcp_client_start_ip6 (NMDhcpClient *self, priv->info_only = info_only; - nm_log_info (LOGD_DHCP, "Activation (%s) Beginning DHCPv6 transaction (timeout in %d seconds)", - priv->iface, priv->timeout); + _LOGI ("activation: beginning transaction (timeout in %d seconds)", + priv->timeout); return NM_DHCP_CLIENT_GET_CLASS (self)->ip6_start (self, dhcp_anycast_addr, @@ -645,8 +634,10 @@ nm_dhcp_client_stop_existing (const char *pid_file, const char *binary_name) } } - if (remove (pid_file) == -1) - nm_log_dbg (LOGD_DHCP, "Could not remove dhcp pid file \"%s\": %d (%s)", pid_file, errno, g_strerror (errno)); + if (remove (pid_file) == -1) { + nm_log_dbg (LOGD_DHCP, "dhcp: could not remove pid file \"%s\": %d (%s)", + pid_file, errno, g_strerror (errno)); + } g_free (proc_path); g_free (pid_contents); @@ -666,11 +657,10 @@ nm_dhcp_client_stop (NMDhcpClient *self, gboolean release) /* Kill the DHCP client */ old_pid = priv->pid; NM_DHCP_CLIENT_GET_CLASS (self)->stop (self, release, priv->duid); - if (old_pid > 0) { - nm_log_info (LOGD_DHCP, "(%s): canceled DHCP transaction, DHCP client pid %d", - priv->iface, old_pid); - } else - nm_log_info (LOGD_DHCP, "(%s): canceled DHCP transaction", priv->iface); + if (old_pid > 0) + _LOGI ("canceled DHCP transaction, DHCP client pid %d", old_pid); + else + _LOGI ("canceled DHCP transaction"); g_assert (priv->pid == -1); nm_dhcp_client_set_state (self, NM_DHCP_STATE_DONE, NULL, NULL); @@ -710,7 +700,7 @@ bytearray_variant_to_string (GVariant *value, const char *key) converted = str->str; if (!g_utf8_validate (converted, -1, NULL)) - nm_log_warn (LOGD_DHCP, "DHCP option '%s' couldn't be converted to UTF-8", key); + nm_log_warn (LOGD_DHCP, "dhcp: option '%s' couldn't be converted to UTF-8", key); g_string_free (str, FALSE); return converted; } @@ -782,9 +772,9 @@ nm_dhcp_client_handle_event (gpointer unused, return FALSE; old_state = priv->state; - new_state = reason_to_state (priv->iface, reason); - nm_log_dbg (LOGD_DHCP, "(%s): DHCP reason '%s' -> state '%s'", - iface, reason, state_to_string (new_state)); + new_state = reason_to_state (self, priv->iface, reason); + _LOGD ("DHCP reason '%s' -> state '%s'", + reason, state_to_string (new_state)); if (new_state == NM_DHCP_STATE_BOUND) { GVariantIter iter; @@ -817,7 +807,7 @@ nm_dhcp_client_handle_event (gpointer unused, /* Fail if no valid IP config was received */ if (ip_config == NULL) { - nm_log_warn (LOGD_DHCP, "(%s): DHCP client bound but IP config not received", iface); + _LOGW ("client bound but IP config not received"); new_state = NM_DHCP_STATE_FAIL; g_clear_pointer (&str_options, g_hash_table_unref); } diff --git a/src/dhcp-manager/nm-dhcp-dhclient.c b/src/dhcp-manager/nm-dhcp-dhclient.c index bc4345fe..4b6d301b 100644 --- a/src/dhcp-manager/nm-dhcp-dhclient.c +++ b/src/dhcp-manager/nm-dhcp-dhclient.c @@ -41,6 +41,7 @@ #include "nm-dhcp-manager.h" #include "NetworkManagerUtils.h" #include "nm-dhcp-listener.h" +#include "nm-dhcp-client-logging.h" G_DEFINE_TYPE (NMDhcpDhclient, nm_dhcp_dhclient, NM_TYPE_DHCP_CLIENT) @@ -148,7 +149,8 @@ nm_dhcp_dhclient_get_lease_ip_configs (const char *iface, } static gboolean -merge_dhclient_config (const char *iface, +merge_dhclient_config (NMDhcpDhclient *self, + const char *iface, const char *conf_file, gboolean is_ip6, GBytes *client_id, @@ -169,8 +171,8 @@ merge_dhclient_config (const char *iface, GError *read_error = NULL; if (!g_file_get_contents (orig_path, &orig, NULL, &read_error)) { - nm_log_warn (LOGD_DHCP, "(%s): error reading dhclient%s configuration %s: %s", - iface, is_ip6 ? "6" : "", orig_path, read_error->message); + _LOGW ("error reading dhclient configuration %s: %s", + orig_path, read_error->message); g_error_free (read_error); } } @@ -185,7 +187,7 @@ merge_dhclient_config (const char *iface, } static char * -find_existing_config (const char *iface, const char *uuid, gboolean ipv6) +find_existing_config (NMDhcpDhclient *self, const char *iface, const char *uuid, gboolean ipv6) { char *path; @@ -195,20 +197,20 @@ find_existing_config (const char *iface, const char *uuid, gboolean ipv6) */ if (uuid) { path = g_strdup_printf (NMCONFDIR "/dhclient%s-%s.conf", ipv6 ? "6" : "", uuid); - nm_log_dbg (ipv6 ? LOGD_DHCP6 : LOGD_DHCP4, "(%s) looking for existing config %s", iface, path); + _LOGD ("looking for existing config %s", path); if (g_file_test (path, G_FILE_TEST_EXISTS)) return path; g_free (path); } path = g_strdup_printf (NMCONFDIR "/dhclient%s-%s.conf", ipv6 ? "6" : "", iface); - nm_log_dbg (ipv6 ? LOGD_DHCP6 : LOGD_DHCP4, "(%s) looking for existing config %s", iface, path); + _LOGD ("looking for existing config %s", path); if (g_file_test (path, G_FILE_TEST_EXISTS)) return path; g_free (path); path = g_strdup_printf (NMCONFDIR "/dhclient%s.conf", ipv6 ? "6" : ""); - nm_log_dbg (ipv6 ? LOGD_DHCP6 : LOGD_DHCP4, "(%s) looking for existing config %s", iface, path); + _LOGD ("looking for existing config %s", path); if (g_file_test (path, G_FILE_TEST_EXISTS)) return path; g_free (path); @@ -222,25 +224,25 @@ find_existing_config (const char *iface, const char *uuid, gboolean ipv6) * (including Fedora) don't even provide a default configuration file. */ path = g_strdup_printf (SYSCONFDIR "/dhcp/dhclient%s-%s.conf", ipv6 ? "6" : "", iface); - nm_log_dbg (ipv6 ? LOGD_DHCP6 : LOGD_DHCP4, "(%s) looking for existing config %s", iface, path); + _LOGD ("looking for existing config %s", path); if (g_file_test (path, G_FILE_TEST_EXISTS)) return path; g_free (path); path = g_strdup_printf (SYSCONFDIR "/dhclient%s-%s.conf", ipv6 ? "6" : "", iface); - nm_log_dbg (ipv6 ? LOGD_DHCP6 : LOGD_DHCP4, "(%s) looking for existing config %s", iface, path); + _LOGD ("looking for existing config %s", path); if (g_file_test (path, G_FILE_TEST_EXISTS)) return path; g_free (path); path = g_strdup_printf (SYSCONFDIR "/dhcp/dhclient%s.conf", ipv6 ? "6" : ""); - nm_log_dbg (ipv6 ? LOGD_DHCP6 : LOGD_DHCP4, "(%s) looking for existing config %s", iface, path); + _LOGD ("looking for existing config %s", path); if (g_file_test (path, G_FILE_TEST_EXISTS)) return path; g_free (path); path = g_strdup_printf (SYSCONFDIR "/dhclient%s.conf", ipv6 ? "6" : ""); - nm_log_dbg (ipv6 ? LOGD_DHCP6 : LOGD_DHCP4, "(%s) looking for existing config %s", iface, path); + _LOGD ("looking for existing config %s", path); if (g_file_test (path, G_FILE_TEST_EXISTS)) return path; g_free (path); @@ -256,7 +258,8 @@ find_existing_config (const char *iface, const char *uuid, gboolean ipv6) * config file along with the NM options. */ static char * -create_dhclient_config (const char *iface, +create_dhclient_config (NMDhcpDhclient *self, + const char *iface, gboolean is_ip6, const char *uuid, GBytes *client_id, @@ -272,26 +275,19 @@ create_dhclient_config (const char *iface, g_return_val_if_fail (iface != NULL, NULL); new = g_strdup_printf (NMSTATEDIR "/dhclient%s-%s.conf", is_ip6 ? "6" : "", iface); - nm_log_dbg (is_ip6 ? LOGD_DHCP6 : LOGD_DHCP4, - "(%s): creating composite dhclient config %s", - iface, new); - - orig = find_existing_config (iface, uuid, is_ip6); - if (orig) { - nm_log_dbg (is_ip6 ? LOGD_DHCP6 : LOGD_DHCP4, - "(%s): merging existing dhclient config %s", - iface, orig); - } else { - nm_log_dbg (is_ip6 ? LOGD_DHCP6 : LOGD_DHCP4, - "(%s): no existing dhclient configuration to merge", - iface); - } + _LOGD ("creating composite dhclient config %s", new); + + orig = find_existing_config (self, iface, uuid, is_ip6); + if (orig) + _LOGD ("merging existing dhclient config %s", orig); + else + _LOGD ("no existing dhclient configuration to merge"); error = NULL; - success = merge_dhclient_config (iface, new, is_ip6, client_id, dhcp_anycast_addr, hostname, fqdn, orig, out_new_client_id, &error); + success = merge_dhclient_config (self, iface, new, is_ip6, client_id, dhcp_anycast_addr, + hostname, fqdn, orig, out_new_client_id, &error); if (!success) { - nm_log_warn (LOGD_DHCP, "(%s): error creating dhclient%s configuration: %s", - iface, is_ip6 ? "6" : "", error->message); + _LOGW ("error creating dhclient configuration: %s", error->message); g_error_free (error); } @@ -307,14 +303,14 @@ dhclient_start (NMDhcpClient *client, gboolean release, pid_t *out_pid) { - NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (client); + NMDhcpDhclient *self = NM_DHCP_DHCLIENT (client); + NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (self); GPtrArray *argv = NULL; pid_t pid; GError *error = NULL; const char *iface, *uuid, *system_bus_address, *dhclient_path = NULL; char *binary_name, *cmd_str, *pid_file = NULL, *system_bus_address_env = NULL; gboolean ipv6, success; - guint log_domain; char *escaped, *preferred_leasefile_path = NULL; g_return_val_if_fail (priv->pid_file == NULL, FALSE); @@ -323,11 +319,9 @@ dhclient_start (NMDhcpClient *client, uuid = nm_dhcp_client_get_uuid (client); ipv6 = nm_dhcp_client_get_ipv6 (client); - log_domain = ipv6 ? LOGD_DHCP6 : LOGD_DHCP4; - dhclient_path = nm_dhcp_dhclient_get_path (); if (!dhclient_path) { - nm_log_warn (log_domain, "dhclient could not be found"); + _LOGW ("dhclient could not be found"); return FALSE; } @@ -362,9 +356,9 @@ dhclient_start (NMDhcpClient *client, priv->lease_file = g_strdup (g_file_get_path (dst)); } else { /* Failure; just use the existing leasefile */ - nm_log_warn (log_domain, "Failed to copy leasefile %s to %s: (%d) %s", - g_file_get_path (src), g_file_get_path (dst), - error->code, error->message); + _LOGW ("failed to copy leasefile %s to %s: %s", + g_file_get_path (src), g_file_get_path (dst), + error->message); g_clear_error (&error); } g_object_unref (src); @@ -378,10 +372,7 @@ dhclient_start (NMDhcpClient *client, success = nm_dhcp_dhclient_save_duid (priv->lease_file, escaped, &error); g_free (escaped); if (!success) { - nm_log_warn (log_domain, "(%s): failed to save DUID to %s: (%d) %s.", - iface, priv->lease_file, - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); + _LOGW ("failed to save DUID to %s: %s", priv->lease_file, error->message); g_free (pid_file); return FALSE; } @@ -437,19 +428,19 @@ dhclient_start (NMDhcpClient *client, g_ptr_array_add (argv, NULL); cmd_str = g_strjoinv (" ", (gchar **) argv->pdata); - nm_log_dbg (log_domain, "running: %s", cmd_str); + _LOGD ("running: %s", cmd_str); g_free (cmd_str); if (g_spawn_async (NULL, (char **) argv->pdata, NULL, G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, nm_utils_setpgid, NULL, &pid, &error)) { g_assert (pid > 0); - nm_log_info (log_domain, "dhclient started with pid %d", pid); + _LOGI ("dhclient started with pid %d", pid); if (release == FALSE) nm_dhcp_client_watch_child (client, pid); priv->pid_file = pid_file; } else { - nm_log_warn (log_domain, "dhclient failed to start: '%s'", error->message); + _LOGW ("dhclient failed to start: '%s'", error->message); g_error_free (error); g_free (pid_file); } @@ -465,7 +456,8 @@ dhclient_start (NMDhcpClient *client, static gboolean ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last_ip4_address) { - NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (client); + NMDhcpDhclient *self = NM_DHCP_DHCLIENT (client); + NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (self); GBytes *client_id; gs_unref_bytes GBytes *new_client_id = NULL; const char *iface, *uuid, *hostname, *fqdn; @@ -477,14 +469,14 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last hostname = nm_dhcp_client_get_hostname (client); fqdn = nm_dhcp_client_get_fqdn (client); - priv->conf_file = create_dhclient_config (iface, FALSE, uuid, client_id, dhcp_anycast_addr, + priv->conf_file = create_dhclient_config (self, iface, FALSE, uuid, client_id, dhcp_anycast_addr, hostname, fqdn, &new_client_id); if (priv->conf_file) { if (new_client_id) nm_dhcp_client_set_client_id (client, new_client_id); success = dhclient_start (client, NULL, NULL, FALSE, NULL); } else - nm_log_warn (LOGD_DHCP4, "(%s): error creating dhclient configuration file.", iface); + _LOGW ("error creating dhclient configuration file"); return success; } @@ -497,16 +489,17 @@ ip6_start (NMDhcpClient *client, NMSettingIP6ConfigPrivacy privacy, const GByteArray *duid) { - NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (client); + NMDhcpDhclient *self = NM_DHCP_DHCLIENT (client); + NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (self); const char *iface, *uuid, *hostname; iface = nm_dhcp_client_get_iface (client); uuid = nm_dhcp_client_get_uuid (client); hostname = nm_dhcp_client_get_hostname (client); - priv->conf_file = create_dhclient_config (iface, TRUE, uuid, NULL, dhcp_anycast_addr, hostname, NULL, NULL); + priv->conf_file = create_dhclient_config (self, iface, TRUE, uuid, NULL, dhcp_anycast_addr, hostname, NULL, NULL); if (!priv->conf_file) { - nm_log_warn (LOGD_DHCP6, "(%s): error creating dhclient6 configuration file.", iface); + _LOGW ("error creating dhclient configuration file"); return FALSE; } @@ -516,17 +509,18 @@ ip6_start (NMDhcpClient *client, static void stop (NMDhcpClient *client, gboolean release, const GByteArray *duid) { - NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (client); + NMDhcpDhclient *self = NM_DHCP_DHCLIENT (client); + NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (self); /* Chain up to parent */ NM_DHCP_CLIENT_CLASS (nm_dhcp_dhclient_parent_class)->stop (client, release, duid); if (priv->conf_file) if (remove (priv->conf_file) == -1) - nm_log_dbg (LOGD_DHCP, "Could not remove dhcp config file \"%s\": %d (%s)", priv->conf_file, errno, g_strerror (errno)); + _LOGD ("could not remove dhcp config file \"%s\": %d (%s)", priv->conf_file, errno, g_strerror (errno)); if (priv->pid_file) { if (remove (priv->pid_file) == -1) - nm_log_dbg (LOGD_DHCP, "Could not remove dhcp pid file \"%s\": %d (%s)", priv->pid_file, errno, g_strerror (errno)); + _LOGD ("could not remove dhcp pid file \"%s\": %d (%s)", priv->pid_file, errno, g_strerror (errno)); g_free (priv->pid_file); priv->pid_file = NULL; } @@ -562,7 +556,8 @@ state_changed (NMDhcpClient *client, static GByteArray * get_duid (NMDhcpClient *client) { - NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (client); + NMDhcpDhclient *self = NM_DHCP_DHCLIENT (client); + NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (self); GByteArray *duid = NULL; char *leasefile; GError *error = NULL; @@ -573,12 +568,12 @@ get_duid (NMDhcpClient *client) TRUE, NULL); if (leasefile) { - nm_log_dbg (LOGD_DHCP, "Looking for DHCPv6 DUID in '%s'.", leasefile); + _LOGD ("looking for DUID in '%s'", leasefile); duid = nm_dhcp_dhclient_read_duid (leasefile, &error); if (error) { - nm_log_warn (LOGD_DHCP, "Failed to read leasefile '%s': (%d) %s", - leasefile, error->code, error->message); + _LOGW ("failed to read leasefile '%s': %s", + leasefile, error->message); g_clear_error (&error); } g_free (leasefile); @@ -586,13 +581,12 @@ get_duid (NMDhcpClient *client) if (!duid && priv->def_leasefile) { /* Otherwise read the default machine-wide DUID */ - nm_log_dbg (LOGD_DHCP, "Looking for default DHCPv6 DUID in '%s'.", priv->def_leasefile); + _LOGD ("looking for default DUID in '%s'", priv->def_leasefile); duid = nm_dhcp_dhclient_read_duid (priv->def_leasefile, &error); if (error) { - nm_log_warn (LOGD_DHCP, "Failed to read leasefile '%s': (%d) %s", - priv->def_leasefile, - error ? error->code : -1, - error ? error->message : "(unknown)"); + _LOGW ("failed to read leasefile '%s': %s", + priv->def_leasefile, + error->message); g_clear_error (&error); } } diff --git a/src/dhcp-manager/nm-dhcp-dhcpcd.c b/src/dhcp-manager/nm-dhcp-dhcpcd.c index 8060cc6a..8bbb6e4c 100644 --- a/src/dhcp-manager/nm-dhcp-dhcpcd.c +++ b/src/dhcp-manager/nm-dhcp-dhcpcd.c @@ -36,6 +36,7 @@ #include "nm-utils.h" #include "NetworkManagerUtils.h" #include "nm-dhcp-listener.h" +#include "nm-dhcp-client-logging.h" G_DEFINE_TYPE (NMDhcpDhcpcd, nm_dhcp_dhcpcd, NM_TYPE_DHCP_CLIENT) @@ -58,7 +59,8 @@ nm_dhcp_dhcpcd_get_path (void) static gboolean ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last_ip4_address) { - NMDhcpDhcpcdPrivate *priv = NM_DHCP_DHCPCD_GET_PRIVATE (client); + NMDhcpDhcpcd *self = NM_DHCP_DHCPCD (client); + NMDhcpDhcpcdPrivate *priv = NM_DHCP_DHCPCD_GET_PRIVATE (self); GPtrArray *argv = NULL; pid_t pid = -1; GError *error = NULL; @@ -77,7 +79,7 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last dhcpcd_path = nm_dhcp_dhcpcd_get_path (); if (!dhcpcd_path) { - nm_log_warn (LOGD_DHCP4, "dhcpcd could not be found"); + _LOGW ("dhcpcd could not be found"); return FALSE; } @@ -134,17 +136,17 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last g_ptr_array_add (argv, NULL); cmd_str = g_strjoinv (" ", (gchar **) argv->pdata); - nm_log_dbg (LOGD_DHCP4, "running: %s", cmd_str); + _LOGD ("running: %s", cmd_str); g_free (cmd_str); if (g_spawn_async (NULL, (char **) argv->pdata, NULL, G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, nm_utils_setpgid, NULL, &pid, &error)) { g_assert (pid > 0); - nm_log_info (LOGD_DHCP4, "dhcpcd started with pid %d", pid); + _LOGI ("dhcpcd started with pid %d", pid); nm_dhcp_client_watch_child (client, pid); } else { - nm_log_warn (LOGD_DHCP4, "dhcpcd failed to start. error: '%s'", error->message); + _LOGW ("dhcpcd failed to start, error: '%s'", error->message); g_error_free (error); } @@ -161,21 +163,24 @@ ip6_start (NMDhcpClient *client, NMSettingIP6ConfigPrivacy privacy, const GByteArray *duid) { - nm_log_warn (LOGD_DHCP6, "the dhcpcd backend does not support IPv6."); + NMDhcpDhcpcd *self = NM_DHCP_DHCPCD (client); + + _LOGW ("the dhcpcd backend does not support IPv6"); return FALSE; } static void stop (NMDhcpClient *client, gboolean release, const GByteArray *duid) { - NMDhcpDhcpcdPrivate *priv = NM_DHCP_DHCPCD_GET_PRIVATE (client); + NMDhcpDhcpcd *self = NM_DHCP_DHCPCD (client); + NMDhcpDhcpcdPrivate *priv = NM_DHCP_DHCPCD_GET_PRIVATE (self); /* Chain up to parent */ NM_DHCP_CLIENT_CLASS (nm_dhcp_dhcpcd_parent_class)->stop (client, release, duid); if (priv->pid_file) { if (remove (priv->pid_file) == -1) - nm_log_dbg (LOGD_DHCP, "Could not remove dhcp pid file \"%s\": %d (%s)", priv->pid_file, errno, g_strerror (errno)); + _LOGD ("could not remove dhcp pid file \"%s\": %d (%s)", priv->pid_file, errno, g_strerror (errno)); } /* FIXME: implement release... */ diff --git a/src/dhcp-manager/nm-dhcp-manager.c b/src/dhcp-manager/nm-dhcp-manager.c index 44c3365d..fe723e96 100644 --- a/src/dhcp-manager/nm-dhcp-manager.c +++ b/src/dhcp-manager/nm-dhcp-manager.c @@ -113,7 +113,7 @@ find_client_desc (const char *name, GType gtype) } static GType -is_client_enabled (const char *name, GError **error) +is_client_enabled (const char *name) { ClientDesc *desc; @@ -121,9 +121,6 @@ is_client_enabled (const char *name, GError **error) if (desc && (!desc->get_path_func || desc->get_path_func())) return desc->gtype; - g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, - _("'%s' support not found or not enabled."), - name); return G_TYPE_INVALID; } @@ -153,28 +150,6 @@ get_client_for_ifindex (NMDhcpManager *manager, int ifindex, gboolean ip6) return NULL; } -static GType -get_client_type (const char *client, GError **error) -{ - GType client_gtype; - - if (client) - client_gtype = is_client_enabled (client, error); - else { - /* Fallbacks */ - client_gtype = is_client_enabled ("dhclient", NULL); - if (client_gtype == G_TYPE_INVALID) - client_gtype = is_client_enabled ("dhcpcd", NULL); - if (client_gtype == G_TYPE_INVALID) - client_gtype = is_client_enabled ("internal", NULL); - if (client_gtype == G_TYPE_INVALID) { - g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, - _("no usable DHCP client could be found.")); - } - } - return client_gtype; -} - static void client_state_changed (NMDhcpClient *client, NMDhcpState state, GObject *ip_config, @@ -237,7 +212,8 @@ client_start (NMDhcpManager *self, priv = NM_DHCP_MANAGER_GET_PRIVATE (self); /* Ensure we have a usable DHCP client */ - g_return_val_if_fail (priv->client_type != 0, NULL); + if (priv->client_type == G_TYPE_INVALID) + return NULL; /* Kill any old client instance */ client = get_client_for_ifindex (self, ifindex, ipv6); @@ -362,6 +338,7 @@ nm_dhcp_manager_get_lease_ip_configs (NMDhcpManager *self, gboolean ipv6, guint32 default_route_metric) { + NMDhcpManagerPrivate *priv; ClientDesc *desc; g_return_val_if_fail (NM_IS_DHCP_MANAGER (self), NULL); @@ -369,7 +346,11 @@ nm_dhcp_manager_get_lease_ip_configs (NMDhcpManager *self, g_return_val_if_fail (ifindex >= -1, NULL); g_return_val_if_fail (uuid != NULL, NULL); - desc = find_client_desc (NULL, NM_DHCP_MANAGER_GET_PRIVATE (self)->client_type); + priv = NM_DHCP_MANAGER_GET_PRIVATE (self); + if (priv->client_type == G_TYPE_INVALID) + return NULL; + + desc = find_client_desc (NULL, priv->client_type); if (desc && desc->get_lease_configs_func) return desc->get_lease_configs_func (iface, ifindex, uuid, ipv6, default_route_metric); return NULL; @@ -385,8 +366,8 @@ nm_dhcp_manager_init (NMDhcpManager *self) NMDhcpManagerPrivate *priv = NM_DHCP_MANAGER_GET_PRIVATE (self); NMConfig *config = nm_config_get (); const char *client; - GError *error = NULL; GSList *iter; + GType type = G_TYPE_INVALID; for (iter = client_descs; iter; iter = iter->next) { ClientDesc *desc = iter->data; @@ -403,16 +384,26 @@ nm_dhcp_manager_init (NMDhcpManager *self) client = "internal"; } - priv->client_type = get_client_type (client, &error); - if (priv->client_type == G_TYPE_INVALID) { - nm_log_warn (LOGD_DHCP, "No usable DHCP client found (%s)! DHCP configurations will fail.", - error->message); - } else { - nm_log_dbg (LOGD_DHCP, "Using DHCP client '%s'", find_client_desc (NULL, priv->client_type)->name); + if (client) + type = is_client_enabled (client); + if (type == G_TYPE_INVALID) { + if (client) + nm_log_warn (LOGD_DHCP, "DHCP client '%s' not available", client); + + type = is_client_enabled ("dhclient"); + if (type == G_TYPE_INVALID) + type = is_client_enabled ("dhcpcd"); + if (type == G_TYPE_INVALID) + type = is_client_enabled ("internal"); } - g_clear_error (&error); + if (type == G_TYPE_INVALID) + nm_log_warn (LOGD_DHCP, "No usable DHCP client found! DHCP configurations will fail"); + else + nm_log_info (LOGD_DHCP, "Using DHCP client '%s'", find_client_desc (NULL, type)->name); + + priv->client_type = type; priv->clients = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) g_object_unref); diff --git a/src/dhcp-manager/nm-dhcp-systemd.c b/src/dhcp-manager/nm-dhcp-systemd.c index b5a3d67c..91fa8803 100644 --- a/src/dhcp-manager/nm-dhcp-systemd.c +++ b/src/dhcp-manager/nm-dhcp-systemd.c @@ -33,11 +33,11 @@ #include "nm-dhcp-utils.h" #include "NetworkManagerUtils.h" #include "nm-platform.h" +#include "nm-dhcp-client-logging.h" #include "sd-dhcp-client.h" #include "sd-dhcp6-client.h" -/* we use a private systemd header, thus need to include nm-sd-adapt.h. */ #include "nm-sd-adapt.h" #include "dhcp-lease-internal.h" @@ -53,6 +53,7 @@ typedef struct { guint request_count; gboolean privacy; + gboolean info_only; } NMDhcpSystemdPrivate; /************************************************************/ @@ -464,15 +465,15 @@ bound4_handle (NMDhcpSystemd *self) GError *error = NULL; int r; - nm_log_dbg (LOGD_DHCP4, "(%s): lease available", iface); - r = sd_dhcp_client_get_lease (priv->client4, &lease); if (r < 0 || !lease) { - nm_log_warn (LOGD_DHCP4, "(%s): no lease!", iface); + _LOGW ("no lease!"); nm_dhcp_client_set_state (NM_DHCP_CLIENT (self), NM_DHCP_STATE_FAIL, NULL, NULL); return; } + _LOGD ("lease available"); + options = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free); ip4_config = lease_to_ip4_config (iface, nm_dhcp_client_get_ifindex (NM_DHCP_CLIENT (self)), @@ -498,7 +499,7 @@ bound4_handle (NMDhcpSystemd *self) G_OBJECT (ip4_config), options); } else { - nm_log_warn (LOGD_DHCP4, "(%s): %s", iface, error->message); + _LOGW ("%s", error->message); nm_dhcp_client_set_state (NM_DHCP_CLIENT (self), NM_DHCP_STATE_FAIL, NULL, NULL); g_clear_error (&error); } @@ -512,11 +513,10 @@ dhcp_event_cb (sd_dhcp_client *client, int event, gpointer user_data) { NMDhcpSystemd *self = NM_DHCP_SYSTEMD (user_data); NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE (self); - const char *iface = nm_dhcp_client_get_iface (NM_DHCP_CLIENT (self)); g_assert (priv->client4 == client); - nm_log_dbg (LOGD_DHCP4, "(%s): DHCPv4 client event %d", iface, event); + _LOGD ("client event %d", event); switch (event) { case SD_DHCP_CLIENT_EVENT_EXPIRED: @@ -531,7 +531,7 @@ dhcp_event_cb (sd_dhcp_client *client, int event, gpointer user_data) bound4_handle (self); break; default: - nm_log_warn (LOGD_DHCP4, "(%s): unhandled DHCP event %d", iface, event); + _LOGW ("unhandled DHCP event %d", event); break; } } @@ -550,7 +550,8 @@ get_arp_type (const GByteArray *hwaddr) static gboolean ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last_ip4_address) { - NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE (client); + NMDhcpSystemd *self = NM_DHCP_SYSTEMD (client); + NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE (self); const char *iface = nm_dhcp_client_get_iface (client); const GByteArray *hwaddr; sd_dhcp_lease *lease = NULL; @@ -571,13 +572,13 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last r = sd_dhcp_client_new (&priv->client4); if (r < 0) { - nm_log_warn (LOGD_DHCP4, "(%s): failed to create DHCPv4 client (%d)", iface, r); + _LOGW ("failed to create client (%d)", r); return FALSE; } r = sd_dhcp_client_attach_event (priv->client4, NULL, 0); if (r < 0) { - nm_log_warn (LOGD_DHCP4, "(%s): failed to attach DHCP event (%d)", iface, r); + _LOGW ("failed to attach event (%d)", r); goto error; } @@ -585,7 +586,7 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last if (hwaddr) { arp_type= get_arp_type (hwaddr); if (arp_type == ARPHRD_NONE) { - nm_log_warn (LOGD_DHCP4, "(%s): failed to determine ARP type", iface); + _LOGW ("failed to determine ARP type"); goto error; } @@ -594,26 +595,26 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last hwaddr->len, arp_type); if (r < 0) { - nm_log_warn (LOGD_DHCP4, "(%s): failed to set DHCP MAC address (%d)", iface, r); + _LOGW ("failed to set MAC address (%d)", r); goto error; } } r = sd_dhcp_client_set_index (priv->client4, nm_dhcp_client_get_ifindex (client)); if (r < 0) { - nm_log_warn (LOGD_DHCP4, "(%s): failed to set DHCP ifindex (%d)", iface, r); + _LOGW ("failed to set ifindex (%d)", r); goto error; } r = sd_dhcp_client_set_callback (priv->client4, dhcp_event_cb, client); if (r < 0) { - nm_log_warn (LOGD_DHCP4, "(%s): failed to set DHCP callback (%d)", iface, r); + _LOGW ("failed to set callback (%d)", r); goto error; } r = sd_dhcp_client_set_request_broadcast (priv->client4, true); if (r < 0) { - nm_log_warn (LOGD_DHCP4, "(%s): failed to set DHCP broadcast (%d)", iface, r); + _LOGW ("failed to enable broadcast mode (%d)", r); goto error; } @@ -627,7 +628,7 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last if (last_addr.s_addr) { r = sd_dhcp_client_set_request_address (priv->client4, &last_addr); if (r < 0) { - nm_log_warn (LOGD_DHCP4, "(%s): failed to set last IPv4 address (%d)", iface, r); + _LOGW ("failed to set last IPv4 address (%d)", r); goto error; } } @@ -675,7 +676,7 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last free (prefix); if (r < 0) { - nm_log_warn (LOGD_DHCP4, "(%s): failed to set DHCP hostname (%d)", iface, r); + _LOGW ("failed to set DHCP hostname (%d)", r); goto error; } } @@ -684,14 +685,14 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last if (fqdn) { r = sd_dhcp_client_set_hostname (priv->client4, fqdn); if (r < 0) { - nm_log_warn (LOGD_DHCP4, "(%s): failed to set DHCP FQDN (%d)", iface, r); + _LOGW ("failed to set DHCP FQDN (%d)", r); goto error; } } r = sd_dhcp_client_start (priv->client4); if (r < 0) { - nm_log_warn (LOGD_DHCP4, "(%s): failed to start DHCP (%d)", iface, r); + _LOGW ("failed to start client (%d)", r); goto error; } @@ -706,13 +707,134 @@ error: return success; } +static NMIP6Config * +lease_to_ip6_config (const char *iface, + int ifindex, + sd_dhcp6_lease *lease, + GHashTable *options, + gboolean log_lease, + gboolean info_only, + GError **error) +{ + struct in6_addr tmp_addr, *dns; + uint32_t lft_pref, lft_valid; + NMIP6Config *ip6_config; + const char *addr_str; + char **domains; + GString *str; + int num, i; + gint32 ts; + + g_return_val_if_fail (lease, NULL); + ip6_config = nm_ip6_config_new (ifindex); + ts = nm_utils_get_monotonic_timestamp_s (); + str = g_string_sized_new (30); + + /* Addresses */ + sd_dhcp6_lease_reset_address_iter (lease); + while (sd_dhcp6_lease_get_address (lease, &tmp_addr, &lft_pref, &lft_valid) >= 0) { + NMPlatformIP6Address address = { + .plen = 128, + .address = tmp_addr, + .timestamp = ts, + .lifetime = lft_valid, + .preferred = lft_pref, + .source = NM_IP_CONFIG_SOURCE_DHCP, + }; + + nm_ip6_config_add_address (ip6_config, &address); + + addr_str = nm_utils_inet6_ntop (&tmp_addr, NULL); + g_string_append_printf (str, "%s%s", str->len ? " " : "", addr_str); + + LOG_LEASE (LOGD_DHCP6, + " address %s", + nm_platform_ip6_address_to_string (&address, NULL, 0)); + }; + + if (str->len) { + add_option (options, dhcp6_requests, DHCP6_OPTION_IP_ADDRESS, str->str); + g_string_set_size (str , 0); + } + + if (!info_only && nm_ip6_config_get_num_addresses (ip6_config) == 0) { + g_string_free (str, TRUE); + g_object_unref (ip6_config); + g_set_error_literal (error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_FAILED, + "no address received in managed mode"); + return NULL; + } + + /* DNS servers */ + num = sd_dhcp6_lease_get_dns (lease, &dns); + if (num > 0) { + for (i = 0; i < num; i++) { + nm_ip6_config_add_nameserver (ip6_config, &dns[i]); + addr_str = nm_utils_inet6_ntop (&dns[i], NULL); + g_string_append_printf (str, "%s%s", str->len ? " " : "", addr_str); + LOG_LEASE (LOGD_DHCP6, " nameserver %s", addr_str); + } + add_option (options, dhcp6_requests, SD_DHCP6_OPTION_DNS_SERVERS, str->str); + g_string_set_size (str, 0); + } + + /* Search domains */ + num = sd_dhcp6_lease_get_domains (lease, &domains); + if (num > 0) { + for (i = 0; i < num; i++) { + nm_ip6_config_add_search (ip6_config, domains[i]); + g_string_append_printf (str, "%s%s", str->len ? " " : "", domains[i]); + LOG_LEASE (LOGD_DHCP6, " domain name '%s'", domains[i]); + } + add_option (options, dhcp6_requests, SD_DHCP6_OPTION_DOMAIN_LIST, str->str); + g_string_set_size (str, 0); + } + + g_string_free (str, TRUE); + + return ip6_config; +} + static void bound6_handle (NMDhcpSystemd *self) { - /* not yet supported... */ - nm_log_warn (LOGD_DHCP6, "(%s): internal DHCP does not yet support DHCPv6", - nm_dhcp_client_get_iface (NM_DHCP_CLIENT (self))); - nm_dhcp_client_set_state (NM_DHCP_CLIENT (self), NM_DHCP_STATE_FAIL, NULL, NULL); + NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE (self); + const char *iface = nm_dhcp_client_get_iface (NM_DHCP_CLIENT (self)); + gs_unref_object NMIP6Config *ip6_config = NULL; + gs_unref_hashtable GHashTable *options = NULL; + gs_free_error GError *error = NULL; + sd_dhcp6_lease *lease; + int r; + + r = sd_dhcp6_client_get_lease (priv->client6, &lease); + if (r < 0 || !lease) { + _LOGW (" no lease!"); + nm_dhcp_client_set_state (NM_DHCP_CLIENT (self), NM_DHCP_STATE_FAIL, NULL, NULL); + return; + } + + _LOGD ("lease available"); + + options = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free); + ip6_config = lease_to_ip6_config (iface, + nm_dhcp_client_get_ifindex (NM_DHCP_CLIENT (self)), + lease, + options, + TRUE, + priv->info_only, + &error); + + if (ip6_config) { + nm_dhcp_client_set_state (NM_DHCP_CLIENT (self), + NM_DHCP_STATE_BOUND, + G_OBJECT (ip6_config), + options); + } else { + _LOGW ("%s", error->message); + nm_dhcp_client_set_state (NM_DHCP_CLIENT (self), NM_DHCP_STATE_FAIL, NULL, NULL); + } } static void @@ -720,11 +842,10 @@ dhcp6_event_cb (sd_dhcp6_client *client, int event, gpointer user_data) { NMDhcpSystemd *self = NM_DHCP_SYSTEMD (user_data); NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE (self); - const char *iface = nm_dhcp_client_get_iface (NM_DHCP_CLIENT (self)); g_assert (priv->client6 == client); - nm_log_dbg (LOGD_DHCP6, "(%s): DHCPv6 client event %d", iface, event); + _LOGD ("client event %d", event); switch (event) { case SD_DHCP6_CLIENT_EVENT_RETRANS_MAX: @@ -738,7 +859,7 @@ dhcp6_event_cb (sd_dhcp6_client *client, int event, gpointer user_data) bound6_handle (self); break; default: - nm_log_warn (LOGD_DHCP6, "(%s): unhandled DHCPv6 event %d", iface, event); + _LOGW ("unhandled event %d", event); break; } } @@ -751,7 +872,8 @@ ip6_start (NMDhcpClient *client, NMSettingIP6ConfigPrivacy privacy, const GByteArray *duid) { - NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE (client); + NMDhcpSystemd *self = NM_DHCP_SYSTEMD (client); + NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE (self); const char *iface = nm_dhcp_client_get_iface (client); const GByteArray *hwaddr; int r, i; @@ -762,10 +884,11 @@ ip6_start (NMDhcpClient *client, g_free (priv->lease_file); priv->lease_file = get_leasefile_path (iface, nm_dhcp_client_get_uuid (client), TRUE); + priv->info_only = info_only; r = sd_dhcp6_client_new (&priv->client6); if (r < 0) { - nm_log_warn (LOGD_DHCP6, "(%s): failed to create DHCPv6 client (%d)", iface, r); + _LOGW ("failed to create client (%d)", r); return FALSE; } @@ -777,13 +900,13 @@ ip6_start (NMDhcpClient *client, duid->data + 2, duid->len - 2); if (r < 0) { - nm_log_warn (LOGD_DHCP6, "(%s): failed to create DHCPv6 client (%d)", iface, r); + _LOGW ("failed to set DUID (%d)", r); return FALSE; } r = sd_dhcp6_client_attach_event (priv->client6, NULL, 0); if (r < 0) { - nm_log_warn (LOGD_DHCP6, "(%s): failed to attach DHCP event (%d)", iface, r); + _LOGW ("failed to attach event (%d)", r); goto error; } @@ -794,20 +917,20 @@ ip6_start (NMDhcpClient *client, hwaddr->len, get_arp_type (hwaddr)); if (r < 0) { - nm_log_warn (LOGD_DHCP6, "(%s): failed to set DHCP MAC address (%d)", iface, r); + _LOGW ("failed to set MAC address (%d)", r); goto error; } } r = sd_dhcp6_client_set_index (priv->client6, nm_dhcp_client_get_ifindex (client)); if (r < 0) { - nm_log_warn (LOGD_DHCP6, "(%s): failed to set DHCP ifindex (%d)", iface, r); + _LOGW ("failed to set ifindex (%d)", r); goto error; } r = sd_dhcp6_client_set_callback (priv->client6, dhcp6_event_cb, client); if (r < 0) { - nm_log_warn (LOGD_DHCP6, "(%s): failed to set DHCP callback (%d)", iface, r); + _LOGW ("failed to set callback (%d)", r); goto error; } @@ -819,13 +942,13 @@ ip6_start (NMDhcpClient *client, r = sd_dhcp6_client_set_local_address (priv->client6, ll_addr); if (r < 0) { - nm_log_warn (LOGD_DHCP6, "(%s): failed to set local address (%d)", iface, r); + _LOGW ("failed to set local address (%d)", r); goto error; } r = sd_dhcp6_client_start (priv->client6); if (r < 0) { - nm_log_warn (LOGD_DHCP6, "(%s): failed to start DHCP (%d)", iface, r); + _LOGW ("failed to start client (%d)", r); goto error; } @@ -840,7 +963,8 @@ error: static void stop (NMDhcpClient *client, gboolean release, const GByteArray *duid) { - NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE (client); + NMDhcpSystemd *self = NM_DHCP_SYSTEMD (client); + NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE (self); int r = 0; if (priv->client4) { @@ -851,12 +975,8 @@ stop (NMDhcpClient *client, gboolean release, const GByteArray *duid) r = sd_dhcp6_client_stop (priv->client6); } - if (r) { - nm_log_warn (priv->client6 ? LOGD_DHCP6 : LOGD_DHCP4, - "(%s): failed to stop DHCP client (%d)", - nm_dhcp_client_get_iface (client), - r); - } + if (r) + _LOGW ("failed to stop client (%d)", r); } /***************************************************/ diff --git a/src/dhcp-manager/tests/test-dhcp-utils.c b/src/dhcp-manager/tests/test-dhcp-utils.c index 38051326..162f2dd4 100644 --- a/src/dhcp-manager/tests/test-dhcp-utils.c +++ b/src/dhcp-manager/tests/test-dhcp-utils.c @@ -331,7 +331,7 @@ test_dhclient_invalid_classless_routes_1 (void) options = fill_table (generic_options, NULL); options = fill_table (data, options); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*ignoring invalid classless static routes*"); ip4_config = nm_dhcp_utils_ip4_config_from_options (1, "eth0", options, 0); g_assert (ip4_config); @@ -362,7 +362,7 @@ test_dhcpcd_invalid_classless_routes_1 (void) options = fill_table (generic_options, NULL); options = fill_table (data, options); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*ignoring invalid classless static routes*"); ip4_config = nm_dhcp_utils_ip4_config_from_options (1, "eth0", options, 0); g_assert (ip4_config); @@ -395,7 +395,7 @@ test_dhclient_invalid_classless_routes_2 (void) options = fill_table (generic_options, NULL); options = fill_table (data, options); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*ignoring invalid classless static routes*"); ip4_config = nm_dhcp_utils_ip4_config_from_options (1, "eth0", options, 0); g_assert (ip4_config); @@ -428,7 +428,7 @@ test_dhcpcd_invalid_classless_routes_2 (void) options = fill_table (generic_options, NULL); options = fill_table (data, options); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*ignoring invalid classless static routes*"); ip4_config = nm_dhcp_utils_ip4_config_from_options (1, "eth0", options, 0); g_assert (ip4_config); @@ -461,7 +461,7 @@ test_dhclient_invalid_classless_routes_3 (void) options = fill_table (generic_options, NULL); options = fill_table (data, options); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*ignoring invalid classless static routes*"); ip4_config = nm_dhcp_utils_ip4_config_from_options (1, "eth0", options, 0); g_assert (ip4_config); @@ -489,7 +489,7 @@ test_dhcpcd_invalid_classless_routes_3 (void) options = fill_table (generic_options, NULL); options = fill_table (data, options); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*DHCP provided invalid classless static route*"); ip4_config = nm_dhcp_utils_ip4_config_from_options (1, "eth0", options, 0); g_assert (ip4_config); @@ -598,7 +598,7 @@ test_invalid_escaped_domain_searches (void) options = fill_table (generic_options, NULL); options = fill_table (data, options); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*invalid domain search*"); ip4_config = nm_dhcp_utils_ip4_config_from_options (1, "eth0", options, 0); g_assert (ip4_config); diff --git a/src/dns-manager/nm-dns-dnsmasq.c b/src/dns-manager/nm-dns-dnsmasq.c index 8663dfd8..460feaac 100644 --- a/src/dns-manager/nm-dns-dnsmasq.c +++ b/src/dns-manager/nm-dns-dnsmasq.c @@ -46,7 +46,20 @@ typedef struct { guint32 foo; } NMDnsDnsmasqPrivate; -/*******************************************/ +/*****************************************************************************/ + +#define _NMLOG_DOMAIN LOGD_DNS +#define _NMLOG_PREFIX_NAME "dnsmasq" +#define _NMLOG(level, ...) \ + G_STMT_START { \ + nm_log ((level), _NMLOG_DOMAIN, \ + "%s[%p]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, \ + (self) \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } G_STMT_END + +/*****************************************************************************/ static gboolean add_ip4_config (GString *str, NMIP4Config *ip4, gboolean split) @@ -246,7 +259,7 @@ update (NMDnsPlugin *plugin, dm_binary = nm_utils_find_helper ("dnsmasq", DNSMASQ_PATH, NULL); if (!dm_binary) { - nm_log_warn (LOGD_DNS, "Could not find dnsmasq binary"); + _LOGW ("could not find dnsmasq binary"); return FALSE; } @@ -283,17 +296,16 @@ update (NMDnsPlugin *plugin, /* Write out the config file */ if (!g_file_set_contents (CONFFILE, conf->str, -1, &error)) { - nm_log_warn (LOGD_DNS, "Failed to write dnsmasq config file %s: (%d) %s", - CONFFILE, - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); + _LOGW ("failed to write dnsmasq config file %s: %s", + CONFFILE, + error->message); g_clear_error (&error); goto out; } ignored = chmod (CONFFILE, 0644); - nm_log_dbg (LOGD_DNS, "dnsmasq local caching DNS configuration:"); - nm_log_dbg (LOGD_DNS, "%s", conf->str); + _LOGD ("dnsmasq local caching DNS configuration:"); + _LOGD ("%s", conf->str); argv[idx++] = dm_binary; argv[idx++] = "--no-resolv"; /* Use only commandline */ @@ -351,18 +363,17 @@ child_quit (NMDnsPlugin *plugin, gint status) if (WIFEXITED (status)) { err = WEXITSTATUS (status); if (err) { - nm_log_warn (LOGD_DNS, "dnsmasq exited with error: %s (%d)", - dm_exit_code_to_msg (err), - err); + _LOGW ("dnsmasq exited with error: %s (%d)", + dm_exit_code_to_msg (err), + err); } else failed = FALSE; - } else if (WIFSTOPPED (status)) { - nm_log_warn (LOGD_DNS, "dnsmasq stopped unexpectedly with signal %d", WSTOPSIG (status)); - } else if (WIFSIGNALED (status)) { - nm_log_warn (LOGD_DNS, "dnsmasq died with signal %d", WTERMSIG (status)); - } else { - nm_log_warn (LOGD_DNS, "dnsmasq died from an unknown cause"); - } + } else if (WIFSTOPPED (status)) + _LOGW ("dnsmasq stopped unexpectedly with signal %d", WSTOPSIG (status)); + else if (WIFSIGNALED (status)) + _LOGW ("dnsmasq died with signal %d", WTERMSIG (status)); + else + _LOGW ("dnsmasq died from an unknown cause"); unlink (CONFFILE); if (failed) diff --git a/src/dns-manager/nm-dns-manager.c b/src/dns-manager/nm-dns-manager.c index 79d345be..ec83e600 100644 --- a/src/dns-manager/nm-dns-manager.c +++ b/src/dns-manager/nm-dns-manager.c @@ -100,14 +100,11 @@ NM_DEFINE_SINGLETON_INSTANCE (NMDnsManager); const NMDnsManager *const __self = (self); \ \ _nm_log (__level, _NMLOG_DOMAIN, 0, \ - "%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ - ((__self == singleton_instance) \ - ? _NMLOG_PREFIX_NAME \ - : ({ \ - g_snprintf (__prefix, sizeof (__prefix), "%s[%p]", _NMLOG_PREFIX_NAME, __self); \ - __prefix; \ - }) \ - ) \ + "%s%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, \ + ((!__self || __self == singleton_instance) \ + ? "" \ + : nm_sprintf_buf (__prefix, "[%p]", __self)) \ _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ } \ } G_STMT_END @@ -128,6 +125,9 @@ typedef struct { NMDnsManagerResolvConfMode resolv_conf_mode; NMDnsManagerResolvConfManager rc_manager; + char *last_mode; + bool last_immutable:1; + bool mode_initialized:1; NMDnsPlugin *plugin; NMConfig *config; @@ -164,6 +164,15 @@ typedef struct { GPtrArray *nis_servers; } NMResolvConfData; +NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_rc_manager_to_string, NMDnsManagerResolvConfManager, + NM_UTILS_LOOKUP_DEFAULT_WARN (NULL), + NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE, "none"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE, "file"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF, "resolvconf"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG, "netconfig"), + NM_UTILS_LOOKUP_ITEM_IGNORE (_NM_DNS_MANAGER_RESOLV_CONF_MAN_INTERNAL_ONLY), +); + static void add_string_item (GPtrArray *array, const char *str) { @@ -406,12 +415,10 @@ dispatch_netconfig (NMDnsManager *self, return SR_SUCCESS; } -static gboolean -write_resolv_conf (FILE *f, - char **searches, - char **nameservers, - char **options, - GError **error) +static char * +create_resolv_conf (char **searches, + char **nameservers, + char **options) { gs_free char *searches_str = NULL; gs_free char *nameservers_str = NULL; @@ -439,9 +446,9 @@ write_resolv_conf (FILE *f, for (i = 0; i < num; i++) { if (i == 3) { g_string_append (str, "# "); - g_string_append (str, _("NOTE: the libc resolver may not support more than 3 nameservers.")); + g_string_append (str, "NOTE: the libc resolver may not support more than 3 nameservers."); g_string_append (str, "\n# "); - g_string_append (str, _("The nameservers listed below may not be recognized.")); + g_string_append (str, "The nameservers listed below may not be recognized."); g_string_append_c (str, '\n'); } @@ -452,10 +459,18 @@ write_resolv_conf (FILE *f, nameservers_str = g_string_free (str, FALSE); } - if (fprintf (f, "# Generated by NetworkManager\n%s%s%s", - searches_str ? searches_str : "", - nameservers_str ? nameservers_str : "", - options_str ? options_str : "") < 0) { + return g_strdup_printf ("# Generated by NetworkManager\n%s%s%s", + searches_str ?: "", + nameservers_str ?: "", + options_str ?: ""); +} + +static gboolean +write_resolv_conf_contents (FILE *f, + const char *content, + GError **error) +{ + if (fprintf (f, "%s", content) < 0) { g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, @@ -467,6 +482,19 @@ write_resolv_conf (FILE *f, return TRUE; } +static gboolean +write_resolv_conf (FILE *f, + char **searches, + char **nameservers, + char **options, + GError **error) +{ + gs_free char *content = NULL; + + content = create_resolv_conf (searches, nameservers, options); + return write_resolv_conf_contents (f, content, error); +} + static SpawnResult dispatch_resolvconf (NMDnsManager *self, char **searches, @@ -539,18 +567,22 @@ update_resolv_conf (NMDnsManager *self, char **nameservers, char **options, GError **error, - gboolean install_etc) + NMDnsManagerResolvConfManager rc_manager) { FILE *f; struct stat st; gboolean success; + gs_free char *content = NULL; + SpawnResult write_file_result = SR_SUCCESS; /* If we are not managing /etc/resolv.conf and it points to * MY_RESOLV_CONF, don't write the private DNS configuration to * MY_RESOLV_CONF otherwise we would overwrite the changes done by * some external application. - */ - if (!install_etc) { + * + * This is the only situation, where we don't try to update our + * internal resolv.conf file. */ + if (rc_manager == _NM_DNS_MANAGER_RESOLV_CONF_MAN_INTERNAL_ONLY) { gs_free char *path = g_file_read_link (_PATH_RESCONF, NULL); if (g_strcmp0 (path, MY_RESOLV_CONF) == 0) { @@ -560,6 +592,18 @@ update_resolv_conf (NMDnsManager *self, } } + content = create_resolv_conf (searches, nameservers, options); + + if (rc_manager == NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE) { + /* we first write to /etc/resolv.conf directly. If that fails, + * we still continue to write to runstatedir but remember the + * error. */ + if (!g_file_set_contents (_PATH_RESCONF, content, -1, error)) { + write_file_result = SR_ERROR; + error = NULL; + } + } + if ((f = fopen (MY_RESOLV_CONF_TMP, "w")) == NULL) { g_set_error (error, NM_MANAGER_ERROR, @@ -570,7 +614,7 @@ update_resolv_conf (NMDnsManager *self, return SR_ERROR; } - success = write_resolv_conf (f, searches, nameservers, options, error); + success = write_resolv_conf_contents (f, content, error); if (fclose (f) < 0) { if (success) { @@ -598,7 +642,10 @@ update_resolv_conf (NMDnsManager *self, return SR_ERROR; } - if (!install_etc) + if (rc_manager == NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE) + return write_file_result; + + if (rc_manager != NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE) return SR_SUCCESS; /* A symlink pointing to NM's own resolv.conf (MY_RESOLV_CONF) is always @@ -920,7 +967,7 @@ update_dns (NMDnsManager *self, nis_domain = rc.nis_domain; /* Let any plugins do their thing first */ - if (update && priv->plugin) { + if (priv->plugin) { NMDnsPlugin *plugin = priv->plugin; const char *plugin_name = nm_dns_plugin_get_name (plugin); GSList *vpn_configs = NULL, *dev_configs = NULL, *other_configs = NULL; @@ -973,7 +1020,8 @@ update_dns (NMDnsManager *self, if (update) { switch (priv->rc_manager) { case NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE: - result = update_resolv_conf (self, searches, nameservers, options, error, TRUE); + case NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE: + result = update_resolv_conf (self, searches, nameservers, options, error, priv->rc_manager); resolv_conf_updated = TRUE; break; case NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF: @@ -990,7 +1038,7 @@ update_dns (NMDnsManager *self, if (result == SR_NOTFOUND) { _LOGD ("update-dns: program not available, writing to resolv.conf"); g_clear_error (error); - result = update_resolv_conf (self, searches, nameservers, options, error, TRUE); + result = update_resolv_conf (self, searches, nameservers, options, error, NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE); resolv_conf_updated = TRUE; } } @@ -998,7 +1046,7 @@ update_dns (NMDnsManager *self, /* Unless we've already done it, update private resolv.conf in NMRUNDIR ignoring any errors */ if (!resolv_conf_updated) - update_resolv_conf (self, searches, nameservers, options, NULL, FALSE); + update_resolv_conf (self, searches, nameservers, options, NULL, _NM_DNS_MANAGER_RESOLV_CONF_MAN_INTERNAL_ONLY); /* signal that resolv.conf was changed */ if (update && result == SR_SUCCESS) @@ -1318,70 +1366,105 @@ nm_dns_manager_end_updates (NMDnsManager *self, const char *func) /******************************************************************/ +static bool +_get_resconf_immutable (int *immutable_cached) +{ + int fd, flags; + int immutable; + + immutable = *immutable_cached; + if (!NM_IN_SET (immutable, FALSE, TRUE)) { + immutable = FALSE; + fd = open (_PATH_RESCONF, O_RDONLY); + if (fd != -1) { + if (ioctl (fd, FS_IOC_GETFLAGS, &flags) != -1) + immutable = NM_FLAGS_HAS (flags, FS_IMMUTABLE_FL); + close (fd); + } + *immutable_cached = immutable; + } + return immutable; +} + NM_DEFINE_SINGLETON_GETTER (NMDnsManager, nm_dns_manager_get, NM_TYPE_DNS_MANAGER); static void init_resolv_conf_mode (NMDnsManager *self) { NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); - const char *mode; - int fd, flags; - - g_clear_object (&priv->plugin); + const char *mode, *mode_unknown; + int immutable = -1; mode = nm_config_data_get_dns_mode (nm_config_get_data (priv->config)); - if (!g_strcmp0 (mode, "none")) { - priv->resolv_conf_mode = NM_DNS_MANAGER_RESOLV_CONF_UNMANAGED; - goto out; + + if ( priv->mode_initialized + && nm_streq0 (mode, priv->last_mode) + && ( nm_streq0 (mode, "none") + || priv->last_immutable == _get_resconf_immutable (&immutable))) { + /* we call init_resolv_conf_mode() on every SIGHUP to possibly reload + * when either "mode" or "immutable" changed. However, we don't want to + * re-create the plugin, when the paramters didn't actually change. So + * detect that we would recreate the same plugin and return early. */ + return; } - fd = open (_PATH_RESCONF, O_RDONLY); - if (fd != -1) { - if (ioctl (fd, FS_IOC_GETFLAGS, &flags) == -1) - flags = 0; - close (fd); + priv->mode_initialized = TRUE; + g_free (priv->last_mode); + priv->last_mode = g_strdup (mode); + priv->last_immutable = FALSE; + g_clear_object (&priv->plugin); + priv->resolv_conf_mode = NM_DNS_MANAGER_RESOLV_CONF_UNMANAGED; - if (flags & FS_IMMUTABLE_FL) { - _LOGI ("set resolv-conf-mode: none -- " _PATH_RESCONF " is immutable"); - priv->resolv_conf_mode = NM_DNS_MANAGER_RESOLV_CONF_UNMANAGED; - return; - } + if (nm_streq0 (mode, "none")) { + _LOGI ("%s%s", "set resolv-conf-mode: ", "none"); + return; } - if (!g_strcmp0 (mode, "dnsmasq")) { - priv->resolv_conf_mode = NM_DNS_MANAGER_RESOLV_CONF_PROXY; - priv->plugin = nm_dns_dnsmasq_new (); - } else if (!g_strcmp0 (mode, "unbound")) { - priv->resolv_conf_mode = NM_DNS_MANAGER_RESOLV_CONF_PROXY; - priv->plugin = nm_dns_unbound_new (); - } else { - priv->resolv_conf_mode = NM_DNS_MANAGER_RESOLV_CONF_EXPLICIT; - if (mode && g_strcmp0 (mode, "default") != 0) { - _LOGW ("set resolve-conf-mode: default -- unknown configuration '%s'", mode); - return; - } - mode = "default"; - } + priv->last_immutable = _get_resconf_immutable (&immutable); + + if (NM_IN_STRSET (mode, "dnsmasq", "unbound")) { + if (!immutable) + priv->resolv_conf_mode = NM_DNS_MANAGER_RESOLV_CONF_PROXY; + if (nm_streq (mode, "dnsmasq")) + priv->plugin = nm_dns_dnsmasq_new (); + else + priv->plugin = nm_dns_unbound_new (); - if (priv->plugin) { g_signal_connect (priv->plugin, NM_DNS_PLUGIN_FAILED, G_CALLBACK (plugin_failed), self); g_signal_connect (priv->plugin, NM_DNS_PLUGIN_CHILD_QUIT, G_CALLBACK (plugin_child_quit), self); + + _NMLOG (immutable ? LOGL_WARN : LOGL_INFO, + "%s%s%s%s%s%s", + "set resolv-conf-mode: ", + immutable ? "none" : mode, + ", plugin=\"", nm_dns_plugin_get_name (priv->plugin), "\"", + immutable ? ", resolv.conf immutable" : ""); + return; } -out: - _LOGI ("set resolv-conf-mode: %s%s%s%s", mode, - NM_PRINT_FMT_QUOTED (priv->plugin, ", plugin=\"", nm_dns_plugin_get_name (priv->plugin), "\"", "")); + if (!immutable) + priv->resolv_conf_mode = NM_DNS_MANAGER_RESOLV_CONF_EXPLICIT; + + mode_unknown = mode && !nm_streq (mode, "default") ? mode : NULL; + _NMLOG (mode_unknown ? LOGL_WARN : LOGL_INFO, + "%s%s%s%s%s%s", + "set resolv-conf-mode: ", + immutable ? "none" : "default", + NM_PRINT_FMT_QUOTED (mode_unknown, " -- unknown configuration '", mode_unknown, "'", ""), + immutable ? ", resolv.conf immutable" : ""); } static void init_resolv_conf_manager (NMDnsManager *self) { NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); - const char *man, *desc = ""; + const char *man; man = nm_config_data_get_rc_manager (nm_config_get_data (priv->config)); if (!g_strcmp0 (man, "none")) priv->rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE; + else if (nm_streq0 (man, "file")) + priv->rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE; else if (!g_strcmp0 (man, "resolvconf")) priv->rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF; else if (!g_strcmp0 (man, "netconfig")) @@ -1398,19 +1481,7 @@ init_resolv_conf_manager (NMDnsManager *self) _LOGW ("unknown resolv.conf manager '%s'", man); } - switch (priv->rc_manager) { - case NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF: - desc = "resolvconf"; - break; - case NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG: - desc = "netconfig"; - break; - case NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE: - desc = "none"; - break; - } - - _LOGI ("using resolv.conf manager '%s'", desc); + _LOGI ("using resolv.conf manager '%s'", _rc_manager_to_string (priv->rc_manager)); } static void @@ -1422,8 +1493,15 @@ config_changed_cb (NMConfig *config, { GError *error = NULL; - if (NM_FLAGS_HAS (changes, NM_CONFIG_CHANGE_DNS_MODE)) + if (NM_FLAGS_ANY (changes, NM_CONFIG_CHANGE_DNS_MODE | + NM_CONFIG_CHANGE_SIGHUP)) { + /* reload the resolv-conf mode also on SIGHUP (when DNS_MODE didn't change). + * The reason is, that the configuration also depends on whether resolv.conf + * is immutable, thus, without the configuration changing, we always want to + * re-configure the mode. */ init_resolv_conf_mode (self); + } + if (NM_FLAGS_HAS (changes, NM_CONFIG_CHANGE_RC_MANAGER)) init_resolv_conf_manager (self); @@ -1474,6 +1552,8 @@ dispose (GObject *object) g_clear_object (&priv->plugin); } + g_clear_pointer (&priv->last_mode, g_free); + /* If we're quitting, leave a valid resolv.conf in place, not one * pointing to 127.0.0.1 if any plugins were active. Thus update * DNS after disposing of all plugins. But if we haven't done any diff --git a/src/dns-manager/nm-dns-manager.h b/src/dns-manager/nm-dns-manager.h index 7a55f1a2..dd5c9e98 100644 --- a/src/dns-manager/nm-dns-manager.h +++ b/src/dns-manager/nm-dns-manager.h @@ -101,7 +101,13 @@ typedef enum { /** * NMDnsManagerResolvConfManager - * @NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE: NM directly writes resolv.conf + * @_NM_DNS_MANAGER_RESOLV_CONF_MAN_INTERNAL_ONLY: dummy-manager + * to not write resolv.conf at all, only the internal file in + * NM's run state directory. + * @NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE: NM writes resolv.conf + * by symlinking it to the run state directory. + * @NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE: Like NONE, but instead of symlinking + * resolv.conf, write it as a file. * @NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF: NM is managing resolv.conf through resolvconf * @NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG: NM is managing resolv.conf @@ -110,7 +116,9 @@ typedef enum { * NMDnsManager's management of resolv.conf */ typedef enum { + _NM_DNS_MANAGER_RESOLV_CONF_MAN_INTERNAL_ONLY, NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE, + NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE, NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF, NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG, } NMDnsManagerResolvConfManager; diff --git a/src/dns-manager/nm-dns-plugin.c b/src/dns-manager/nm-dns-plugin.c index 8313ed13..47322d2a 100644 --- a/src/dns-manager/nm-dns-plugin.c +++ b/src/dns-manager/nm-dns-plugin.c @@ -25,12 +25,12 @@ #include <sys/types.h> #include <sys/wait.h> +#include "nm-core-internal.h" + #include "nm-dns-plugin.h" #include "NetworkManagerUtils.h" typedef struct { - gboolean disposed; - GPid pid; guint watch_id; char *progname; @@ -90,36 +90,60 @@ nm_dns_plugin_get_name (NMDnsPlugin *self) /********************************************/ static void +_clear_pidfile (NMDnsPlugin *self) +{ + NMDnsPluginPrivate *priv = NM_DNS_PLUGIN_GET_PRIVATE (self); + + if (priv->pidfile) { + unlink (priv->pidfile); + g_free (priv->pidfile); + priv->pidfile = NULL; + } +} + +static void kill_existing (const char *progname, const char *pidfile, const char *kill_match) { - char *contents = NULL; glong pid; - char *proc_path = NULL; - char *cmdline_contents = NULL; + gs_free char *contents = NULL; + gs_free char *cmdline_contents = NULL; + guint64 start_time; + char proc_path[256]; + gs_free_error GError *error = NULL; - if (!g_file_get_contents (pidfile, &contents, NULL, NULL)) + if (!pidfile) return; - pid = strtol (contents, NULL, 10); - if (pid < 1 || pid > INT_MAX) + if (!kill_match) + g_return_if_reached (); + + if (!g_file_get_contents (pidfile, &contents, NULL, &error)) { + if (g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) + return; + goto out; + } + + pid = _nm_utils_ascii_str_to_int64 (contents, 10, 2, INT_MAX, -1); + if (pid == -1) goto out; - proc_path = g_strdup_printf ("/proc/%ld/cmdline", pid); + start_time = nm_utils_get_start_time_for_pid (pid, NULL, NULL); + if (start_time == 0) + goto out; + + nm_sprintf_buf (proc_path, "/proc/%ld/cmdline", pid); if (!g_file_get_contents (proc_path, &cmdline_contents, NULL, NULL)) goto out; - if (strstr (cmdline_contents, kill_match)) { - if (kill (pid, 0) == 0) { - nm_log_dbg (LOGD_DNS, "Killing stale %s child process %ld", progname, pid); - kill (pid, SIGKILL); - } - unlink (pidfile); - } + if (!strstr (cmdline_contents, kill_match)) + goto out; + + nm_utils_kill_process_sync (pid, start_time, SIGKILL, LOGD_DNS, + progname ?: "<dns-process>", + 0, 0, 1000); out: - g_free (cmdline_contents); - g_free (proc_path); - g_free (contents); + unlink (pidfile); } static void @@ -133,6 +157,8 @@ watch_cb (GPid pid, gint status, gpointer user_data) g_free (priv->progname); priv->progname = NULL; + _clear_pidfile (self); + g_signal_emit (self, signals[CHILD_QUIT], 0, status); } @@ -153,13 +179,11 @@ nm_dns_plugin_child_spawn (NMDnsPlugin *self, g_free (priv->progname); priv->progname = g_path_get_basename (argv[0]); - if (pidfile) { - g_return_val_if_fail (kill_match != NULL, 0); - kill_existing (priv->progname, pidfile, kill_match); + kill_existing (priv->progname, pidfile, kill_match); - g_free (priv->pidfile); - priv->pidfile = g_strdup (pidfile); - } + g_warn_if_fail (priv->pidfile == NULL); + g_clear_pointer (&priv->pidfile, g_free); + priv->pidfile = g_strdup (pidfile); nm_log_info (LOGD_DNS, "DNS: starting %s...", priv->progname); cmdline = g_strjoinv (" ", (char **) argv); @@ -175,9 +199,8 @@ nm_dns_plugin_child_spawn (NMDnsPlugin *self, nm_log_dbg (LOGD_DNS, "%s started with pid %d", priv->progname, priv->pid); priv->watch_id = g_child_watch_add (priv->pid, (GChildWatchFunc) watch_cb, self); } else { - nm_log_warn (LOGD_DNS, "Failed to spawn %s: (%d) %s", - priv->progname, error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); + nm_log_warn (LOGD_DNS, "Failed to spawn %s: %s", + priv->progname, error->message); g_clear_error (&error); } @@ -198,11 +221,7 @@ nm_dns_plugin_child_kill (NMDnsPlugin *self) priv->progname = NULL; } - if (priv->pidfile) { - unlink (priv->pidfile); - g_free (priv->pidfile); - priv->pidfile = NULL; - } + _clear_pidfile (self); return TRUE; } @@ -218,13 +237,8 @@ static void dispose (GObject *object) { NMDnsPlugin *self = NM_DNS_PLUGIN (object); - NMDnsPluginPrivate *priv = NM_DNS_PLUGIN_GET_PRIVATE (self); - if (!priv->disposed) { - priv->disposed = TRUE; - - nm_dns_plugin_child_kill (self); - } + nm_dns_plugin_child_kill (self); G_OBJECT_CLASS (nm_dns_plugin_parent_class)->dispose (object); } @@ -255,21 +269,21 @@ nm_dns_plugin_class_init (NMDnsPluginClass *plugin_class) /* signals */ signals[FAILED] = - g_signal_new (NM_DNS_PLUGIN_FAILED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMDnsPluginClass, failed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); + g_signal_new (NM_DNS_PLUGIN_FAILED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMDnsPluginClass, failed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); signals[CHILD_QUIT] = - g_signal_new (NM_DNS_PLUGIN_CHILD_QUIT, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMDnsPluginClass, child_quit), - NULL, NULL, - g_cclosure_marshal_VOID__INT, - G_TYPE_NONE, 1, G_TYPE_INT); + g_signal_new (NM_DNS_PLUGIN_CHILD_QUIT, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMDnsPluginClass, child_quit), + NULL, NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); } diff --git a/src/dnsmasq-manager/nm-dnsmasq-manager.c b/src/dnsmasq-manager/nm-dnsmasq-manager.c index 9e388acf..31c1db24 100644 --- a/src/dnsmasq-manager/nm-dnsmasq-manager.c +++ b/src/dnsmasq-manager/nm-dnsmasq-manager.c @@ -34,6 +34,16 @@ #include "NetworkManagerUtils.h" #include "nm-core-internal.h" +#define _NMLOG_DOMAIN LOGD_SHARING +#define _NMLOG_PREFIX_NAME "dnsmasq-manager" +#define _NMLOG(level, ...) \ + G_STMT_START { \ + nm_log ((level), _NMLOG_DOMAIN, \ + "%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME": " \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } G_STMT_END + typedef struct { char *iface; char *pidfile; @@ -181,7 +191,7 @@ dm_exit_code (guint dm_exit_status) break; } - nm_log_warn (LOGD_SHARING, "dnsmasq exited with error: %s (%d)", msg, dm_exit_status); + _LOGW ("dnsmasq exited with error: %s (%d)", msg, dm_exit_status); } static void @@ -196,11 +206,11 @@ dm_watch_cb (GPid pid, gint status, gpointer user_data) if (err != 0) dm_exit_code (err); } else if (WIFSTOPPED (status)) { - nm_log_warn (LOGD_SHARING, "dnsmasq stopped unexpectedly with signal %d", WSTOPSIG (status)); + _LOGW ("dnsmasq stopped unexpectedly with signal %d", WSTOPSIG (status)); } else if (WIFSIGNALED (status)) { - nm_log_warn (LOGD_SHARING, "dnsmasq died with signal %d", WTERMSIG (status)); + _LOGW ("dnsmasq died with signal %d", WTERMSIG (status)); } else { - nm_log_warn (LOGD_SHARING, "dnsmasq died from an unknown cause"); + _LOGW ("dnsmasq died from an unknown cause"); } priv->pid = 0; @@ -269,7 +279,7 @@ create_dm_cmd_line (const char *iface, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, error_desc); - nm_log_warn (LOGD_SHARING, "Failed to find DHCP address ranges: %s", error_desc); + _LOGW ("failed to find DHCP address ranges: %s", error_desc); g_free (error_desc); nm_cmd_line_destroy (cmd); return NULL; @@ -361,10 +371,8 @@ nm_dnsmasq_manager_start (NMDnsMasqManager *manager, g_ptr_array_add (dm_cmd->array, NULL); - nm_log_info (LOGD_SHARING, "Starting dnsmasq..."); - - nm_log_dbg (LOGD_SHARING, "Command line: %s", - (cmd_str = nm_cmd_line_to_str (dm_cmd))); + _LOGI ("starting dnsmasq..."); + _LOGD ("command line: %s", (cmd_str = nm_cmd_line_to_str (dm_cmd))); priv->pid = 0; if (!g_spawn_async (NULL, (char **) dm_cmd->array->pdata, NULL, @@ -374,7 +382,7 @@ nm_dnsmasq_manager_start (NMDnsMasqManager *manager, goto out; } - nm_log_dbg (LOGD_SHARING, "dnsmasq started with pid %d", priv->pid); + _LOGD ("dnsmasq started with pid %d", priv->pid); priv->dm_watch_id = g_child_watch_add (priv->pid, (GChildWatchFunc) dm_watch_cb, manager); diff --git a/src/main-utils.c b/src/main-utils.c index e0f254b7..86242802 100644 --- a/src/main-utils.c +++ b/src/main-utils.c @@ -29,6 +29,7 @@ #include <sys/stat.h> #include <locale.h> +#include <glib/gstdio.h> #include <glib-unix.h> #include <gmodule.h> @@ -112,6 +113,31 @@ nm_main_utils_write_pidfile (const char *pidfile) } void +nm_main_utils_ensure_statedir () +{ + gs_free char *parent = NULL; + int errsv; + + parent = g_path_get_dirname (NMSTATEDIR); + + /* Ensure parent state directories exists */ + if ( parent + && parent[0] == '/' + && parent[1] != '\0' + && g_mkdir_with_parents (parent, 0755) != 0) { + errsv = errno; + fprintf (stderr, "Cannot create parents for '%s': %s", NMSTATEDIR, g_strerror (errsv)); + exit (1); + } + /* Ensure state directory exists */ + if (g_mkdir_with_parents (NMSTATEDIR, 0700) != 0) { + errsv = errno; + fprintf (stderr, "Cannot create '%s': %s", NMSTATEDIR, g_strerror (errsv)); + exit (1); + } +} + +void nm_main_utils_ensure_rundir () { /* Setup runtime directory */ @@ -178,7 +204,7 @@ void nm_main_utils_ensure_root () { if (getuid () != 0) { - fprintf (stderr, _("You must be root to run %s!\n"), str_if_set (g_get_prgname (), "")); + fprintf (stderr, _("You must be root to run %s!\n"), g_get_prgname () ?: ""); exit (1); } } diff --git a/src/main-utils.h b/src/main-utils.h index cae97b57..10ba3135 100644 --- a/src/main-utils.h +++ b/src/main-utils.h @@ -27,6 +27,7 @@ void nm_main_utils_ensure_root (void); void nm_main_utils_setup_signals (GMainLoop *main_loop); +void nm_main_utils_ensure_statedir (void); void nm_main_utils_ensure_rundir (void); gboolean nm_main_utils_write_pidfile (const char *pidfile); diff --git a/src/main.c b/src/main.c index 9495a9ef..4616155d 100644 --- a/src/main.c +++ b/src/main.c @@ -35,9 +35,9 @@ #include <string.h> #include <sys/resource.h> +#include "main-utils.h" #include "nm-dbus-interface.h" #include "NetworkManagerUtils.h" -#include "main-utils.h" #include "nm-manager.h" #include "nm-linux-platform.h" #include "nm-bus-manager.h" @@ -50,6 +50,7 @@ #include "nm-auth-manager.h" #include "nm-core-internal.h" #include "nm-exported-object.h" +#include "nm-sd.h" #if !defined(NM_DIST_VERSION) # define NM_DIST_VERSION VERSION @@ -216,8 +217,7 @@ print_config (NMConfigCmdLineOptions *config_cli) config = nm_config_new (config_cli, NULL, &error); if (config == NULL) { - fprintf (stderr, _("Failed to read configuration: %s\n"), - (error && error->message) ? error->message : _("unknown")); + fprintf (stderr, _("Failed to read configuration: %s\n"), error->message); return 7; } @@ -272,6 +272,7 @@ main (int argc, char *argv[]) gboolean wrote_pidfile = FALSE; char *bad_domains = NULL; NMConfigCmdLineOptions *config_cli; + guint sd_id = 0; nm_g_type_init (); @@ -308,12 +309,7 @@ main (int argc, char *argv[]) nm_main_utils_ensure_not_running_pidfile (global_opt.pidfile); - /* Ensure state directory exists */ - if (g_mkdir_with_parents (NMSTATEDIR, 0755) != 0) { - fprintf (stderr, "Cannot create '%s': %s", NMSTATEDIR, strerror (errno)); - exit (1); - } - + nm_main_utils_ensure_statedir (); nm_main_utils_ensure_rundir (); /* When running from the build directory, determine our build directory @@ -359,9 +355,8 @@ main (int argc, char *argv[]) nm_config_cmd_line_options_free (config_cli); config_cli = NULL; if (config == NULL) { - fprintf (stderr, _("Failed to read configuration: (%d) %s\n"), - error ? error->code : -1, - (error && error->message) ? error->message : _("unknown")); + fprintf (stderr, _("Failed to read configuration: %s\n"), + error->message); exit (1); } @@ -413,10 +408,9 @@ main (int argc, char *argv[]) /* Parse the state file */ if (!parse_state_file (global_opt.state_file, &net_enabled, &wifi_enabled, &wwan_enabled, &error)) { - nm_log_err (LOGD_CORE, "State file %s parsing failed: (%d) %s", + nm_log_err (LOGD_CORE, "State file %s parsing failed: %s", global_opt.state_file, - error ? error->code : -1, - (error && error->message) ? error->message : _("unknown")); + error->message); /* Not a hard failure */ } g_clear_error (&error); @@ -477,8 +471,11 @@ main (int argc, char *argv[]) success = TRUE; - if (configure_and_quit == FALSE) + if (configure_and_quit == FALSE) { + sd_id = nm_sd_event_attach_default (); + g_main_loop_run (main_loop); + } done: nm_exported_object_class_set_quitting (); @@ -489,5 +486,8 @@ done: unlink (global_opt.pidfile); nm_log_info (LOGD_CORE, "exiting (%s)", success ? "success" : "error"); + + nm_clear_g_source (&sd_id); + exit (success ? 0 : 1); } diff --git a/src/nm-activation-request.c b/src/nm-activation-request.c index 17b1d75d..acc3e4ca 100644 --- a/src/nm-activation-request.c +++ b/src/nm-activation-request.c @@ -303,9 +303,8 @@ nm_act_request_set_shared (NMActRequest *req, gboolean shared) nm_log_info (LOGD_SHARING, "Executing: %s", cmd); if (!g_spawn_sync ("/", argv, envp, G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, NULL, NULL, &status, &error)) { - nm_log_warn (LOGD_SHARING, "Error executing command: (%d) %s", - error ? error->code : -1, - (error && error->message) ? error->message : "(unknown)"); + nm_log_warn (LOGD_SHARING, "Error executing command: %s", + error->message); g_clear_error (&error); } else if (WEXITSTATUS (status)) { nm_log_warn (LOGD_SHARING, "** Command returned exit status %d.", diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c index f275b3ef..e9076136 100644 --- a/src/nm-active-connection.c +++ b/src/nm-active-connection.c @@ -59,6 +59,8 @@ typedef struct { NMActiveConnection *master; gboolean master_ready; + NMActiveConnection *parent; + gboolean assumed; NMAuthChain *chain; @@ -98,6 +100,7 @@ enum { enum { DEVICE_CHANGED, DEVICE_METERED_CHANGED, + PARENT_ACTIVE, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; @@ -678,6 +681,69 @@ nm_active_connection_get_assumed (NMActiveConnection *self) /****************************************************************/ +static void unwatch_parent (NMActiveConnection *self); + +static void +parent_destroyed (gpointer user_data, GObject *parent) +{ + NMActiveConnection *self = user_data; + + unwatch_parent (self); + g_signal_emit (self, signals[PARENT_ACTIVE], 0, NULL); +} + +static void +parent_state_cb (NMActiveConnection *parent_ac, + GParamSpec *pspec, + gpointer user_data) +{ + NMActiveConnection *self = user_data; + NMActiveConnectionState parent_state = nm_active_connection_get_state (parent_ac); + + if (parent_state < NM_ACTIVE_CONNECTION_STATE_ACTIVATED) + return; + + unwatch_parent (self); + g_signal_emit (self, signals[PARENT_ACTIVE], 0, parent_ac); +} + +static void +unwatch_parent (NMActiveConnection *self) +{ + NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self); + + g_signal_handlers_disconnect_by_func (priv->parent, + (GCallback) parent_state_cb, + self); + g_object_weak_unref ((GObject *) priv->parent, parent_destroyed, self); + priv->parent = NULL; +} + +/** + * nm_active_connection_set_parent: + * @self: the #NMActiveConnection + * @parent: The #NMActiveConnection that must be active before the manager + * can proceed progressing the device to disconnected state for us. + * + * Sets the parent connection of @self. A "parent-active" signal will be + * emitted when the parent connection becomes active. + */ +void +nm_active_connection_set_parent (NMActiveConnection *self, NMActiveConnection *parent) +{ + NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self); + + g_return_if_fail (priv->parent == NULL); + priv->parent = parent; + g_signal_connect (priv->parent, + "notify::" NM_ACTIVE_CONNECTION_STATE, + (GCallback) parent_state_cb, + self); + g_object_weak_ref ((GObject *) priv->parent, parent_destroyed, self); +} + +/****************************************************************/ + static void auth_done (NMAuthChain *chain, GError *error, @@ -1028,6 +1094,10 @@ dispose (GObject *object) self); } g_clear_object (&priv->master); + + if (priv->parent) + unwatch_parent (self); + g_clear_object (&priv->subject); G_OBJECT_CLASS (nm_active_connection_parent_class)->dispose (object); @@ -1208,6 +1278,14 @@ nm_active_connection_class_init (NMActiveConnectionClass *ac_class) NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_UINT); + signals[PARENT_ACTIVE] = + g_signal_new (NM_ACTIVE_CONNECTION_PARENT_ACTIVE, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMActiveConnectionClass, parent_active), + NULL, NULL, NULL, + G_TYPE_NONE, 1, NM_TYPE_ACTIVE_CONNECTION); + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (ac_class), NMDBUS_TYPE_ACTIVE_CONNECTION_SKELETON, NULL); diff --git a/src/nm-active-connection.h b/src/nm-active-connection.h index a7b3d0cd..a66f8e9f 100644 --- a/src/nm-active-connection.h +++ b/src/nm-active-connection.h @@ -58,6 +58,7 @@ /* Internal signals*/ #define NM_ACTIVE_CONNECTION_DEVICE_CHANGED "device-changed" #define NM_ACTIVE_CONNECTION_DEVICE_METERED_CHANGED "device-metered-changed" +#define NM_ACTIVE_CONNECTION_PARENT_ACTIVE "parent-active" struct _NMActiveConnection { NMExportedObject parent; @@ -81,6 +82,8 @@ typedef struct { void (*device_metered_changed) (NMActiveConnection *connection, NMMetered new_value); + + void (*parent_active) (NMActiveConnection *connection); } NMActiveConnectionClass; guint64 nm_active_connection_version_id_get (NMActiveConnection *self); @@ -148,6 +151,9 @@ gboolean nm_active_connection_get_master_ready (NMActiveConnection *self); void nm_active_connection_set_master (NMActiveConnection *self, NMActiveConnection *master); +void nm_active_connection_set_parent (NMActiveConnection *self, + NMActiveConnection *parent); + void nm_active_connection_set_assumed (NMActiveConnection *self, gboolean assumed); diff --git a/src/nm-audit-manager.c b/src/nm-audit-manager.c index b4cfb20b..728575f6 100644 --- a/src/nm-audit-manager.c +++ b/src/nm-audit-manager.c @@ -34,6 +34,15 @@ #define AUDIT_LOG_LEVEL LOGL_INFO +#define _NMLOG_PREFIX_NAME "audit" +#define _NMLOG(level, domain, ...) \ + G_STMT_START { \ + nm_log ((level), (domain), \ + "%s" _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ + _NMLOG_PREFIX_NAME": " \ + _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ + } G_STMT_END + typedef enum { BACKEND_LOG = (1 << 0), BACKEND_AUDITD = (1 << 1), @@ -154,7 +163,7 @@ nm_audit_log (NMAuditManager *self, GPtrArray *fields, const char *file, if (nm_logging_enabled (AUDIT_LOG_LEVEL, LOGD_AUDIT)) { msg = build_message (fields, BACKEND_LOG); - _nm_log_impl (file, line, func, AUDIT_LOG_LEVEL, LOGD_AUDIT, 0, "%s", msg); + _NMLOG (AUDIT_LOG_LEVEL, LOGD_AUDIT, "%s", msg); g_free (msg); } } @@ -306,17 +315,16 @@ init_auditd (NMAuditManager *self) NM_CONFIG_DEFAULT_LOGGING_AUDIT)) { if (priv->auditd_fd < 0) { priv->auditd_fd = audit_open (); - if (priv->auditd_fd < 0) { - nm_log_err (LOGD_CORE, "failed to open auditd socket: %s", - strerror (errno)); - } else - nm_log_dbg (LOGD_CORE, "audit socket created"); + if (priv->auditd_fd < 0) + _LOGE (LOGD_CORE, "failed to open auditd socket: %s", strerror (errno)); + else + _LOGD (LOGD_CORE, "socket created"); } } else { if (priv->auditd_fd >= 0) { audit_close (priv->auditd_fd); priv->auditd_fd = -1; - nm_log_dbg (LOGD_CORE, "audit socket closed"); + _LOGD (LOGD_CORE, "socket closed"); } } } diff --git a/src/nm-auth-utils.c b/src/nm-auth-utils.c index e741546b..928e88b0 100644 --- a/src/nm-auth-utils.c +++ b/src/nm-auth-utils.c @@ -335,8 +335,8 @@ pk_call_cb (GObject *object, GAsyncResult *result, gpointer user_data) } if (error) { - nm_log_warn (LOGD_CORE, "error requesting auth for %s: (%d) %s", - call->permission, error->code, error->message); + nm_log_warn (LOGD_CORE, "error requesting auth for %s: %s", + call->permission, error->message); if (!call->chain->error) { call->chain->error = error; diff --git a/src/nm-bus-manager.c b/src/nm-bus-manager.c index b6245b24..656e7dbf 100644 --- a/src/nm-bus-manager.c +++ b/src/nm-bus-manager.c @@ -34,6 +34,16 @@ #include "nm-exported-object.h" #include "NetworkManagerUtils.h" +#define _NMLOG_DOMAIN LOGD_CORE +#define _NMLOG_PREFIX_NAME "bus-manager" +#define _NMLOG(level, ...) \ + G_STMT_START { \ + nm_log ((level), _NMLOG_DOMAIN, \ + "%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME": " \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } G_STMT_END + enum { DBUS_CONNECTION_CHANGED = 0, PRIVATE_CONNECTION_NEW, @@ -100,7 +110,7 @@ nm_bus_manager_setup (NMBusManager *instance) already_setup = TRUE; singleton_instance = instance; nm_singleton_instance_register (); - nm_log_dbg (LOGD_CORE, "setup %s singleton (%p)", "NMBusManager", singleton_instance); + _LOGD ("setup %s singleton (%p)", "NMBusManager", singleton_instance); } /**************************************************************/ @@ -176,8 +186,7 @@ private_server_closed_connection (GDBusConnection *conn, CloseConnectionInfo *info; /* Clean up after the connection */ - nm_log_dbg (LOGD_CORE, "(%s) closed connection %p on private socket.", - s->tag, conn); + _LOGD ("(%s) closed connection %p on private socket", s->tag, conn); info = g_slice_new0 (CloseConnectionInfo); info->connection = conn; @@ -210,8 +219,7 @@ private_server_new_connection (GDBusServer *server, g_dbus_object_manager_server_set_connection (manager, conn); g_hash_table_insert (s->obj_managers, manager, sender); - nm_log_dbg (LOGD_CORE, "(%s) accepted connection %p on private socket.", - s->tag, conn); + _LOGD ("(%s) accepted connection %p on private socket", s->tag, conn); /* Emit this for the manager */ g_signal_emit (s->manager, @@ -256,7 +264,7 @@ private_server_new (const char *path, unlink (path); address = g_strdup_printf ("unix:path=%s", path); - nm_log_dbg (LOGD_CORE, "(%s) creating private socket %s.", tag, address); + _LOGD ("(%s) creating private socket %s", tag, address); guid = g_dbus_generate_guid (); auth_observer = g_dbus_auth_observer_new (); @@ -271,8 +279,8 @@ private_server_new (const char *path, g_object_unref (auth_observer); if (!server) { - nm_log_warn (LOGD_CORE, "(%s) failed to set up private socket %s: %s", - tag, address, error->message); + _LOGW ("(%s) failed to set up private socket %s: %s", + tag, address, error->message); g_error_free (error); g_free (address); return NULL; @@ -379,7 +387,7 @@ _bus_get_unix_pid (NMBusManager *self, GError **error) { guint32 unix_pid = G_MAXUINT32; - GVariant *ret; + gs_unref_variant GVariant *ret = NULL; ret = _nm_dbus_proxy_call_sync (NM_BUS_MANAGER_GET_PRIVATE (self)->proxy, "GetConnectionUnixProcessID", @@ -403,7 +411,7 @@ _bus_get_unix_user (NMBusManager *self, GError **error) { guint32 unix_uid = G_MAXUINT32; - GVariant *ret; + gs_unref_variant GVariant *ret = NULL; ret = _nm_dbus_proxy_call_sync (NM_BUS_MANAGER_GET_PRIVATE (self)->proxy, "GetConnectionUnixUser", @@ -547,8 +555,8 @@ nm_bus_manager_get_unix_user (NMBusManager *self, /* Otherwise, a bus connection */ if (!_bus_get_unix_user (self, sender, out_uid, &error)) { - nm_log_warn (LOGD_CORE, "Failed to get unix user for dbus sender '%s': %s", - sender, error->message); + _LOGW ("failed to get unix user for dbus sender '%s': %s", + sender, error->message); g_error_free (error); return FALSE; } @@ -661,7 +669,7 @@ nm_bus_manager_reconnect (gpointer user_data) if (nm_bus_manager_init_bus (self)) { if (nm_bus_manager_start_service (self)) { - nm_log_info (LOGD_CORE, "reconnected to the system bus."); + _LOGI ("reconnected to the system bus"); g_signal_emit (self, signals[DBUS_CONNECTION_CHANGED], 0, priv->connection); priv->reconnect_id = 0; @@ -695,7 +703,7 @@ closed_cb (GDBusConnection *connection, NMBusManager *self = NM_BUS_MANAGER (user_data); /* Clean up existing connection */ - nm_log_warn (LOGD_CORE, "disconnected by the system bus."); + _LOGW ("disconnected by the system bus"); nm_bus_manager_cleanup (self); @@ -711,7 +719,7 @@ nm_bus_manager_init_bus (NMBusManager *self) GError *error = NULL; if (priv->connection) { - nm_log_warn (LOGD_CORE, "DBus Manager already has a valid connection."); + _LOGW ("DBus Manager already has a valid connection"); return FALSE; } @@ -721,9 +729,9 @@ nm_bus_manager_init_bus (NMBusManager *self) * environments (eg, initrd) where we only want to use the private * socket. */ - nm_log_info (LOGD_CORE, "Could not connect to the system bus (%s); only the " - "private D-Bus socket will be available.", - error->message); + _LOGI ("could not connect to the system bus (%s); only the " + "private D-Bus socket will be available", + error->message); g_error_free (error); return FALSE; } @@ -742,9 +750,9 @@ nm_bus_manager_init_bus (NMBusManager *self) NULL, &error); if (!priv->proxy) { g_clear_object (&priv->connection); - nm_log_warn (LOGD_CORE, "Could not create org.freedesktop.DBus proxy (%s); only the " - "private D-Bus socket will be available.", - error->message); + _LOGW ("could not create org.freedesktop.DBus proxy (%s); only the " + "private D-Bus socket will be available", + error->message); g_error_free (error); return FALSE; } @@ -761,7 +769,7 @@ gboolean nm_bus_manager_start_service (NMBusManager *self) { NMBusManagerPrivate *priv; - GVariant *ret; + gs_unref_variant GVariant *ret = NULL; int result; GError *err = NULL; @@ -770,7 +778,7 @@ nm_bus_manager_start_service (NMBusManager *self) priv = NM_BUS_MANAGER_GET_PRIVATE (self); if (priv->started) { - nm_log_err (LOGD_CORE, "Service has already started."); + _LOGE ("service has already started"); return FALSE; } @@ -787,8 +795,7 @@ nm_bus_manager_start_service (NMBusManager *self) G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err); if (!ret) { - nm_log_err (LOGD_CORE, "Could not acquire the NetworkManager service.\n" - " Error: '%s'", err->message); + _LOGE ("could not acquire the NetworkManager service: '%s'", err->message); g_error_free (err); return FALSE; } @@ -796,7 +803,7 @@ nm_bus_manager_start_service (NMBusManager *self) g_variant_get (ret, "(u)", &result); if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { - nm_log_err (LOGD_CORE, "Could not acquire the NetworkManager service as it is already taken."); + _LOGE ("could not acquire the NetworkManager service as it is already taken"); return FALSE; } @@ -940,8 +947,8 @@ nm_bus_manager_new_proxy (NMBusManager *self, "g-interface-name", iface, NULL); if (!proxy) { - nm_log_warn (LOGD_CORE, "Could not create proxy for %s on connection %s: %s", - iface, name, error->message); + _LOGW ("could not create proxy for %s on connection %s: %s", + iface, name, error->message); g_error_free (error); } return proxy; diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c index a7d85c29..b98b6e8a 100644 --- a/src/nm-core-utils.c +++ b/src/nm-core-utils.c @@ -109,39 +109,6 @@ _nm_utils_set_testing (NMUtilsTestFlags flags) /*****************************************************************************/ -G_DEFINE_QUARK (nm-utils-error-quark, nm_utils_error) - -void -nm_utils_error_set_cancelled (GError **error, - gboolean is_disposing, - const char *instance_name) -{ - if (is_disposing) { - g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_CANCELLED_DISPOSING, - "Disposing %s instance", - instance_name && *instance_name ? instance_name : "source"); - } else { - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANCELLED, - "Request cancelled"); - } -} - -gboolean -nm_utils_error_is_cancelled (GError *error, - gboolean consider_is_disposing) -{ - if (error) { - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - return TRUE; - if ( consider_is_disposing - && g_error_matches (error, NM_UTILS_ERROR, NM_UTILS_ERROR_CANCELLED_DISPOSING)) - return TRUE; - } - return FALSE; -} - -/*****************************************************************************/ - static GSList *_singletons = NULL; static gboolean _singletons_shutdown = FALSE; @@ -454,10 +421,11 @@ nm_utils_modprobe (GError **error, gboolean suppress_error_logging, const char * nm_log (llevel, LOGD_CORE, "modprobe: '%s' failed: %s", ARGV_TO_STR (argv), local->message); g_propagate_error (error, local); return -1; - } else if (exit_status != 0) + } else if (exit_status != 0) { nm_log (llevel, LOGD_CORE, "modprobe: '%s' exited with error %d%s%s%s%s%s%s", ARGV_TO_STR (argv), exit_status, std_out&&*std_out ? " (" : "", std_out&&*std_out ? _trunk_first_line (std_out) : "", std_out&&*std_out ? ")" : "", std_err&&*std_err ? " (" : "", std_err&&*std_err ? _trunk_first_line (std_err) : "", std_err&&*std_err ? ")" : ""); + } return exit_status; } @@ -1008,7 +976,6 @@ nm_utils_kill_process_sync (pid_t pid, guint64 start_time, int sig, NMLogDomain g_return_if_fail (pid > 0); g_return_if_fail (log_name != NULL); - g_return_if_fail (wait_before_kill_msec > 0); start_time0 = nm_utils_get_start_time_for_pid (pid, &p_state, NULL); if (start_time0 == 0) { @@ -1046,12 +1013,12 @@ nm_utils_kill_process_sync (pid_t pid, guint64 start_time, int sig, NMLogDomain return; } - /* wait for the process to terminated... */ + /* wait for the process to terminate... */ wait_start_us = nm_utils_get_monotonic_timestamp_us (); sleep_duration_usec = _sleep_duration_convert_ms_to_us (sleep_duration_msec); - if (sig != SIGKILL) + if (sig != SIGKILL && wait_before_kill_msec) wait_until_sigkill = wait_start_us + (((gint64) wait_before_kill_msec) * 1000L); else wait_until_sigkill = 0; @@ -2507,8 +2474,8 @@ _get_property_path (const char *ifname, static char path[sizeof (IPV6_PROPERTY_DIR) + IFNAMSIZ + 32]; int len; - ifname = ASSERT_VALID_PATH_COMPONENT (ifname); - property = ASSERT_VALID_PATH_COMPONENT (property); + ifname = NM_ASSERT_VALID_PATH_COMPONENT (ifname); + property = NM_ASSERT_VALID_PATH_COMPONENT (property); len = g_snprintf (path, sizeof (path), @@ -2573,7 +2540,7 @@ nm_utils_is_valid_path_component (const char *name) } const char * -ASSERT_VALID_PATH_COMPONENT (const char *name) +NM_ASSERT_VALID_PATH_COMPONENT (const char *name) { if (G_LIKELY (nm_utils_is_valid_path_component (name))) return name; @@ -2941,4 +2908,113 @@ nm_utils_parse_debug_string (const char *string, return result; } +/*****************************************************************************/ + +void +nm_utils_ifname_cpy (char *dst, const char *name) +{ + g_return_if_fail (dst); + g_return_if_fail (name && name[0]); + + nm_assert (nm_utils_iface_valid_name (name)); + + if (g_strlcpy (dst, name, IFNAMSIZ) >= IFNAMSIZ) + g_return_if_reached (); +} + +/*****************************************************************************/ + +#define IPV4LL_NETWORK (htonl (0xA9FE0000L)) +#define IPV4LL_NETMASK (htonl (0xFFFF0000L)) + +gboolean +nm_utils_ip4_address_is_link_local (in_addr_t addr) +{ + return (addr & IPV4LL_NETMASK) == IPV4LL_NETWORK; +} + +/*****************************************************************************/ + +/** + * Takes a pair @timestamp and @duration, and returns the remaining duration based + * on the new timestamp @now. + */ +guint32 +nm_utils_lifetime_rebase_relative_time_on_now (guint32 timestamp, + guint32 duration, + gint32 now) +{ + gint64 t; + + nm_assert (now >= 0); + + if (duration == NM_PLATFORM_LIFETIME_PERMANENT) + return NM_PLATFORM_LIFETIME_PERMANENT; + + if (timestamp == 0) { + /* if the @timestamp is zero, assume it was just left unset and that the relative + * @duration starts counting from @now. This is convenient to construct an address + * and print it in nm_platform_ip4_address_to_string(). + * + * In general it does not make sense to set the @duration without anchoring at + * @timestamp because you don't know the absolute expiration time when looking + * at the address at a later moment. */ + timestamp = now; + } + + /* For timestamp > now, just accept it and calculate the expected(?) result. */ + t = (gint64) timestamp + (gint64) duration - (gint64) now; + + if (t <= 0) + return 0; + if (t >= NM_PLATFORM_LIFETIME_PERMANENT) + return NM_PLATFORM_LIFETIME_PERMANENT - 1; + return t; +} + +gboolean +nm_utils_lifetime_get (guint32 timestamp, + guint32 lifetime, + guint32 preferred, + gint32 now, + guint32 *out_lifetime, + guint32 *out_preferred) +{ + guint32 t_lifetime, t_preferred; + + nm_assert (now >= 0); + + if (lifetime == 0) { + *out_lifetime = NM_PLATFORM_LIFETIME_PERMANENT; + *out_preferred = NM_PLATFORM_LIFETIME_PERMANENT; + + /* We treat lifetime==0 as permanent addresses to allow easy creation of such addresses + * (without requiring to set the lifetime fields to NM_PLATFORM_LIFETIME_PERMANENT). + * In that case we also expect that the other fields (timestamp and preferred) are left unset. */ + g_return_val_if_fail (timestamp == 0 && preferred == 0, TRUE); + } else { + if (now <= 0) + now = nm_utils_get_monotonic_timestamp_s (); + t_lifetime = nm_utils_lifetime_rebase_relative_time_on_now (timestamp, lifetime, now); + if (!t_lifetime) { + *out_lifetime = 0; + *out_preferred = 0; + return FALSE; + } + t_preferred = nm_utils_lifetime_rebase_relative_time_on_now (timestamp, preferred, now); + + *out_lifetime = t_lifetime; + *out_preferred = MIN (t_preferred, t_lifetime); + + /* Assert that non-permanent addresses have a (positive) @timestamp. nm_utils_lifetime_rebase_relative_time_on_now() + * treats addresses with timestamp 0 as *now*. Addresses passed to _address_get_lifetime() always + * should have a valid @timestamp, otherwise on every re-sync, their lifetime will be extended anew. + */ + g_return_val_if_fail ( timestamp != 0 + || ( lifetime == NM_PLATFORM_LIFETIME_PERMANENT + && preferred == NM_PLATFORM_LIFETIME_PERMANENT), TRUE); + g_return_val_if_fail (t_preferred <= t_lifetime, TRUE); + } + return TRUE; +} diff --git a/src/nm-core-utils.h b/src/nm-core-utils.h index 7a69fb19..f77b43e2 100644 --- a/src/nm-core-utils.h +++ b/src/nm-core-utils.h @@ -30,6 +30,8 @@ /*****************************************************************************/ +#define NM_PLATFORM_LIFETIME_PERMANENT G_MAXUINT32 + #define NM_DEFINE_SINGLETON_INSTANCE(TYPE) \ static TYPE *singleton_instance @@ -89,31 +91,6 @@ GETTER (void) \ /*****************************************************************************/ -/** - * NMUtilsError: - * @NM_UTILS_ERROR_UNKNOWN: unknown or unclassified error - * @NM_UTILS_ERROR_CANCELLED_DISPOSING: when disposing an object that has - * pending aynchronous operations, the operation is cancelled with this - * error reason. Depending on the usage, this might indicate a bug because - * usually the target object should stay alive as long as there are pending - * operations. - */ -typedef enum { - NM_UTILS_ERROR_UNKNOWN = 0, /*< nick=Unknown >*/ - NM_UTILS_ERROR_CANCELLED_DISPOSING, /*< nick=CancelledDisposing >*/ -} NMUtilsError; - -#define NM_UTILS_ERROR (nm_utils_error_quark ()) -GQuark nm_utils_error_quark (void); - -void nm_utils_error_set_cancelled (GError **error, - gboolean is_disposing, - const char *instance_name); -gboolean nm_utils_error_is_cancelled (GError *error, - gboolean consider_is_disposing); - -/*****************************************************************************/ - gint nm_utils_ascii_str_to_bool (const char *str, gint default_value); @@ -143,22 +120,6 @@ int nm_spawn_process (const char *args, GError **error); int nm_utils_modprobe (GError **error, gboolean suppress_error_loggin, const char *arg1, ...) G_GNUC_NULL_TERMINATED; -/** - * str_if_set: - * @str: input string that will be returned if @str is not %NULL - * @fallback: if @str is %NULL, return @fallback instead - * - * This utility function is useful when printing a string to avoid passing - * %NULL. E.g. printf ("%s", str_if_set (get_string(), "(none)")); - * - * Returns: either @str or @fallback, depending on whether @str is %NULL. - */ -static inline const char * -str_if_set (const char *str, const char *fallback) -{ - return str ? str : fallback; -} - guint64 nm_utils_get_start_time_for_pid (pid_t pid, char *out_state, pid_t *out_ppid); void nm_utils_kill_process_sync (pid_t pid, guint64 start_time, int sig, guint64 log_domain, @@ -331,6 +292,9 @@ int nm_utils_cmp_connection_by_autoconnect_priority (NMConnection **a, NMConnect void nm_utils_log_connection_diff (NMConnection *connection, NMConnection *diff_base, guint32 level, guint64 domain, const char *name, const char *prefix); #define NM_UTILS_NS_PER_SECOND ((gint64) 1000000000) +#define NM_UTILS_NS_PER_MSEC ((gint64) 1000000) +#define NM_UTILS_NS_TO_MSEC_CEIL(nsec) (((nsec) + (NM_UTILS_NS_PER_MSEC - 1)) / NM_UTILS_NS_PER_MSEC) + gint64 nm_utils_get_monotonic_timestamp_ns (void); gint64 nm_utils_get_monotonic_timestamp_us (void); gint64 nm_utils_get_monotonic_timestamp_ms (void); @@ -338,7 +302,7 @@ gint32 nm_utils_get_monotonic_timestamp_s (void); gint64 nm_utils_monotonic_timestamp_as_boottime (gint64 timestamp, gint64 timestamp_ticks_per_ns); gboolean nm_utils_is_valid_path_component (const char *name); -const char *ASSERT_VALID_PATH_COMPONENT (const char *name); +const char *NM_ASSERT_VALID_PATH_COMPONENT (const char *name); const char *nm_utils_ip6_property_path (const char *ifname, const char *property); const char *nm_utils_ip4_property_path (const char *ifname, const char *property); @@ -412,4 +376,19 @@ guint nm_utils_parse_debug_string (const char *string, const GDebugKey *keys, guint nkeys); +void nm_utils_ifname_cpy (char *dst, const char *name); + +guint32 nm_utils_lifetime_rebase_relative_time_on_now (guint32 timestamp, + guint32 duration, + gint32 now); + +gboolean nm_utils_lifetime_get (guint32 timestamp, + guint32 lifetime, + guint32 preferred, + gint32 now, + guint32 *out_lifetime, + guint32 *out_preferred); + +gboolean nm_utils_ip4_address_is_link_local (in_addr_t addr); + #endif /* __NM_CORE_UTILS_H__ */ diff --git a/src/nm-default-route-manager.c b/src/nm-default-route-manager.c index e2c4eefe..3ee634a7 100644 --- a/src/nm-default-route-manager.c +++ b/src/nm-default-route-manager.c @@ -58,6 +58,10 @@ typedef struct { G_DEFINE_TYPE (NMDefaultRouteManager, nm_default_route_manager, G_TYPE_OBJECT) +NM_GOBJECT_PROPERTIES_DEFINE_BASE ( + PROP_PLATFORM, +); + NM_DEFINE_SINGLETON_GETTER (NMDefaultRouteManager, nm_default_route_manager_get, NM_TYPE_DEFAULT_ROUTE_MANAGER); #define _NMLOG_PREFIX_NAME "default-route" @@ -283,7 +287,7 @@ _platform_route_sync_add (const VTableIP *vtable, NMDefaultRouteManager *self, g return FALSE; if (vtable->vt->is_ip4) { - success = nm_platform_ip4_route_add (NM_PLATFORM_GET, + success = nm_platform_ip4_route_add (priv->platform, entry->route.rx.ifindex, entry->route.rx.source, 0, @@ -293,7 +297,7 @@ _platform_route_sync_add (const VTableIP *vtable, NMDefaultRouteManager *self, g entry->effective_metric, entry->route.rx.mss); } else { - success = nm_platform_ip6_route_add (NM_PLATFORM_GET, + success = nm_platform_ip6_route_add (priv->platform, entry->route.rx.ifindex, entry->route.rx.source, in6addr_any, @@ -319,7 +323,7 @@ _platform_route_sync_flush (const VTableIP *vtable, NMDefaultRouteManager *self, gboolean changed = FALSE; /* prune all other default routes from this device. */ - routes = vtable->vt->route_get_all (NM_PLATFORM_GET, 0, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT); + routes = vtable->vt->route_get_all (priv->platform, 0, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT); for (i = 0; i < routes->len; i++) { const NMPlatformIPRoute *route; @@ -351,7 +355,7 @@ _platform_route_sync_flush (const VTableIP *vtable, NMDefaultRouteManager *self, */ if ( !entry && (has_ifindex_synced || ifindex_to_flush == route->ifindex)) { - vtable->vt->route_delete_default (NM_PLATFORM_GET, route->ifindex, route->metric); + vtable->vt->route_delete_default (priv->platform, route->ifindex, route->metric); changed = TRUE; } } @@ -505,7 +509,7 @@ _resync_all (const VTableIP *vtable, NMDefaultRouteManager *self, const Entry *c entries = vtable->get_entries (priv); - routes = vtable->vt->route_get_all (NM_PLATFORM_GET, 0, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT); + routes = vtable->vt->route_get_all (priv->platform, 0, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT); assumed_metrics = _get_assumed_interface_metrics (vtable, self, routes); @@ -1381,20 +1385,54 @@ _platform_changed_cb (NMPlatform *platform, /***********************************************************************************/ static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMDefaultRouteManager *self = NM_DEFAULT_ROUTE_MANAGER (object); + NMDefaultRouteManagerPrivate *priv = NM_DEFAULT_ROUTE_MANAGER_GET_PRIVATE (self); + + switch (prop_id) { + case PROP_PLATFORM: + /* construct-only */ + priv->platform = g_value_get_object (value) ? : NM_PLATFORM_GET; + if (!priv->platform) + g_return_if_reached (); + g_object_ref (priv->platform); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void nm_default_route_manager_init (NMDefaultRouteManager *self) { +} + +static void +constructed (GObject *object) +{ + NMDefaultRouteManager *self = NM_DEFAULT_ROUTE_MANAGER (object); NMDefaultRouteManagerPrivate *priv = NM_DEFAULT_ROUTE_MANAGER_GET_PRIVATE (self); priv->entries_ip4 = g_ptr_array_new_full (0, (GDestroyNotify) _entry_free); priv->entries_ip6 = g_ptr_array_new_full (0, (GDestroyNotify) _entry_free); - priv->platform = g_object_ref (NM_PLATFORM_GET); g_signal_connect (priv->platform, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, G_CALLBACK (_platform_changed_cb), self); g_signal_connect (priv->platform, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, G_CALLBACK (_platform_changed_cb), self); g_signal_connect (priv->platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, G_CALLBACK (_platform_changed_cb), self); g_signal_connect (priv->platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, G_CALLBACK (_platform_changed_cb), self); } +NMDefaultRouteManager * +nm_default_route_manager_new (NMPlatform *platform) +{ + return g_object_new (NM_TYPE_DEFAULT_ROUTE_MANAGER, + NM_DEFAULT_ROUTE_MANAGER_PLATFORM, platform, + NULL); +} + static void dispose (GObject *object) { @@ -1437,6 +1475,17 @@ nm_default_route_manager_class_init (NMDefaultRouteManagerClass *klass) g_type_class_add_private (klass, sizeof (NMDefaultRouteManagerPrivate)); /* virtual methods */ + object_class->constructed = constructed; object_class->dispose = dispose; + object_class->set_property = set_property; + + obj_properties[PROP_PLATFORM] = + g_param_spec_object (NM_DEFAULT_ROUTE_MANAGER_PLATFORM, "", "", + NM_TYPE_PLATFORM, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + } diff --git a/src/nm-default-route-manager.h b/src/nm-default-route-manager.h index 2ee4b6d6..ca92814c 100644 --- a/src/nm-default-route-manager.h +++ b/src/nm-default-route-manager.h @@ -33,7 +33,7 @@ #define NM_IS_DEFAULT_ROUTE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEFAULT_ROUTE_MANAGER)) #define NM_DEFAULT_ROUTE_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEFAULT_ROUTE_MANAGER, NMDefaultRouteManagerClass)) - +#define NM_DEFAULT_ROUTE_MANAGER_PLATFORM "platform" struct _NMDefaultRouteManager { GObject parent; @@ -46,6 +46,7 @@ typedef struct { GType nm_default_route_manager_get_type (void); NMDefaultRouteManager *nm_default_route_manager_get (void); +NMDefaultRouteManager *nm_default_route_manager_new (NMPlatform *platform); void nm_default_route_manager_ip4_update_default_route (NMDefaultRouteManager *manager, gpointer source); void nm_default_route_manager_ip6_update_default_route (NMDefaultRouteManager *manager, gpointer source); diff --git a/src/nm-dispatcher.c b/src/nm-dispatcher.c index c0238fc5..4959ed5d 100644 --- a/src/nm-dispatcher.c +++ b/src/nm-dispatcher.c @@ -39,6 +39,16 @@ #define CALL_TIMEOUT (1000 * 60 * 10) /* 10 minutes for all scripts */ +#define _NMLOG_DOMAIN LOGD_DISPATCH +#define _NMLOG_PREFIX_NAME "dispatcher" +#define _NMLOG(level, ...) \ + G_STMT_START { \ + nm_log ((level), _NMLOG_DOMAIN, \ + "%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } G_STMT_END + static GDBusProxy *dispatcher_proxy; static GHashTable *requests = NULL; @@ -332,8 +342,7 @@ dispatcher_results_process (guint request_id, DispatcherAction action, GVariantI g_return_if_fail (results != NULL); if (g_variant_iter_n_children (results) == 0) { - nm_log_dbg (LOGD_DISPATCH, "(%u) succeeded but no scripts invoked", - request_id); + _LOGD ("(%u) succeeded but no scripts invoked", request_id); return; } @@ -353,15 +362,16 @@ dispatcher_results_process (guint request_id, DispatcherAction action, GVariantI script_validation_msg = " (unexpected path)"; if (result == DISPATCH_RESULT_SUCCESS) { - nm_log_dbg (LOGD_DISPATCH, "(%u) %s succeeded%s", - request_id, - script, script_validation_msg); + _LOGD ("(%u) %s succeeded%s", + request_id, + script, script_validation_msg); } else { - nm_log_warn (LOGD_DISPATCH, "(%u) %s failed (%s): %s%s", - request_id, - script, - dispatch_result_to_string (result), - err, script_validation_msg); + _LOGW ("(%u) %s failed (%s): %s%s", + request_id, + script, + dispatch_result_to_string (result), + err, + script_validation_msg); } } } @@ -385,11 +395,11 @@ dispatcher_done_cb (GObject *proxy, GAsyncResult *result, gpointer user_data) } else { if (_nm_dbus_error_has_name (error, "org.freedesktop.systemd1.LoadFailed")) { g_dbus_error_strip_remote_error (error); - nm_log_warn (LOGD_DISPATCH, "(%u) failed to call dispatcher scripts: %s", - info->request_id, error->message); + _LOGW ("(%u) failed to call dispatcher scripts: %s", + info->request_id, error->message); } else { - nm_log_dbg (LOGD_DISPATCH, "(%u) failed to call dispatcher scripts: %s", - info->request_id, error->message); + _LOGD ("(%u) failed to call dispatcher scripts: %s", + info->request_id, error->message); } g_clear_error (&error); } @@ -474,21 +484,21 @@ _dispatcher_call (DispatcherAction action, /* All actions except 'hostname' require a device */ if (action == DISPATCHER_ACTION_HOSTNAME) { - nm_log_dbg (LOGD_DISPATCH, "(%u) dispatching action '%s'%s", - reqid, action_to_string (action), - blocking - ? " (blocking)" - : (callback ? " (with callback)" : "")); + _LOGD ("(%u) dispatching action '%s'%s", + reqid, action_to_string (action), + blocking + ? " (blocking)" + : (callback ? " (with callback)" : "")); } else { g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); - nm_log_dbg (LOGD_DISPATCH, "(%u) (%s) dispatching action '%s'%s", - reqid, - vpn_iface ? vpn_iface : nm_device_get_iface (device), - action_to_string (action), - blocking - ? " (blocking)" - : (callback ? " (with callback)" : "")); + _LOGD ("(%u) (%s) dispatching action '%s'%s", + reqid, + vpn_iface ? vpn_iface : nm_device_get_iface (device), + action_to_string (action), + blocking + ? " (blocking)" + : (callback ? " (with callback)" : "")); } if (!_get_monitor_by_action(action)->has_scripts) { @@ -499,9 +509,9 @@ _dispatcher_call (DispatcherAction action, info->callback = callback; info->user_data = user_data; info->idle_id = g_idle_add (dispatcher_idle_cb, info); - nm_log_dbg (LOGD_DISPATCH, "(%u) simulate request; no scripts in %s", reqid, _get_monitor_by_action(action)->dir); + _LOGD ("(%u) simulate request; no scripts in %s", reqid, _get_monitor_by_action(action)->dir); } else - nm_log_dbg (LOGD_DISPATCH, "(%u) ignoring request; no scripts in %s", reqid, _get_monitor_by_action(action)->dir); + _LOGD ("(%u) ignoring request; no scripts in %s", reqid, _get_monitor_by_action(action)->dir); success = TRUE; goto done; } @@ -592,7 +602,7 @@ _dispatcher_call (DispatcherAction action, success = TRUE; } else { g_dbus_error_strip_remote_error (error); - nm_log_warn (LOGD_DISPATCH, "(%u) failed: %s", reqid, error->message); + _LOGW ("(%u) failed: %s", reqid, error->message); g_clear_error (&error); success = FALSE; } @@ -764,8 +774,7 @@ nm_dispatcher_call_cancel (guint call_id) g_return_if_fail (info); if (info && info->callback) { - nm_log_dbg (LOGD_DISPATCH, "(%u) cancelling dispatcher callback action", - call_id); + _LOGD ("(%u) cancelling dispatcher callback action", call_id); info->callback = NULL; } } @@ -797,19 +806,19 @@ dispatcher_dir_changed (GFileMonitor *monitor, errsv = errno; g_dir_close (dir); if (item->has_scripts) - nm_log_dbg (LOGD_DISPATCH, "dispatcher: %s script directory '%s' has scripts", item->description, item->dir); + _LOGD ("%s script directory '%s' has scripts", item->description, item->dir); else if (errsv == 0) - nm_log_dbg (LOGD_DISPATCH, "dispatcher: %s script directory '%s' has no scripts", item->description, item->dir); + _LOGD ("%s script directory '%s' has no scripts", item->description, item->dir); else { - nm_log_dbg (LOGD_DISPATCH, "dispatcher: %s script directory '%s' error reading (%s)", item->description, item->dir, strerror (errsv)); + _LOGD ("%s script directory '%s' error reading (%s)", item->description, item->dir, strerror (errsv)); item->has_scripts = TRUE; } } else { if (g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) { - nm_log_dbg (LOGD_DISPATCH, "dispatcher: %s script directory '%s' does not exist", item->description, item->dir); + _LOGD ("%s script directory '%s' does not exist", item->description, item->dir); item->has_scripts = FALSE; } else { - nm_log_dbg (LOGD_DISPATCH, "dispatcher: %s script directory '%s' error (%s)", item->description, item->dir, error->message); + _LOGD ("%s script directory '%s' error (%s)", item->description, item->dir, error->message); item->has_scripts = TRUE; } g_error_free (error); @@ -843,7 +852,7 @@ nm_dispatcher_init (void) NM_DISPATCHER_DBUS_INTERFACE, NULL, &error); if (!dispatcher_proxy) { - nm_log_err (LOGD_DISPATCH, "could not get dispatcher proxy! %s", error->message); + _LOGE ("could not get dispatcher proxy! %s", error->message); g_clear_error (&error); } } diff --git a/src/nm-enum-types.c b/src/nm-enum-types.c index 66d54bdf..66d6c9b3 100644 --- a/src/nm-enum-types.c +++ b/src/nm-enum-types.c @@ -27,7 +27,6 @@ #include "nm-device-ethernet-utils.h" #include "nm-device-factory.h" #include "nm-device-generic.h" -#include "nm-device-logging.h" #include "nm-dhcp-client.h" #include "nm-dhcp-utils.h" #include "nm-dhcp-listener.h" @@ -39,6 +38,7 @@ #include "nm-dns-utils.h" #include "nm-dnsmasq-manager.h" #include "nm-dnsmasq-utils.h" +#include "nmp-netns.h" #include "nm-fake-platform.h" #include "nm-linux-platform.h" #include "nm-platform.h" @@ -215,9 +215,11 @@ nm_dns_manager_resolv_conf_manager_get_type (void) if (g_once_init_enter (&g_define_type_id__volatile)) { static const GEnumValue values[] = { - { NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE, "NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE", "none" }, - { NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF, "NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF", "resolvconf" }, - { NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG, "NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG", "netconfig" }, + { _NM_DNS_MANAGER_RESOLV_CONF_MAN_INTERNAL_ONLY, "_NM_DNS_MANAGER_RESOLV_CONF_MAN_INTERNAL_ONLY", "-nm-dns-manager-resolv-conf-man-internal-only" }, + { NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE, "NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE", "nm-dns-manager-resolv-conf-man-none" }, + { NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE, "NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE", "nm-dns-manager-resolv-conf-man-file" }, + { NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF, "NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF", "nm-dns-manager-resolv-conf-man-resolvconf" }, + { NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG, "NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG", "nm-dns-manager-resolv-conf-man-netconfig" }, { 0, NULL, NULL } }; GType g_define_type_id = @@ -744,25 +746,6 @@ nm_ip_config_merge_flags_get_type (void) return g_define_type_id__volatile; } GType -nm_utils_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_UTILS_ERROR_UNKNOWN, "NM_UTILS_ERROR_UNKNOWN", "Unknown" }, - { NM_UTILS_ERROR_CANCELLED_DISPOSING, "NM_UTILS_ERROR_CANCELLED_DISPOSING", "CancelledDisposing" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMUtilsError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType nm_match_spec_match_type_get_type (void) { static volatile gsize g_define_type_id__volatile = 0; diff --git a/src/nm-enum-types.h b/src/nm-enum-types.h index 6bfc3ebc..8fe52e19 100644 --- a/src/nm-enum-types.h +++ b/src/nm-enum-types.h @@ -64,8 +64,6 @@ GType nm_pobject_type_get_type (void) G_GNUC_CONST; #define NM_TYPE_POBJECT_TYPE (nm_pobject_type_get_type ()) GType nm_ip_config_merge_flags_get_type (void) G_GNUC_CONST; #define NM_TYPE_IP_CONFIG_MERGE_FLAGS (nm_ip_config_merge_flags_get_type ()) -GType nm_utils_error_get_type (void) G_GNUC_CONST; -#define NM_TYPE_UTILS_ERROR (nm_utils_error_get_type ()) GType nm_match_spec_match_type_get_type (void) G_GNUC_CONST; #define NM_TYPE_MATCH_SPEC_MATCH_TYPE (nm_match_spec_match_type_get_type ()) GType nm_utils_test_flags_get_type (void) G_GNUC_CONST; diff --git a/src/nm-iface-helper.c b/src/nm-iface-helper.c index cc59835f..5a697537 100644 --- a/src/nm-iface-helper.c +++ b/src/nm-iface-helper.c @@ -36,14 +36,15 @@ * Forward declare if_nametoindex. */ extern unsigned int if_nametoindex (const char *__ifname); +#include "main-utils.h" #include "NetworkManagerUtils.h" #include "nm-linux-platform.h" #include "nm-dhcp-manager.h" -#include "main-utils.h" #include "nm-rdisc.h" #include "nm-lndp-rdisc.h" #include "nm-utils.h" #include "nm-setting-ip6-config.h" +#include "nm-sd.h" #if !defined(NM_DIST_VERSION) # define NM_DIST_VERSION VERSION @@ -130,9 +131,8 @@ dhcp4_state_changed (NMDhcpClient *client, static void rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, gpointer user_data) { - static NMIP6Config *last_config = NULL; + static NMIP6Config *rdisc_config = NULL; NMIP6Config *existing; - NMIP6Config *ip6_config; static int system_support = -1; guint32 ifa_flags = 0x00; int i; @@ -157,21 +157,25 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, gpointer user_da ifa_flags |= IFA_F_MANAGETEMPADDR; } - ip6_config = nm_ip6_config_new (ifindex); + existing = nm_ip6_config_capture (ifindex, FALSE, global_opt.tempaddr); + if (rdisc_config) + nm_ip6_config_subtract (existing, rdisc_config); + else + rdisc_config = nm_ip6_config_new (ifindex); 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 (ip6_config, &gateway->address); + nm_ip6_config_set_gateway (rdisc_config, &gateway->address); } else - nm_ip6_config_set_gateway (ip6_config, NULL); + nm_ip6_config_set_gateway (rdisc_config, NULL); } if (changed & NM_RDISC_CONFIG_ADDRESSES) { /* Rebuild address list from router discovery cache. */ - nm_ip6_config_reset_addresses (ip6_config); + nm_ip6_config_reset_addresses (rdisc_config); /* rdisc->addresses contains at most max_addresses entries. * This is different from what the kernel does, which @@ -193,13 +197,13 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, gpointer user_da address.source = NM_IP_CONFIG_SOURCE_RDISC; address.n_ifa_flags = ifa_flags; - nm_ip6_config_add_address (ip6_config, &address); + nm_ip6_config_add_address (rdisc_config, &address); } } if (changed & NM_RDISC_CONFIG_ROUTES) { /* Rebuild route list from router discovery cache. */ - nm_ip6_config_reset_routes (ip6_config); + nm_ip6_config_reset_routes (rdisc_config); for (i = 0; i < rdisc->routes->len; i++) { NMRDiscRoute *discovered_route = &g_array_index (rdisc->routes, NMRDiscRoute, i); @@ -217,7 +221,7 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, gpointer user_da route.source = NM_IP_CONFIG_SOURCE_RDISC; route.metric = global_opt.priority_v6; - nm_ip6_config_add_route (ip6_config, &route); + nm_ip6_config_add_route (rdisc_config, &route); } } } @@ -236,18 +240,9 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, gpointer user_da nm_platform_sysctl_set (NM_PLATFORM_GET, nm_utils_ip6_property_path (global_opt.ifname, "mtu"), val); } - existing = nm_ip6_config_capture (ifindex, FALSE, global_opt.tempaddr); - if (last_config) - nm_ip6_config_subtract (existing, last_config); - - nm_ip6_config_merge (existing, ip6_config, NM_IP_CONFIG_MERGE_DEFAULT); + nm_ip6_config_merge (existing, rdisc_config, NM_IP_CONFIG_MERGE_DEFAULT); if (!nm_ip6_config_commit (existing, ifindex, TRUE)) nm_log_warn (LOGD_IP6, "(%s): failed to apply IPv6 config", global_opt.ifname); - - if (last_config) - g_object_unref (last_config); - last_config = nm_ip6_config_new (ifindex); - nm_ip6_config_replace (last_config, ip6_config, NULL); } static void @@ -351,6 +346,7 @@ main (int argc, char *argv[]) size_t hwaddr_len = 0; gconstpointer tmp; gs_free NMUtilsIPv6IfaceId *iid = NULL; + guint sd_id; nm_g_type_init (); @@ -474,7 +470,7 @@ main (int argc, char *argv[]) if (global_opt.slaac) { nm_platform_link_set_user_ipv6ll_enabled (NM_PLATFORM_GET, ifindex, TRUE); - rdisc = nm_lndp_rdisc_new (ifindex, global_opt.ifname, global_opt.uuid, global_opt.addr_gen_mode, NULL); + rdisc = nm_lndp_rdisc_new (NM_PLATFORM_GET, ifindex, global_opt.ifname, global_opt.uuid, global_opt.addr_gen_mode, NULL); g_assert (rdisc); if (iid) @@ -500,6 +496,8 @@ main (int argc, char *argv[]) nm_rdisc_start (rdisc); } + sd_id = nm_sd_event_attach_default (); + g_main_loop_run (main_loop); g_clear_pointer (&hwaddr, g_byte_array_unref); @@ -508,6 +506,8 @@ main (int argc, char *argv[]) unlink (pidfile); nm_log_info (LOGD_CORE, "exiting"); + + nm_clear_g_source (&sd_id); exit (0); } diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index 9c2557f9..4b27edf7 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -188,7 +188,7 @@ routes_are_duplicate (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b, static gint _addresses_sort_cmp_get_prio (in_addr_t addr) { - if (nmp_utils_ip4_address_is_link_local (addr)) + if (nm_utils_ip4_address_is_link_local (addr)) return 0; return 1; } @@ -1315,7 +1315,7 @@ nm_ip4_config_dump (const NMIP4Config *config, const char *detail) g_message (" nis: %s", nm_utils_inet4_ntop (tmp, NULL)); } - g_message (" nisdmn: %s", str_if_set (nm_ip4_config_get_nis_domain (config), "(none)")); + g_message (" nisdmn: %s", nm_ip4_config_get_nis_domain (config) ?: "(none)"); /* WINS */ for (i = 0; i < nm_ip4_config_get_num_wins (config); i++) { diff --git a/src/nm-logging.c b/src/nm-logging.c index 5bb3660f..935b34a8 100644 --- a/src/nm-logging.c +++ b/src/nm-logging.c @@ -73,6 +73,8 @@ typedef enum { LOG_FORMAT_FLAG_LOCATION_DEBUG | LOG_FORMAT_FLAG_LOCATION_ERROR | LOG_FORMAT_FLAG_ALIGN_LOCATION, + + _LOG_FORMAT_FLAG_DEFAULT = _LOG_FORMAT_FLAG_TIMESTAMP, } LogFormatFlags; void (*_nm_logging_clear_platform_logging_cache) (void); @@ -109,19 +111,20 @@ static struct { char *logging_domains_to_string; const LogLevelDesc level_desc[_LOGL_N]; -#define _DOMAIN_DESC_LEN 36 +#define _DOMAIN_DESC_LEN 37 /* Would be nice to use C99 flexible array member here, * but that feature doesn't seem well supported. */ const LogDesc domain_desc[_DOMAIN_DESC_LEN]; } global = { .log_level = LOGL_INFO, .log_backend = LOG_BACKEND_GLIB, + .log_format_flags = _LOG_FORMAT_FLAG_DEFAULT, .level_desc = { [LOGL_TRACE] = { "TRACE", "<trace>", LOG_DEBUG, G_LOG_LEVEL_DEBUG, _LOG_FORMAT_FLAG_LEVEL_DEBUG }, [LOGL_DEBUG] = { "DEBUG", "<debug>", LOG_INFO, G_LOG_LEVEL_DEBUG, _LOG_FORMAT_FLAG_LEVEL_DEBUG }, - [LOGL_INFO] = { "INFO", "<info>", LOG_INFO, G_LOG_LEVEL_MESSAGE, _LOG_FORMAT_FLAG_LEVEL_INFO }, - [LOGL_WARN] = { "WARN", "<warn>", LOG_WARNING, G_LOG_LEVEL_WARNING, _LOG_FORMAT_FLAG_LEVEL_INFO }, - [LOGL_ERR] = { "ERR", "<error>", LOG_ERR, G_LOG_LEVEL_WARNING, _LOG_FORMAT_FLAG_LEVEL_ERROR }, + [LOGL_INFO] = { "INFO", "<info>", LOG_INFO, G_LOG_LEVEL_INFO, _LOG_FORMAT_FLAG_LEVEL_INFO }, + [LOGL_WARN] = { "WARN", "<warn>", LOG_WARNING, G_LOG_LEVEL_MESSAGE, _LOG_FORMAT_FLAG_LEVEL_INFO }, + [LOGL_ERR] = { "ERR", "<error>", LOG_ERR, G_LOG_LEVEL_MESSAGE, _LOG_FORMAT_FLAG_LEVEL_ERROR }, [_LOGL_OFF] = { "OFF", NULL, 0, 0, 0 }, [_LOGL_KEEP] = { "KEEP", NULL, 0, 0, 0 }, }, @@ -161,6 +164,7 @@ static struct { { LOGD_DCB, "DCB" }, { LOGD_DISPATCH, "DISPATCH" }, { LOGD_AUDIT, "AUDIT" }, + { LOGD_SYSTEMD, "SYSTEMD" }, { 0, NULL } /* keep _DOMAIN_DESC_LEN in sync */ }, @@ -532,7 +536,7 @@ _nm_log_impl (const char *file, if (NM_FLAGS_ANY (global.log_format_flags, global.level_desc[level].log_format_level & _LOG_FORMAT_FLAG_TIMESTAMP)) { g_get_current_time (&tv); - nm_sprintf_buf (s_buf_timestamp, " [%ld.%06ld]", tv.tv_sec, tv.tv_usec); + nm_sprintf_buf (s_buf_timestamp, " [%ld.%04ld]", tv.tv_sec, (tv.tv_usec + 50) / 100); } else s_buf_timestamp[0] = '\0'; @@ -722,11 +726,11 @@ nm_log_handler (const gchar *log_domain, boottime = nm_utils_monotonic_timestamp_as_boottime (now, 1); sd_journal_send ("PRIORITY=%d", syslog_priority, - "MESSAGE=%s", str_if_set (message, ""), + "MESSAGE=%s", message ?: "", "SYSLOG_IDENTIFIER=%s", G_LOG_DOMAIN, "SYSLOG_PID=%ld", (long) getpid (), "SYSLOG_FACILITY=GLIB", - "GLIB_DOMAIN=%s", str_if_set (log_domain, ""), + "GLIB_DOMAIN=%s", log_domain ?: "", "GLIB_LEVEL=%d", (int) (level & G_LOG_LEVEL_MASK), "TIMESTAMP_MONOTONIC=%lld.%06lld", (long long) (now / NM_UTILS_NS_PER_SECOND), (long long) ((now % NM_UTILS_NS_PER_SECOND) / 1000), "TIMESTAMP_BOOTTIME=%lld.%06lld", (long long) (boottime / NM_UTILS_NS_PER_SECOND), (long long) ((boottime % NM_UTILS_NS_PER_SECOND) / 1000), @@ -735,7 +739,7 @@ nm_log_handler (const gchar *log_domain, break; #endif default: - syslog (syslog_priority, "%s", str_if_set (message, "")); + syslog (syslog_priority, "%s", message ?: ""); break; } } @@ -751,16 +755,13 @@ nm_logging_syslog_openlog (const char *logging_backend) if (!logging_backend) logging_backend = ""NM_CONFIG_LOGGING_BACKEND_DEFAULT; + log_format_flags = _LOG_FORMAT_FLAG_DEFAULT; + if (strcmp (logging_backend, "debug") == 0) { global.log_backend = LOG_BACKEND_SYSLOG; openlog (G_LOG_DOMAIN, LOG_CONS | LOG_PERROR | LOG_PID, LOG_USER); - log_format_flags = _LOG_FORMAT_FLAG_SYSLOG; #if SYSTEMD_JOURNAL } else if (strcmp (logging_backend, "syslog") != 0) { - if (strcmp (logging_backend, "journal-syslog-style") == 0) - log_format_flags = _LOG_FORMAT_FLAG_SYSLOG; - else - log_format_flags = _LOG_FORMAT_FLAG_TIMESTAMP; global.log_backend = LOG_BACKEND_JOURNAL; /* ensure we read a monotonic timestamp. Reading the timestamp the first @@ -769,7 +770,6 @@ nm_logging_syslog_openlog (const char *logging_backend) #endif } else { global.log_backend = LOG_BACKEND_SYSLOG; - log_format_flags = _LOG_FORMAT_FLAG_SYSLOG; openlog (G_LOG_DOMAIN, LOG_PID, LOG_DAEMON); } diff --git a/src/nm-logging.h b/src/nm-logging.h index 97102770..27f89f5d 100644 --- a/src/nm-logging.h +++ b/src/nm-logging.h @@ -64,6 +64,7 @@ typedef enum { /*< skip >*/ LOGD_DCB = (1LL << 32), /* Data Center Bridging */ LOGD_DISPATCH = (1LL << 33), LOGD_AUDIT = (1LL << 34), + LOGD_SYSTEMD = (1LL << 35), __LOGD_MAX, LOGD_ALL = ((__LOGD_MAX - 1LL) << 1) - 1LL, @@ -118,30 +119,32 @@ typedef enum { /*< skip >*/ } G_STMT_END -#define _nm_log_ptr(level, domain, self, ...) \ - nm_log ((level), (domain), "[%p] " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), self _NM_UTILS_MACRO_REST(__VA_ARGS__)) +#define _nm_log_ptr(level, domain, self, prefix, ...) \ + nm_log ((level), (domain), "%s[%p] " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), (prefix) ?: "", self _NM_UTILS_MACRO_REST(__VA_ARGS__)) /* log a message for an object (with providing a generic @self pointer) */ -#define nm_log_ptr(level, domain, self, ...) \ +#define nm_log_ptr(level, domain, self, prefix, ...) \ G_STMT_START { \ NM_PRAGMA_WARNING_DISABLE("-Wtautological-compare") \ if ((level) <= LOGL_DEBUG) { \ - _nm_log_ptr ((level), (domain), (self), __VA_ARGS__); \ + _nm_log_ptr ((level), (domain), (self), (prefix), __VA_ARGS__); \ } else { \ - nm_log ((level), (domain), __VA_ARGS__); \ + const char *__prefix = (prefix); \ + \ + nm_log ((level), (domain), "%s%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), __prefix ?: "", __prefix ? " " : "" _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ } \ NM_PRAGMA_WARNING_REENABLE \ } G_STMT_END -#define _nm_log_obj(level, domain, self, ...) \ - _nm_log_ptr ((level), (domain), (self), __VA_ARGS__) +#define _nm_log_obj(level, domain, self, prefix, ...) \ + _nm_log_ptr ((level), (domain), (self), prefix, __VA_ARGS__) /* log a message for an object (with providing a @self pointer to a GObject). * Contrary to nm_log_ptr(), @self must be a GObject type (or %NULL). * As of now, nm_log_obj() is identical to nm_log_ptr(), but we might change that */ -#define nm_log_obj(level, domain, self, ...) \ - nm_log_ptr ((level), (domain), (self), __VA_ARGS__) +#define nm_log_obj(level, domain, self, prefix, ...) \ + nm_log_ptr ((level), (domain), (self), prefix, __VA_ARGS__) void _nm_log_impl (const char *file, diff --git a/src/nm-manager.c b/src/nm-manager.c index 7f414e8f..dc394a49 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -198,20 +198,24 @@ NM_DEFINE_SINGLETON_INSTANCE (NMManager); /************************************************************************/ -#define _NMLOG_DOMAIN LOGD_CORE #define _NMLOG_PREFIX_NAME "manager" -#define _NMLOG(level, ...) \ +#define _NMLOG(level, domain, ...) \ G_STMT_START { \ - char __sbuf[32]; \ - const void *const __self = (self); \ + const NMLogLevel __level = (level); \ + const NMLogDomain __domain = (domain); \ \ - nm_log ((level), _NMLOG_DOMAIN, \ - "%s%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ - _NMLOG_PREFIX_NAME, \ - (__self && __self != singleton_instance \ - ? (__self ? nm_sprintf_buf (__sbuf, "[%p]", __self) : "[]") \ - : "") \ - _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ + if (nm_logging_enabled (__level, __domain)) { \ + const NMManager *const __self = (self); \ + char __sbuf[32]; \ + \ + _nm_log (__level, __domain, 0, \ + "%s%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, \ + (__self && __self != singleton_instance) \ + ? nm_sprintf_buf (__sbuf, "[%p]", __self) \ + : "" \ + _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ + } \ } G_STMT_END /************************************************************************/ @@ -222,6 +226,9 @@ static void active_connection_state_changed (NMActiveConnection *active, static void active_connection_default_changed (NMActiveConnection *active, GParamSpec *pspec, NMManager *self); +static void active_connection_parent_active (NMActiveConnection *active, + NMActiveConnection *parent_ac, + NMManager *self); /* Returns: whether to notify D-Bus of the removal or not */ static gboolean @@ -240,6 +247,7 @@ active_connection_remove (NMManager *self, NMActiveConnection *active) g_signal_emit (self, signals[ACTIVE_CONNECTION_REMOVED], 0, active); g_signal_handlers_disconnect_by_func (active, active_connection_state_changed, self); g_signal_handlers_disconnect_by_func (active, active_connection_default_changed, self); + g_signal_handlers_disconnect_by_func (active, active_connection_parent_active, self); if ( nm_active_connection_get_assumed (active) && (connection = nm_active_connection_get_settings_connection (active)) @@ -252,8 +260,8 @@ active_connection_remove (NMManager *self, NMActiveConnection *active) if ( connection && nm_settings_has_connection (priv->settings, connection)) { - nm_log_dbg (LOGD_DEVICE, "Assumed connection disconnected. Deleting generated connection '%s' (%s)", - nm_settings_connection_get_id (connection), nm_settings_connection_get_uuid (connection)); + _LOGD (LOGD_DEVICE, "assumed connection disconnected. Deleting generated connection '%s' (%s)", + nm_settings_connection_get_id (connection), nm_settings_connection_get_uuid (connection)); nm_settings_connection_delete (NM_SETTINGS_CONNECTION (connection), NULL, NULL); g_object_unref (connection); } @@ -603,19 +611,19 @@ _nm_state_to_string (NMState state) } static void -set_state (NMManager *manager, NMState state) +set_state (NMManager *self, NMState state) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); if (priv->state == state) return; priv->state = state; - nm_log_info (LOGD_CORE, "NetworkManager state is now %s", _nm_state_to_string (state)); + _LOGI (LOGD_CORE, "NetworkManager state is now %s", _nm_state_to_string (state)); - g_object_notify (G_OBJECT (manager), NM_MANAGER_STATE); - g_signal_emit (manager, signals[STATE_CHANGED], 0, priv->state); + g_object_notify (G_OBJECT (self), NM_MANAGER_STATE); + g_signal_emit (self, signals[STATE_CHANGED], 0, priv->state); } static void @@ -684,14 +692,14 @@ find_best_device_state (NMManager *manager) } static void -nm_manager_update_metered (NMManager *manager) +nm_manager_update_metered (NMManager *self) { NMManagerPrivate *priv; NMDevice *device; NMMetered value = NM_METERED_UNKNOWN; - g_return_if_fail (NM_IS_MANAGER (manager)); - priv = NM_MANAGER_GET_PRIVATE (manager); + g_return_if_fail (NM_IS_MANAGER (self)); + priv = NM_MANAGER_GET_PRIVATE (self); if (priv->primary_connection) { device = nm_active_connection_get_device (priv->primary_connection); @@ -701,9 +709,8 @@ nm_manager_update_metered (NMManager *manager) if (value != priv->metered) { priv->metered = value; - nm_log_dbg (LOGD_CORE, "New manager metered value: %d", - (int) priv->metered); - g_object_notify (G_OBJECT (manager), NM_MANAGER_METERED); + _LOGD (LOGD_CORE, "new metered value: %d", (int) priv->metered); + g_object_notify (G_OBJECT (self), NM_MANAGER_METERED); } } @@ -777,7 +784,7 @@ check_if_startup_complete (NMManager *self) return; if (!nm_settings_get_startup_complete (priv->settings)) { - nm_log_dbg (LOGD_CORE, "check_if_startup_complete returns FALSE because of NMSettings"); + _LOGD (LOGD_CORE, "check_if_startup_complete returns FALSE because of NMSettings"); return; } @@ -785,13 +792,13 @@ check_if_startup_complete (NMManager *self) NMDevice *dev = iter->data; if (nm_device_has_pending_action (dev)) { - nm_log_dbg (LOGD_CORE, "check_if_startup_complete returns FALSE because of %s", - nm_device_get_iface (dev)); + _LOGD (LOGD_CORE, "check_if_startup_complete returns FALSE because of %s", + nm_device_get_iface (dev)); return; } } - nm_log_info (LOGD_CORE, "startup complete"); + _LOGI (LOGD_CORE, "startup complete"); priv->startup = FALSE; g_object_notify (G_OBJECT (self), "startup"); @@ -824,15 +831,15 @@ settings_startup_complete_changed (NMSettings *settings, } static void -remove_device (NMManager *manager, +remove_device (NMManager *self, NMDevice *device, gboolean quitting, gboolean allow_unmanage) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - nm_log_dbg (LOGD_DEVICE, "(%s): removing device (allow_unmanage %d, managed %d)", - nm_device_get_iface (device), allow_unmanage, nm_device_get_managed (device, FALSE)); + _LOGD (LOGD_DEVICE, "(%s): removing device (allow_unmanage %d, managed %d)", + nm_device_get_iface (device), allow_unmanage, nm_device_get_managed (device, FALSE)); if (allow_unmanage && nm_device_get_managed (device, FALSE)) { NMActRequest *req = nm_device_get_act_request (device); @@ -860,22 +867,22 @@ remove_device (NMManager *manager, } } - g_signal_handlers_disconnect_matched (device, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, manager); + g_signal_handlers_disconnect_matched (device, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self); nm_settings_device_removed (priv->settings, device, quitting); priv->devices = g_slist_remove (priv->devices, device); if (nm_device_is_real (device)) { - g_signal_emit (manager, signals[DEVICE_REMOVED], 0, device); - g_object_notify (G_OBJECT (manager), NM_MANAGER_DEVICES); + g_signal_emit (self, signals[DEVICE_REMOVED], 0, device); + g_object_notify (G_OBJECT (self), NM_MANAGER_DEVICES); nm_device_removed (device); } - g_signal_emit (manager, signals[INTERNAL_DEVICE_REMOVED], 0, device); - g_object_notify (G_OBJECT (manager), NM_MANAGER_ALL_DEVICES); + g_signal_emit (self, signals[INTERNAL_DEVICE_REMOVED], 0, device); + g_object_notify (G_OBJECT (self), NM_MANAGER_ALL_DEVICES); nm_exported_object_clear_and_unexport (&device); - check_if_startup_complete (manager); + check_if_startup_complete (self); } static void @@ -1039,8 +1046,8 @@ system_create_virtual_device (NMManager *self, NMConnection *connection) iface = nm_manager_get_connection_iface (self, connection, &parent, &error); if (!iface) { - nm_log_warn (LOGD_DEVICE, "(%s) can't get a name of a virtual device: %s", - nm_connection_get_id (connection), error->message); + _LOGD (LOGD_DEVICE, "(%s) can't get a name of a virtual device: %s", + nm_connection_get_id (connection), error->message); g_error_free (error); return NULL; } @@ -1051,8 +1058,8 @@ system_create_virtual_device (NMManager *self, NMConnection *connection) if (nm_device_check_connection_compatible (candidate, connection)) { if (nm_device_is_real (candidate)) { - nm_log_dbg (LOGD_DEVICE, "(%s) already created virtual interface name %s", - nm_connection_get_id (connection), iface); + _LOGD (LOGD_DEVICE, "(%s) already created virtual interface name %s", + nm_connection_get_id (connection), iface); return NULL; } @@ -1066,23 +1073,27 @@ system_create_virtual_device (NMManager *self, NMConnection *connection) factory = nm_device_factory_manager_find_factory_for_connection (connection); if (!factory) { - nm_log_err (LOGD_DEVICE, "(%s:%s) NetworkManager plugin for '%s' unavailable", - nm_connection_get_id (connection), iface, - nm_connection_get_connection_type (connection)); + _LOGE (LOGD_DEVICE, "(%s:%s) NetworkManager plugin for '%s' unavailable", + nm_connection_get_id (connection), iface, + nm_connection_get_connection_type (connection)); return NULL; } device = nm_device_factory_create_device (factory, iface, NULL, connection, NULL, &error); if (!device) { - nm_log_warn (LOGD_DEVICE, "(%s) factory can't create the device: %s", - nm_connection_get_id (connection), error->message); + _LOGW (LOGD_DEVICE, "(%s) factory can't create the device: %s", + nm_connection_get_id (connection), error->message); g_error_free (error); return NULL; } + _LOGD (LOGD_DEVICE, "(%s) create virtual device %s", + nm_connection_get_id (connection), + nm_device_get_iface (device)); + if (!add_device (self, device, &error)) { - nm_log_warn (LOGD_DEVICE, "(%s) can't register the device with manager: %s", - nm_connection_get_id (connection), error->message); + _LOGW (LOGD_DEVICE, "(%s) can't register the device with manager: %s", + nm_connection_get_id (connection), error->message); g_error_free (error); g_object_unref (device); return NULL; @@ -1110,8 +1121,8 @@ system_create_virtual_device (NMManager *self, NMConnection *connection) /* Create any backing resources the device needs */ if (!nm_device_create_and_realize (device, connection, parent, &error)) { - nm_log_warn (LOGD_DEVICE, "(%s) couldn't create the device: %s", - nm_connection_get_id (connection), error->message); + _LOGW (LOGD_DEVICE, "(%s) couldn't create the device: %s", + nm_connection_get_id (connection), error->message); g_error_free (error); remove_device (self, device, FALSE, TRUE); return NULL; @@ -1133,11 +1144,19 @@ retry_connections_for_parent_device (NMManager *self, NMDevice *device) connections = nm_settings_get_connections (priv->settings); for (iter = connections; iter; iter = g_slist_next (iter)) { NMConnection *candidate = iter->data; + gs_free_error GError *error = NULL; + gs_free char *ifname = NULL; NMDevice *parent; parent = find_parent_device_for_connection (self, candidate, NULL); - if (parent == device) - connection_changed (priv->settings, candidate, self); + if (parent == device) { + /* Only try to activate devices that don't already exist */ + ifname = nm_manager_get_connection_iface (self, candidate, &parent, &error); + if (ifname) { + if (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, ifname)) + connection_changed (priv->settings, candidate, self); + } + } } g_slist_free (connections); @@ -1314,9 +1333,9 @@ manager_update_radio_enabled (NMManager *self, NMDevice *device = NM_DEVICE (iter->data); if (nm_device_get_rfkill_type (device) == rstate->rtype) { - nm_log_dbg (LOGD_RFKILL, "(%s): setting radio %s", - nm_device_get_iface (device), - enabled ? "enabled" : "disabled"); + _LOGD (LOGD_RFKILL, "(%s): setting radio %s", + nm_device_get_iface (device), + enabled ? "enabled" : "disabled"); nm_device_set_enabled (device, enabled); } } @@ -1361,16 +1380,16 @@ manager_rfkill_update_one_type (NMManager *self, /* Print out all states affecting device enablement */ if (rstate->desc) { - nm_log_dbg (LOGD_RFKILL, "%s hw-enabled %d sw-enabled %d", - rstate->desc, rstate->hw_enabled, rstate->sw_enabled); + _LOGD (LOGD_RFKILL, "%s hw-enabled %d sw-enabled %d", + rstate->desc, rstate->hw_enabled, rstate->sw_enabled); } /* Log new killswitch state */ new_rfkilled = rstate->hw_enabled && rstate->sw_enabled; if (old_rfkilled != new_rfkilled) { - nm_log_info (LOGD_RFKILL, "%s now %s by radio killswitch", - rstate->desc, - new_rfkilled ? "enabled" : "disabled"); + _LOGI (LOGD_RFKILL, "%s now %s by radio killswitch", + rstate->desc, + new_rfkilled ? "enabled" : "disabled"); } /* Send out property changed signal for HW enabled */ @@ -1435,13 +1454,13 @@ device_auth_done_cb (NMAuthChain *chain, if (auth_error) { /* translate the auth error into a manager permission denied error */ - nm_log_dbg (LOGD_CORE, "%s request failed: %s", permission, auth_error->message); + _LOGD (LOGD_CORE, "%s request failed: %s", permission, auth_error->message); error = g_error_new (NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED, "%s request failed: %s", permission, auth_error->message); } else if (result != NM_AUTH_CALL_RESULT_YES) { - nm_log_dbg (LOGD_CORE, "%s request failed: not authorized", permission); + _LOGD (LOGD_CORE, "%s request failed: not authorized", permission); error = g_error_new (NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED, "%s request failed: not authorized", @@ -1539,10 +1558,10 @@ match_connection_filter (NMConnection *connection, gpointer user_data) * the device does not support assuming existing connections. */ static NMSettingsConnection * -get_existing_connection (NMManager *manager, NMDevice *device, gboolean *out_generated) +get_existing_connection (NMManager *self, NMDevice *device, gboolean *out_generated) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - gs_free_slist GSList *connections = nm_manager_get_activatable_connections (manager); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + gs_free_slist GSList *connections = nm_manager_get_activatable_connections (self); NMConnection *connection = NULL; NMSettingsConnection *matched; NMSettingsConnection *added = NULL; @@ -1559,15 +1578,15 @@ get_existing_connection (NMManager *manager, NMDevice *device, gboolean *out_gen int master_ifindex = nm_platform_link_get_master (NM_PLATFORM_GET, ifindex); if (master_ifindex) { - master = nm_manager_get_device_by_ifindex (manager, master_ifindex); + master = nm_manager_get_device_by_ifindex (self, master_ifindex); if (!master) { - nm_log_dbg (LOGD_DEVICE, "(%s): cannot generate connection for slave before its master (%s/%d)", - nm_device_get_iface (device), nm_platform_link_get_name (NM_PLATFORM_GET, master_ifindex), master_ifindex); + _LOGD (LOGD_DEVICE, "(%s): cannot generate connection for slave before its master (%s/%d)", + nm_device_get_iface (device), nm_platform_link_get_name (NM_PLATFORM_GET, master_ifindex), master_ifindex); return NULL; } if (!nm_device_get_act_request (master)) { - nm_log_dbg (LOGD_DEVICE, "(%s): cannot generate connection for slave before master %s activates", - nm_device_get_iface (device), nm_device_get_iface (master)); + _LOGD (LOGD_DEVICE, "(%s): cannot generate connection for slave before master %s activates", + nm_device_get_iface (device), nm_device_get_iface (master)); return NULL; } } @@ -1601,16 +1620,16 @@ get_existing_connection (NMManager *manager, NMDevice *device, gboolean *out_gen match_connection_filter, device)); if (matched) { - nm_log_info (LOGD_DEVICE, "(%s): found matching connection '%s'", - nm_device_get_iface (device), - nm_settings_connection_get_id (matched)); + _LOGI (LOGD_DEVICE, "(%s): found matching connection '%s'", + nm_device_get_iface (device), + nm_settings_connection_get_id (matched)); g_object_unref (connection); return matched; } - nm_log_dbg (LOGD_DEVICE, "(%s): generated connection '%s'", - nm_device_get_iface (device), - nm_connection_get_id (connection)); + _LOGD (LOGD_DEVICE, "(%s): generated connection '%s'", + nm_device_get_iface (device), + nm_connection_get_id (connection)); added = nm_settings_add_connection (priv->settings, connection, FALSE, &error); if (added) { @@ -1621,10 +1640,10 @@ get_existing_connection (NMManager *manager, NMDevice *device, gboolean *out_gen if (out_generated) *out_generated = TRUE; } else { - nm_log_warn (LOGD_SETTINGS, "(%s) Couldn't save generated connection '%s': %s", - nm_device_get_iface (device), - nm_connection_get_id (connection), - (error && error->message) ? error->message : "(unknown)"); + _LOGW (LOGD_SETTINGS, "(%s) Couldn't save generated connection '%s': %s", + nm_device_get_iface (device), + nm_connection_get_id (connection), + error->message); g_clear_error (&error); } g_object_unref (connection); @@ -1639,8 +1658,8 @@ assume_connection (NMManager *self, NMDevice *device, NMSettingsConnection *conn NMAuthSubject *subject; GError *error = NULL; - nm_log_dbg (LOGD_DEVICE, "(%s): will attempt to assume connection", - nm_device_get_iface (device)); + _LOGD (LOGD_DEVICE, "(%s): will attempt to assume connection", + nm_device_get_iface (device)); /* Move device to DISCONNECTED to activate the connection */ if (nm_device_get_state (device) == NM_DEVICE_STATE_UNAVAILABLE) { @@ -1655,10 +1674,9 @@ assume_connection (NMManager *self, NMDevice *device, NMSettingsConnection *conn g_object_unref (subject); if (!active) { - nm_log_warn (LOGD_DEVICE, "assumed connection %s failed to activate: (%d) %s", - nm_connection_get_path (NM_CONNECTION (connection)), - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); + _LOGW (LOGD_DEVICE, "assumed connection %s failed to activate: %s", + nm_connection_get_path (NM_CONNECTION (connection)), + error->message); g_error_free (error); return FALSE; } @@ -1699,8 +1717,8 @@ recheck_assume_connection (NMManager *self, NMDevice *device) connection = get_existing_connection (self, device, &generated); if (!connection) { - nm_log_dbg (LOGD_DEVICE, "(%s): can't assume; no connection", - nm_device_get_iface (device)); + _LOGD (LOGD_DEVICE, "(%s): can't assume; no connection", + nm_device_get_iface (device)); return FALSE; } @@ -1720,8 +1738,8 @@ recheck_assume_connection (NMManager *self, NMDevice *device) } if (generated) { - nm_log_dbg (LOGD_DEVICE, "(%s): connection assumption failed. Deleting generated connection", - nm_device_get_iface (device)); + _LOGD (LOGD_DEVICE, "(%s): connection assumption failed. Deleting generated connection", + nm_device_get_iface (device)); nm_settings_connection_delete (connection, NULL, NULL); } @@ -1908,7 +1926,7 @@ add_device (NMManager *self, NMDevice *device, GError **error) manager_sleeping (self)); dbus_path = nm_exported_object_export (NM_EXPORTED_OBJECT (device)); - nm_log_info (LOGD_DEVICE, "(%s): new %s device (%s)", iface, type_desc, dbus_path); + _LOGI (LOGD_DEVICE, "(%s): new %s device (%s)", iface, type_desc, dbus_path); nm_settings_device_added (priv->settings, device); g_signal_emit (self, signals[INTERNAL_DEVICE_ADDED], 0, device); @@ -1945,8 +1963,8 @@ factory_device_added_cb (NMDeviceFactory *factory, add_device (self, device, NULL); _device_realize_finish (self, device, NULL); } else { - nm_log_warn (LOGD_DEVICE, "(%s): failed to realize device: %s", - nm_device_get_iface (device), error->message); + _LOGW (LOGD_DEVICE, "(%s): failed to realize device: %s", + nm_device_get_iface (device), error->message); g_error_free (error); } } @@ -2019,8 +2037,8 @@ platform_link_added (NMManager *self, return; } - nm_log_dbg (LOGD_DEVICE, "(%s): failed to realize from plink: '%s'", - plink->name, error->message); + _LOGD (LOGD_DEVICE, "(%s): failed to realize from plink: '%s'", + plink->name, error->message); g_clear_error (&error); /* Try next unrealized device */ @@ -2034,8 +2052,8 @@ platform_link_added (NMManager *self, device = nm_device_factory_create_device (factory, plink->name, plink, NULL, &ignore, &error); if (!device) { if (!ignore) { - nm_log_warn (LOGD_HW, "%s: factory failed to create device: %s", - plink->name, error->message); + _LOGW (LOGD_HW, "%s: factory failed to create device: %s", + plink->name, error->message); g_clear_error (&error); } return; @@ -2049,8 +2067,8 @@ platform_link_added (NMManager *self, case NM_LINK_TYPE_OLPC_MESH: case NM_LINK_TYPE_TEAM: case NM_LINK_TYPE_WIFI: - nm_log_info (LOGD_HW, "(%s): '%s' plugin not available; creating generic device", - plink->name, nm_link_type_to_string (plink->type)); + _LOGI (LOGD_HW, "(%s): '%s' plugin not available; creating generic device", + plink->name, nm_link_type_to_string (plink->type)); nm_plugin_missing = TRUE; /* fall through */ default: @@ -2066,8 +2084,8 @@ platform_link_added (NMManager *self, add_device (self, device, NULL); _device_realize_finish (self, device, plink); } else { - nm_log_warn (LOGD_DEVICE, "%s: failed to realize device: %s", - plink->name, error->message); + _LOGW (LOGD_DEVICE, "%s: failed to realize device: %s", + plink->name, error->message); g_clear_error (&error); } g_object_unref (device); @@ -2105,9 +2123,9 @@ _platform_link_cb_idle (PlatformLinkCbData *data) if (nm_device_is_software (device)) { /* Our software devices stick around until their connection is removed */ if (!nm_device_unrealize (device, FALSE, &error)) { - nm_log_warn (LOGD_DEVICE, "(%s): failed to unrealize: %s", - nm_device_get_iface (device), - error->message); + _LOGW (LOGD_DEVICE, "(%s): failed to unrealize: %s", + nm_device_get_iface (device), + error->message); g_clear_error (&error); remove_device (self, device, FALSE, TRUE); } @@ -2654,7 +2672,7 @@ out: } static gboolean -autoconnect_slaves (NMManager *manager, +autoconnect_slaves (NMManager *self, NMSettingsConnection *master_connection, NMDevice *master_device, NMAuthSubject *subject) @@ -2665,28 +2683,28 @@ autoconnect_slaves (NMManager *manager, if (should_connect_slaves (NM_CONNECTION (master_connection), master_device)) { GSList *slaves, *iter; - iter = slaves = find_slaves (manager, master_connection, master_device); + iter = slaves = find_slaves (self, master_connection, master_device); ret = slaves != NULL; while (iter) { NMSettingsConnection *slave_connection = iter->data; iter = iter->next; - nm_log_dbg (LOGD_CORE, "will activate slave connection '%s' (%s) as a dependency for master '%s' (%s)", - nm_settings_connection_get_id (slave_connection), - nm_settings_connection_get_uuid (slave_connection), - nm_settings_connection_get_id (master_connection), - nm_settings_connection_get_uuid (master_connection)); + _LOGD (LOGD_CORE, "will activate slave connection '%s' (%s) as a dependency for master '%s' (%s)", + nm_settings_connection_get_id (slave_connection), + nm_settings_connection_get_uuid (slave_connection), + nm_settings_connection_get_id (master_connection), + nm_settings_connection_get_uuid (master_connection)); /* Schedule slave activation */ - nm_manager_activate_connection (manager, + nm_manager_activate_connection (self, slave_connection, NULL, - nm_manager_get_best_device_for_connection (manager, NM_CONNECTION (slave_connection), FALSE), + nm_manager_get_best_device_for_connection (self, NM_CONNECTION (slave_connection), FALSE), subject, &local_err); if (local_err) { - nm_log_warn (LOGD_CORE, "Slave connection activation failed: %s", local_err->message); + _LOGW (LOGD_CORE, "Slave connection activation failed: %s", local_err->message); g_error_free (local_err); } } @@ -2713,6 +2731,71 @@ _internal_activate_vpn (NMManager *self, NMActiveConnection *active, GError **er return success; } +/* Traverse the device to disconnected state. This means that the device is ready + * for connection and will proceed activating if there's an activation request + * enqueued. + */ +static void +unmanaged_to_disconnected (NMDevice *device) +{ + /* when creating the software device, it can happen that the device is + * still unmanaged by NM_UNMANAGED_PLATFORM_INIT because we didn't yet + * get the udev event. At this point, we can no longer delay the activation + * and force the device to be managed. */ + nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_PLATFORM_INIT, FALSE, NM_DEVICE_STATE_REASON_USER_REQUESTED); + + nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_USER_EXPLICIT, FALSE, NM_DEVICE_STATE_REASON_USER_REQUESTED); + + g_return_if_fail (nm_device_get_managed (device, FALSE)); + + if (nm_device_get_state (device) == NM_DEVICE_STATE_UNMANAGED) { + nm_device_state_changed (device, + NM_DEVICE_STATE_UNAVAILABLE, + NM_DEVICE_STATE_REASON_USER_REQUESTED); + } + + if ( nm_device_is_available (device, NM_DEVICE_CHECK_DEV_AVAILABLE_FOR_USER_REQUEST) + && (nm_device_get_state (device) == NM_DEVICE_STATE_UNAVAILABLE)) { + nm_device_state_changed (device, + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_USER_REQUESTED); + } +} + +/* The parent connection is ready; we can proceed realizing the device and + * progressing the device to disconencted state. + */ +static void +active_connection_parent_active (NMActiveConnection *active, + NMActiveConnection *parent_ac, + NMManager *self) +{ + NMDevice *device = nm_active_connection_get_device (active); + GError *error = NULL; + + g_signal_handlers_disconnect_by_func (active, + (GCallback) active_connection_parent_active, + self); + + if (parent_ac) { + NMSettingsConnection *connection = nm_active_connection_get_settings_connection (active); + NMDevice *parent = nm_active_connection_get_device (parent_ac); + + if (nm_device_create_and_realize (device, (NMConnection *) connection, parent, &error)) { + /* We can now proceed to disconnected state so that activation proceeds. */ + unmanaged_to_disconnected (device); + } else { + nm_log_warn (LOGD_CORE, "Could not realize device '%s': %s", + nm_device_get_iface (device), error->message); + nm_active_connection_set_state (active, NM_ACTIVE_CONNECTION_STATE_DEACTIVATED); + } + } else { + nm_log_warn (LOGD_CORE, "The parent connection device '%s' depended on disappeared.", + nm_device_get_iface (device)); + nm_active_connection_set_state (active, NM_ACTIVE_CONNECTION_STATE_DEACTIVATED); + } +} + static gboolean _internal_activate_device (NMManager *self, NMActiveConnection *active, GError **error) { @@ -2772,9 +2855,35 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError * NMDevice *parent; parent = find_parent_device_for_connection (self, (NMConnection *) connection, NULL); - if (!nm_device_create_and_realize (device, (NMConnection *) connection, parent, error)) { - g_prefix_error (error, "%s failed to create resources: ", nm_device_get_iface (device)); - return FALSE; + + if (parent && !nm_device_is_real (parent)) { + NMSettingsConnection *parent_con; + NMActiveConnection *parent_ac; + + parent_con = nm_device_get_best_connection (parent, NULL, error); + if (!parent_con) { + g_prefix_error (error, "%s failed to create parent: ", nm_device_get_iface (device)); + return FALSE; + } + + parent_ac = nm_manager_activate_connection (self, parent_con, NULL, parent, subject, error); + if (!parent_ac) { + g_prefix_error (error, "%s failed to activate parent: ", nm_device_get_iface (device)); + return FALSE; + } + + /* We can't realize now; defer until the parent device is ready. */ + g_signal_connect (active, + NM_ACTIVE_CONNECTION_PARENT_ACTIVE, + (GCallback) active_connection_parent_active, + self); + nm_active_connection_set_parent (active, parent_ac); + } else { + /* We can realize now; no need to wait for a parent device. */ + if (!nm_device_create_and_realize (device, (NMConnection *) connection, parent, error)) { + g_prefix_error (error, "%s failed to create resources: ", nm_device_get_iface (device)); + return FALSE; + } } } @@ -2789,14 +2898,14 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError * */ if (master_connection || master_device) { if (master_connection) { - nm_log_dbg (LOGD_CORE, "Activation of '%s' requires master connection '%s'", - nm_settings_connection_get_id (connection), - nm_settings_connection_get_id (master_connection)); + _LOGD (LOGD_CORE, "Activation of '%s' requires master connection '%s'", + nm_settings_connection_get_id (connection), + nm_settings_connection_get_id (master_connection)); } if (master_device) { - nm_log_dbg (LOGD_CORE, "Activation of '%s' requires master device '%s'", - nm_settings_connection_get_id (connection), - nm_device_get_ip_iface (master_device)); + _LOGD (LOGD_CORE, "Activation of '%s' requires master device '%s'", + nm_settings_connection_get_id (connection), + nm_device_get_ip_iface (master_device)); } /* Ensure eg bond slave and the candidate master is a bond master */ @@ -2822,10 +2931,10 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError * } nm_active_connection_set_master (active, master_ac); - nm_log_dbg (LOGD_CORE, "Activation of '%s' depends on active connection %p %s", - nm_settings_connection_get_id (connection), - master_ac, - str_if_set (nm_exported_object_get_path (NM_EXPORTED_OBJECT (master_ac)), "")); + _LOGD (LOGD_CORE, "Activation of '%s' depends on active connection %p %s", + nm_settings_connection_get_id (connection), + master_ac, + nm_exported_object_get_path (NM_EXPORTED_OBJECT (master_ac)) ?: ""); } /* Check slaves for master connection and possibly activate them */ @@ -2836,28 +2945,9 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError * if (existing) nm_device_steal_connection (existing, connection); - /* when creating the software device, it can happen that the device is - * still unmanaged by NM_UNMANAGED_PLATFORM_INIT because we didn't yet - * get the udev event. At this point, we can no longer delay the activation - * and force the device to be managed. */ - nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_PLATFORM_INIT, FALSE, NM_DEVICE_STATE_REASON_USER_REQUESTED); - - nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_USER_EXPLICIT, FALSE, NM_DEVICE_STATE_REASON_USER_REQUESTED); - - g_return_val_if_fail (nm_device_get_managed (device, FALSE), FALSE); - - if (nm_device_get_state (device) == NM_DEVICE_STATE_UNMANAGED) { - nm_device_state_changed (device, - NM_DEVICE_STATE_UNAVAILABLE, - NM_DEVICE_STATE_REASON_USER_REQUESTED); - } - - if ( nm_device_is_available (device, NM_DEVICE_CHECK_DEV_AVAILABLE_FOR_USER_REQUEST) - && (nm_device_get_state (device) == NM_DEVICE_STATE_UNAVAILABLE)) { - nm_device_state_changed (device, - NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_REASON_USER_REQUESTED); - } + /* If the device is there, we can ready it for the activation. */ + if (nm_device_is_real (device)) + unmanaged_to_disconnected (device); /* Export the new ActiveConnection to clients and start it on the device */ nm_exported_object_export (NM_EXPORTED_OBJECT (active)); @@ -2998,9 +3088,9 @@ _internal_activation_failed (NMManager *self, NMActiveConnection *active, const char *error_desc) { - nm_log_dbg (LOGD_CORE, "Failed to activate '%s': %s", - nm_active_connection_get_settings_connection_id (active), - error_desc); + _LOGD (LOGD_CORE, "Failed to activate '%s': %s", + nm_active_connection_get_settings_connection_id (active), + error_desc); if (nm_active_connection_get_state (active) <= NM_ACTIVE_CONNECTION_STATE_ACTIVATED) { nm_active_connection_set_state (active, NM_ACTIVE_CONNECTION_STATE_DEACTIVATING); @@ -3315,11 +3405,15 @@ impl_manager_activate_connection (NMManager *self, * regardless of whether that connection is autoconnect-enabled or not * (since this is an explicit request, not an auto-activation request). */ - if (!connection_path) { - GPtrArray *available; - guint64 best_timestamp = 0; - guint i; - + if (connection_path) { + connection = nm_settings_get_connection_by_path (priv->settings, connection_path); + if (!connection) { + error = g_error_new_literal (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_UNKNOWN_CONNECTION, + "Connection could not be found."); + goto error; + } + } else { /* If no connection is given, find a suitable connection for the given device path */ if (!device_path) { error = g_error_new_literal (NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, @@ -3333,36 +3427,9 @@ impl_manager_activate_connection (NMManager *self, goto error; } - available = nm_device_get_available_connections (device, specific_object_path); - for (i = 0; available && i < available->len; i++) { - NMSettingsConnection *candidate = g_ptr_array_index (available, i); - guint64 candidate_timestamp = 0; - - nm_settings_connection_get_timestamp (candidate, &candidate_timestamp); - if (!connection_path || (candidate_timestamp > best_timestamp)) { - connection_path = nm_connection_get_path (NM_CONNECTION (candidate)); - best_timestamp = candidate_timestamp; - } - } - - if (available) - g_ptr_array_free (available, TRUE); - - if (!connection_path) { - error = g_error_new_literal (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_UNKNOWN_CONNECTION, - "The device has no connections available."); + connection = nm_device_get_best_connection (device, specific_object_path, &error); + if (!connection) goto error; - } - } - - g_assert (connection_path); - connection = nm_settings_get_connection_by_path (priv->settings, connection_path); - if (!connection) { - error = g_error_new_literal (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_UNKNOWN_CONNECTION, - "Connection could not be found."); - goto error; } subject = validate_activation_request (self, @@ -3536,7 +3603,7 @@ impl_manager_add_and_activate_connection (NMManager *self, */ connection = nm_simple_connection_new (); if (settings && g_variant_n_children (settings)) - nm_connection_replace_settings (connection, settings, NULL); + _nm_connection_replace_settings (connection, settings, NM_SETTING_PARSE_FLAGS_STRICT, NULL); subject = validate_activation_request (self, context, @@ -3559,7 +3626,8 @@ impl_manager_add_and_activate_connection (NMManager *self, goto error; } - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_VPN_SETTING_NAME, all_connections, NULL, @@ -3668,10 +3736,9 @@ deactivate_net_auth_done_cb (NMAuthChain *chain, path = nm_auth_chain_get_data (chain, "path"); result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL); - active = active_connection_get_by_path (self, path); if (auth_error) { - nm_log_dbg (LOGD_CORE, "Disconnect request failed: %s", auth_error->message); + _LOGD (LOGD_CORE, "Disconnect request failed: %s", auth_error->message); error = g_error_new (NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED, "Deactivate request failed: %s", @@ -3686,9 +3753,10 @@ deactivate_net_auth_done_cb (NMAuthChain *chain, path, NM_DEVICE_STATE_REASON_USER_REQUESTED, &error)) - g_assert (error); + nm_assert (error); } + active = active_connection_get_by_path (self, path); if (active) { nm_audit_log_connection_op (NM_AUDIT_OP_CONN_DEACTIVATE, nm_active_connection_get_settings_connection (active), @@ -3791,7 +3859,7 @@ do_sleep_wake (NMManager *self, gboolean sleeping_changed) waking_from_suspend = sleeping_changed && !priv->sleeping; if (manager_sleeping (self)) { - nm_log_info (LOGD_SUSPEND, "%s...", suspending ? "sleeping" : "disabling"); + _LOGI (LOGD_SUSPEND, "%s...", suspending ? "sleeping" : "disabling"); /* FIXME: are there still hardware devices that need to be disabled around * suspend/resume? @@ -3809,7 +3877,7 @@ do_sleep_wake (NMManager *self, gboolean sleeping_changed) nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_SLEEPING, TRUE, NM_DEVICE_STATE_REASON_SLEEPING); } } else { - nm_log_info (LOGD_SUSPEND, "%s...", waking_from_suspend ? "waking up" : "re-enabling"); + _LOGI (LOGD_SUSPEND, "%s...", waking_from_suspend ? "waking up" : "re-enabling"); if (waking_from_suspend) { /* Belatedly take down Wake-on-LAN devices; ideally we wouldn't have to do this @@ -3846,9 +3914,9 @@ do_sleep_wake (NMManager *self, gboolean sleeping_changed) gboolean enabled = radio_enabled_for_rstate (rstate, TRUE); if (rstate->desc) { - nm_log_dbg (LOGD_RFKILL, "%s %s devices (hw_enabled %d, sw_enabled %d, user_enabled %d)", - enabled ? "enabling" : "disabling", - rstate->desc, rstate->hw_enabled, rstate->sw_enabled, rstate->user_enabled); + _LOGD (LOGD_RFKILL, "%s %s devices (hw_enabled %d, sw_enabled %d, user_enabled %d)", + enabled ? "enabling" : "disabling", + rstate->desc, rstate->hw_enabled, rstate->sw_enabled, rstate->user_enabled); } if (nm_device_get_rfkill_type (device) == rstate->rtype) @@ -3872,10 +3940,10 @@ _internal_sleep (NMManager *self, gboolean do_sleep) if (priv->sleeping == do_sleep) return; - nm_log_info (LOGD_SUSPEND, "%s requested (sleeping: %s enabled: %s)", - do_sleep ? "sleep" : "wake", - priv->sleeping ? "yes" : "no", - priv->net_enabled ? "yes" : "no"); + _LOGI (LOGD_SUSPEND, "%s requested (sleeping: %s enabled: %s)", + do_sleep ? "sleep" : "wake", + priv->sleeping ? "yes" : "no", + priv->net_enabled ? "yes" : "no"); priv->sleeping = do_sleep; @@ -3901,7 +3969,7 @@ sleep_auth_done_cb (NMAuthChain *chain, result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_SLEEP_WAKE); if (error) { - nm_log_dbg (LOGD_SUSPEND, "Sleep/wake request failed: %s", error->message); + _LOGD (LOGD_SUSPEND, "Sleep/wake request failed: %s", error->message); ret_error = g_error_new (NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED, "Sleep/wake request failed: %s", @@ -4006,17 +4074,16 @@ _internal_enable (NMManager *self, gboolean enable) G_TYPE_BOOLEAN, (gpointer) &enable, &err)) { /* Not a hard error */ - nm_log_warn (LOGD_SUSPEND, "writing to state file %s failed: (%d) %s.", - priv->state_file, - err ? err->code : -1, - (err && err->message) ? err->message : "unknown"); + _LOGW (LOGD_SUSPEND, "writing to state file %s failed: %s", + priv->state_file, + err->message); } } - nm_log_info (LOGD_SUSPEND, "%s requested (sleeping: %s enabled: %s)", - enable ? "enable" : "disable", - priv->sleeping ? "yes" : "no", - priv->net_enabled ? "yes" : "no"); + _LOGI (LOGD_SUSPEND, "%s requested (sleeping: %s enabled: %s)", + enable ? "enable" : "disable", + priv->sleeping ? "yes" : "no", + priv->net_enabled ? "yes" : "no"); priv->net_enabled = enable; @@ -4046,7 +4113,7 @@ enable_net_done_cb (NMAuthChain *chain, result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK); if (error) { - nm_log_dbg (LOGD_CORE, "Enable request failed: %s", error->message); + _LOGD (LOGD_CORE, "Enable request failed: %s", error->message); ret_error = g_error_new (NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED, "Enable request failed: %s", @@ -4143,7 +4210,7 @@ get_permissions_done_cb (NMAuthChain *chain, priv->auth_chains = g_slist_remove (priv->auth_chains, chain); if (error) { - nm_log_dbg (LOGD_CORE, "Permissions request failed: %s", error->message); + _LOGD (LOGD_CORE, "Permissions request failed: %s", error->message); ret_error = g_error_new (NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED, "Permissions request failed: %s", @@ -4236,8 +4303,8 @@ impl_manager_set_logging (NMManager *self, } if (nm_logging_setup (level, domains, NULL, &error)) { - nm_log_info (LOGD_CORE, "logging: level '%s' domains '%s'", - nm_logging_level_to_string (), nm_logging_domains_to_string ()); + _LOGI (LOGD_CORE, "logging: level '%s' domains '%s'", + nm_logging_level_to_string (), nm_logging_domains_to_string ()); } done: @@ -4292,7 +4359,7 @@ check_connectivity_auth_done_cb (NMAuthChain *chain, result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL); if (auth_error) { - nm_log_dbg (LOGD_CORE, "CheckConnectivity request failed: %s", auth_error->message); + _LOGD (LOGD_CORE, "CheckConnectivity request failed: %s", auth_error->message); error = g_error_new (NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED, "Connectivity check request failed: %s", @@ -4368,18 +4435,18 @@ nm_manager_start (NMManager *self, GError **error) update_rstate_from_rfkill (priv->rfkill_mgr, rstate); if (rstate->desc) { - nm_log_info (LOGD_RFKILL, "%s %s by radio killswitch; %s by state file", - rstate->desc, - (rstate->hw_enabled && rstate->sw_enabled) ? "enabled" : "disabled", - rstate->user_enabled ? "enabled" : "disabled"); + _LOGI (LOGD_RFKILL, "%s %s by radio killswitch; %s by state file", + rstate->desc, + (rstate->hw_enabled && rstate->sw_enabled) ? "enabled" : "disabled", + rstate->user_enabled ? "enabled" : "disabled"); } enabled = radio_enabled_for_rstate (rstate, TRUE); manager_update_radio_enabled (self, rstate, enabled); } /* Log overall networking status - enabled/disabled */ - nm_log_info (LOGD_CORE, "Networking is %s by state file", - priv->net_enabled ? "enabled" : "disabled"); + _LOGI (LOGD_CORE, "Networking is %s by state file", + priv->net_enabled ? "enabled" : "disabled"); system_unmanaged_devices_changed_cb (priv->settings, NULL, self); system_hostname_changed_cb (priv->settings, NULL, self); @@ -4396,7 +4463,7 @@ nm_manager_start (NMManager *self, GError **error) /* Connections added before the manager is started do not emit * connection-added signals thus devices have to be created manually. */ - nm_log_dbg (LOGD_CORE, "creating virtual devices..."); + _LOGD (LOGD_CORE, "creating virtual devices..."); connections = nm_settings_get_connections (priv->settings); for (iter = connections; iter; iter = iter->next) connection_changed (priv->settings, NM_CONNECTION (iter->data), self); @@ -4437,8 +4504,8 @@ handle_firmware_changed (gpointer user_data) if ( nm_device_get_firmware_missing (candidate) && (state == NM_DEVICE_STATE_UNAVAILABLE)) { - nm_log_info (LOGD_CORE, "(%s): firmware may now be available", - nm_device_get_iface (candidate)); + _LOGI (LOGD_CORE, "(%s): firmware may now be available", + nm_device_get_iface (candidate)); /* Re-set unavailable state to try bringing the device up again */ nm_device_state_changed (candidate, @@ -4457,8 +4524,8 @@ connectivity_changed (NMConnectivity *connectivity, { NMManager *self = NM_MANAGER (user_data); - nm_log_dbg (LOGD_CORE, "connectivity checking indicates %s", - nm_connectivity_state_to_string (nm_connectivity_get_state (connectivity))); + _LOGD (LOGD_CORE, "connectivity checking indicates %s", + nm_connectivity_state_to_string (nm_connectivity_get_state (connectivity))); nm_manager_update_state (self); g_object_notify (G_OBJECT (self), NM_MANAGER_CONNECTIVITY); @@ -4482,8 +4549,8 @@ firmware_dir_changed (GFileMonitor *monitor, case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: if (!priv->fw_changed_id) { priv->fw_changed_id = g_timeout_add_seconds (4, handle_firmware_changed, self); - nm_log_info (LOGD_CORE, "kernel firmware directory '%s' changed", - KERNEL_FIRMWARE_DIR); + _LOGI (LOGD_CORE, "kernel firmware directory '%s' changed", + KERNEL_FIRMWARE_DIR); } break; default: @@ -4534,7 +4601,7 @@ policy_default_device_changed (GObject *object, GParamSpec *pspec, gpointer user g_signal_connect (priv->primary_connection, NM_ACTIVE_CONNECTION_DEVICE_METERED_CHANGED, G_CALLBACK (connection_metered_changed), self); } - nm_log_dbg (LOGD_CORE, "PrimaryConnection now %s", ac ? nm_active_connection_get_settings_connection_id (ac) : "(none)"); + _LOGD (LOGD_CORE, "PrimaryConnection now %s", ac ? nm_active_connection_get_settings_connection_id (ac) : "(none)"); g_object_notify (G_OBJECT (self), NM_MANAGER_PRIMARY_CONNECTION); g_object_notify (G_OBJECT (self), NM_MANAGER_PRIMARY_CONNECTION_TYPE); nm_manager_update_metered (self); @@ -4569,7 +4636,7 @@ policy_activating_device_changed (GObject *object, GParamSpec *pspec, gpointer u if (ac != priv->activating_connection) { g_clear_object (&priv->activating_connection); priv->activating_connection = ac ? g_object_ref (ac) : NULL; - nm_log_dbg (LOGD_CORE, "ActivatingConnection now %s", ac ? nm_active_connection_get_settings_connection_id (ac) : "(none)"); + _LOGD (LOGD_CORE, "ActivatingConnection now %s", ac ? nm_active_connection_get_settings_connection_id (ac) : "(none)"); g_object_notify (G_OBJECT (self), NM_MANAGER_ACTIVATING_CONNECTION); } } @@ -4957,9 +5024,9 @@ manager_radio_user_toggled (NMManager *self, return; if (rstate->desc) { - nm_log_dbg (LOGD_RFKILL, "(%s): setting radio %s by user", - rstate->desc, - enabled ? "enabled" : "disabled"); + _LOGD (LOGD_RFKILL, "(%s): setting radio %s by user", + rstate->desc, + enabled ? "enabled" : "disabled"); } /* Update enabled key in state file */ @@ -4968,10 +5035,9 @@ manager_radio_user_toggled (NMManager *self, "main", rstate->key, G_TYPE_BOOLEAN, (gpointer) &enabled, &error)) { - nm_log_warn (LOGD_CORE, "writing to state file %s failed: (%d) %s.", - priv->state_file, - error ? error->code : -1, - (error && error->message) ? error->message : "unknown"); + _LOGW (LOGD_CORE, "writing to state file %s failed: %s", + priv->state_file, + error->message); g_clear_error (&error); } } @@ -5068,7 +5134,7 @@ nm_manager_setup (const char *state_file, singleton_instance = self; nm_singleton_instance_register (); - nm_log_dbg (LOGD_CORE, "setup %s singleton (%p)", "NMManager", singleton_instance); + _LOGD (LOGD_CORE, "setup %s singleton (%p)", "NMManager", singleton_instance); nm_exported_object_export ((NMExportedObject *) self); @@ -5139,9 +5205,9 @@ constructed (GObject *object) } static void -nm_manager_init (NMManager *manager) +nm_manager_init (NMManager *self) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); guint i; GFile *file; @@ -5173,20 +5239,20 @@ nm_manager_init (NMManager *manager) g_signal_connect (priv->dbus_mgr, NM_BUS_MANAGER_DBUS_CONNECTION_CHANGED, G_CALLBACK (dbus_connection_changed_cb), - manager); + self); /* sleep/wake handling */ priv->sleep_monitor = g_object_ref (nm_sleep_monitor_get ()); g_signal_connect (priv->sleep_monitor, NM_SLEEP_MONITOR_SLEEPING, - G_CALLBACK (sleeping_cb), manager); + G_CALLBACK (sleeping_cb), self); g_signal_connect (priv->sleep_monitor, NM_SLEEP_MONITOR_RESUMING, - G_CALLBACK (resuming_cb), manager); + G_CALLBACK (resuming_cb), self); /* Listen for authorization changes */ g_signal_connect (nm_auth_manager_get (), NM_AUTH_MANAGER_SIGNAL_CHANGED, G_CALLBACK (authority_changed_cb), - manager); + self); /* Monitor the firmware directory */ @@ -5199,16 +5265,16 @@ nm_manager_init (NMManager *manager) if (priv->fw_monitor) { g_signal_connect (priv->fw_monitor, "changed", G_CALLBACK (firmware_dir_changed), - manager); - nm_log_info (LOGD_CORE, "monitoring kernel firmware directory '%s'.", + self); + _LOGI (LOGD_CORE, "monitoring kernel firmware directory '%s'.", KERNEL_FIRMWARE_DIR); } else { - nm_log_warn (LOGD_CORE, "failed to monitor kernel firmware directory '%s'.", - KERNEL_FIRMWARE_DIR); + _LOGW (LOGD_CORE, "failed to monitor kernel firmware directory '%s'.", + KERNEL_FIRMWARE_DIR); } /* Update timestamps in active connections */ - priv->timestamp_update_id = g_timeout_add_seconds (300, (GSourceFunc) periodic_update_active_connection_timestamps, manager); + priv->timestamp_update_id = g_timeout_add_seconds (300, (GSourceFunc) periodic_update_active_connection_timestamps, self); priv->metered = NM_METERED_UNKNOWN; } @@ -5359,7 +5425,7 @@ set_property (GObject *object, guint prop_id, nm_global_dns_config_free (dns_config); if (error) { - nm_log_dbg (LOGD_CORE, "set global DNS failed with error: %s", error->message); + _LOGD (LOGD_CORE, "set global DNS failed with error: %s", error->message); g_error_free (error); } break; diff --git a/src/nm-policy.c b/src/nm-policy.c index 68e50a1c..a46b35a2 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -47,10 +47,18 @@ #include "nm-dhcp4-config.h" #include "nm-dhcp6-config.h" +#define _NMLOG_PREFIX_NAME "policy" +#define _NMLOG(level, domain, ...) \ + G_STMT_START { \ + nm_log ((level), (domain), \ + "%s" _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ + _NMLOG_PREFIX_NAME": " \ + _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ + } G_STMT_END + typedef struct { NMManager *manager; NMFirewallManager *firewall_manager; - guint update_state_id; GSList *pending_activation_checks; GSList *manager_ids; GSList *settings_ids; @@ -82,16 +90,16 @@ typedef struct { G_DEFINE_TYPE (NMPolicy, nm_policy, G_TYPE_OBJECT) -enum { - PROP_0, - +NM_GOBJECT_PROPERTIES_DEFINE (NMPolicy, + PROP_MANAGER, + PROP_SETTINGS, PROP_DEFAULT_IP4_DEVICE, PROP_DEFAULT_IP6_DEVICE, PROP_ACTIVATING_IP4_DEVICE, - PROP_ACTIVATING_IP6_DEVICE -}; + PROP_ACTIVATING_IP6_DEVICE, +); -static void schedule_activate_all (NMPolicy *policy); +static void schedule_activate_all (NMPolicy *self); static NMDevice * @@ -118,51 +126,38 @@ get_best_ip6_device (NMPolicy *self, gboolean fully_activated) #define FALLBACK_HOSTNAME4 "localhost.localdomain" -static gboolean -set_system_hostname (const char *new_hostname, const char *msg) +static void +settings_set_hostname_cb (const char *hostname, + gboolean result, + gpointer user_data) { - char old_hostname[HOST_NAME_MAX + 1]; - const char *name; - int ret; + int ret = 0; - if (new_hostname) - g_warn_if_fail (strlen (new_hostname)); + if (!result) { + ret = sethostname (hostname, strlen (hostname)); + if (ret != 0) { + int errsv = errno; - old_hostname[HOST_NAME_MAX] = '\0'; - errno = 0; - ret = gethostname (old_hostname, HOST_NAME_MAX); - if (ret != 0) { - nm_log_warn (LOGD_DNS, "couldn't get the system hostname: (%d) %s", - errno, strerror (errno)); - } else { - /* Don't set the hostname if it isn't actually changing */ - if ( (new_hostname && !strcmp (old_hostname, new_hostname)) - || (!new_hostname && !strcmp (old_hostname, FALLBACK_HOSTNAME4))) - return FALSE; - } - - name = (new_hostname && strlen (new_hostname)) ? new_hostname : FALLBACK_HOSTNAME4; - - nm_log_info (LOGD_DNS, "Setting system hostname to '%s' (%s)", name, msg); - ret = sethostname (name, strlen (name)); - if (ret != 0) { - int errsv = errno; - - nm_log_warn (LOGD_DNS, "couldn't set the system hostname to '%s': (%d) %s", - name, errsv, strerror (errsv)); - if (errsv == EPERM) - nm_log_warn (LOGD_DNS, "You should use hostnamed when systemd hardening is in effect!"); + _LOGW (LOGD_DNS, "couldn't set the system hostname to '%s': (%d) %s", + hostname, errsv, strerror (errsv)); + if (errsv == EPERM) + _LOGW (LOGD_DNS, "you should use hostnamed when systemd hardening is in effect!"); + } } - return (ret == 0); + if (!ret) + nm_dispatcher_call (DISPATCHER_ACTION_HOSTNAME, NULL, NULL, NULL, NULL, NULL, NULL); } static void -_set_hostname (NMPolicy *policy, +_set_hostname (NMPolicy *self, const char *new_hostname, const char *msg) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); + char old_hostname[HOST_NAME_MAX + 1]; + const char *name; + int ret; /* The incoming hostname *can* be NULL, which will get translated to * 'localhost.localdomain' or such in the hostname policy code, but we @@ -194,10 +189,41 @@ _set_hostname (NMPolicy *policy, priv->cur_hostname = g_strdup (new_hostname); priv->hostname_changed = TRUE; + /* Notify the DNS manager of the hostname change so that the domain part, if + * present, can be added to the search list. + */ nm_dns_manager_set_hostname (priv->dns_manager, priv->cur_hostname); - if (set_system_hostname (priv->cur_hostname, msg)) - nm_dispatcher_call (DISPATCHER_ACTION_HOSTNAME, NULL, NULL, NULL, NULL, NULL, NULL); + /* Finally, set kernel hostname */ + + if (!priv->cur_hostname) + name = FALLBACK_HOSTNAME4; + else if (!priv->cur_hostname[0]) { + g_warn_if_reached (); + name = FALLBACK_HOSTNAME4; + } else + name = priv->cur_hostname; + + old_hostname[HOST_NAME_MAX] = '\0'; + errno = 0; + ret = gethostname (old_hostname, HOST_NAME_MAX); + if (ret != 0) { + _LOGW (LOGD_DNS, "couldn't get the system hostname: (%d) %s", + errno, strerror (errno)); + } else { + /* Don't set the hostname if it isn't actually changing */ + if (nm_streq (name, old_hostname)) + return; + } + + _LOGI (LOGD_DNS, "setting system hostname to '%s' (%s)", name, msg); + + /* Ask NMSettings to update the transient hostname using its + * systemd-hostnamed proxy */ + nm_settings_set_transient_hostname (priv->settings, + name, + settings_set_hostname_cb, + NULL); } static void @@ -205,8 +231,8 @@ lookup_callback (GObject *source, GAsyncResult *result, gpointer user_data) { - NMPolicy *policy = (NMPolicy *) user_data; - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicy *self = (NMPolicy *) user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); const char *hostname; GError *error = NULL; @@ -218,9 +244,9 @@ lookup_callback (GObject *source, } if (hostname) - _set_hostname (policy, hostname, "from address lookup"); + _set_hostname (self, hostname, "from address lookup"); else { - _set_hostname (policy, NULL, error->message); + _set_hostname (self, NULL, error->message); g_error_free (error); } @@ -228,15 +254,15 @@ lookup_callback (GObject *source, } static void -update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6) +update_system_hostname (NMPolicy *self, NMDevice *best4, NMDevice *best6) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); char *configured_hostname = NULL; const char *dhcp_hostname, *p; NMIP4Config *ip4_config; NMIP6Config *ip6_config; - g_return_if_fail (policy != NULL); + g_return_if_fail (self != NULL); if (priv->lookup_cancellable) { g_cancellable_cancel (priv->lookup_cancellable); @@ -255,7 +281,7 @@ update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6) /* Try a persistent hostname first */ g_object_get (G_OBJECT (priv->manager), NM_MANAGER_HOSTNAME, &configured_hostname, NULL); if (configured_hostname && nm_utils_is_specific_hostname (configured_hostname)) { - _set_hostname (policy, configured_hostname, "from system configuration"); + _set_hostname (self, configured_hostname, "from system configuration"); g_free (configured_hostname); return; } @@ -263,15 +289,15 @@ update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6) /* Try automatically determined hostname from the best device's IP config */ if (!best4) - best4 = get_best_ip4_device (policy, TRUE); + best4 = get_best_ip4_device (self, TRUE); if (!best6) - best6 = get_best_ip6_device (policy, TRUE); + best6 = get_best_ip6_device (self, TRUE); if (!best4 && !best6) { /* No best device; fall back to original hostname or if there wasn't * one, 'localhost.localdomain' */ - _set_hostname (policy, priv->orig_hostname, "no default device"); + _set_hostname (self, priv->orig_hostname, "no default device"); return; } @@ -286,12 +312,12 @@ update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6) /* Sanity check; strip leading spaces */ while (*p) { if (!g_ascii_isspace (*p++)) { - _set_hostname (policy, p-1, "from DHCPv4"); + _set_hostname (self, p-1, "from DHCPv4"); return; } } - nm_log_warn (LOGD_DNS, "DHCPv4-provided hostname '%s' looks invalid; ignoring it", - dhcp_hostname); + _LOGW (LOGD_DNS, "DHCPv4-provided hostname '%s' looks invalid; ignoring it", + dhcp_hostname); } } } else if (best6) { @@ -305,12 +331,12 @@ update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6) /* Sanity check; strip leading spaces */ while (*p) { if (!g_ascii_isspace (*p++)) { - _set_hostname (policy, p-1, "from DHCPv6"); + _set_hostname (self, p-1, "from DHCPv6"); return; } } - nm_log_warn (LOGD_DNS, "DHCPv6-provided hostname '%s' looks invalid; ignoring it", - dhcp_hostname); + _LOGW (LOGD_DNS, "DHCPv6-provided hostname '%s' looks invalid; ignoring it", + dhcp_hostname); } } } @@ -319,7 +345,7 @@ update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6) * when NM started up. */ if (priv->orig_hostname) { - _set_hostname (policy, priv->orig_hostname, "from system startup"); + _set_hostname (self, priv->orig_hostname, "from system startup"); return; } @@ -345,7 +371,7 @@ update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6) G_SOCKET_FAMILY_IPV6); } else { /* No valid IP config; fall back to localhost.localdomain */ - _set_hostname (policy, NULL, "no IP config"); + _set_hostname (self, NULL, "no IP config"); return; } @@ -353,15 +379,15 @@ update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6) g_resolver_lookup_by_address_async (priv->resolver, priv->lookup_addr, priv->lookup_cancellable, - lookup_callback, policy); + lookup_callback, self); } static void -update_default_ac (NMPolicy *policy, +update_default_ac (NMPolicy *self, NMActiveConnection *best, void (*set_active_func)(NMActiveConnection*, gboolean)) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); const GSList *connections, *iter; /* Clear the 'default[6]' flag on all active connections that aren't the new @@ -396,14 +422,14 @@ get_best_ip4_config (NMPolicy *self, } static void -update_ip4_dns (NMPolicy *policy, NMDnsManager *dns_mgr) +update_ip4_dns (NMPolicy *self, NMDnsManager *dns_mgr) { NMIP4Config *ip4_config; const char *ip_iface = NULL; NMVpnConnection *vpn = NULL; NMDnsIPConfigType dns_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE; - ip4_config = get_best_ip4_config (policy, TRUE, &ip_iface, NULL, NULL, &vpn); + ip4_config = get_best_ip4_config (self, TRUE, &ip_iface, NULL, NULL, &vpn); if (ip4_config) { if (vpn) dns_type = NM_DNS_IP_CONFIG_TYPE_VPN; @@ -416,9 +442,9 @@ update_ip4_dns (NMPolicy *policy, NMDnsManager *dns_mgr) } static void -update_ip4_routing (NMPolicy *policy, gboolean force_update) +update_ip4_routing (NMPolicy *self, gboolean force_update) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); NMDevice *best = NULL, *default_device; NMConnection *connection = NULL; NMVpnConnection *vpn = NULL; @@ -428,13 +454,13 @@ update_ip4_routing (NMPolicy *policy, gboolean force_update) /* Note that we might have an IPv4 VPN tunneled over an IPv6-only device, * so we can get (vpn != NULL && best == NULL). */ - if (!get_best_ip4_config (policy, FALSE, &ip_iface, &best_ac, &best, &vpn)) { + if (!get_best_ip4_config (self, FALSE, &ip_iface, &best_ac, &best, &vpn)) { gboolean changed; changed = (priv->default_device4 != NULL); priv->default_device4 = NULL; if (changed) - g_object_notify (G_OBJECT (policy), NM_POLICY_DEFAULT_IP4_DEVICE); + _notify (self, PROP_DEFAULT_IP4_DEVICE); return; } @@ -462,16 +488,16 @@ update_ip4_routing (NMPolicy *policy, gboolean force_update) else default_device = best; - update_default_ac (policy, best_ac, nm_active_connection_set_default); + update_default_ac (self, best_ac, nm_active_connection_set_default); if (default_device == priv->default_device4) return; priv->default_device4 = default_device; connection = nm_active_connection_get_applied_connection (best_ac); - nm_log_info (LOGD_CORE, "Policy set '%s' (%s) as default for IPv4 routing and DNS.", - nm_connection_get_id (connection), ip_iface); - g_object_notify (G_OBJECT (policy), NM_POLICY_DEFAULT_IP4_DEVICE); + _LOGI (LOGD_CORE, "set '%s' (%s) as default for IPv4 routing and DNS", + nm_connection_get_id (connection), ip_iface); + _notify (self, PROP_DEFAULT_IP4_DEVICE); } static NMIP6Config * @@ -491,14 +517,14 @@ get_best_ip6_config (NMPolicy *self, } static void -update_ip6_dns (NMPolicy *policy, NMDnsManager *dns_mgr) +update_ip6_dns (NMPolicy *self, NMDnsManager *dns_mgr) { NMIP6Config *ip6_config; const char *ip_iface = NULL; NMVpnConnection *vpn = NULL; NMDnsIPConfigType dns_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE; - ip6_config = get_best_ip6_config (policy, TRUE, &ip_iface, NULL, NULL, &vpn); + ip6_config = get_best_ip6_config (self, TRUE, &ip_iface, NULL, NULL, &vpn); if (ip6_config) { if (vpn) dns_type = NM_DNS_IP_CONFIG_TYPE_VPN; @@ -511,9 +537,9 @@ update_ip6_dns (NMPolicy *policy, NMDnsManager *dns_mgr) } static void -update_ip6_routing (NMPolicy *policy, gboolean force_update) +update_ip6_routing (NMPolicy *self, gboolean force_update) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); NMDevice *best = NULL, *default_device6; NMConnection *connection = NULL; NMVpnConnection *vpn = NULL; @@ -523,13 +549,13 @@ update_ip6_routing (NMPolicy *policy, gboolean force_update) /* Note that we might have an IPv6 VPN tunneled over an IPv4-only device, * so we can get (vpn != NULL && best == NULL). */ - if (!get_best_ip6_config (policy, FALSE, &ip_iface, &best_ac, &best, &vpn)) { + if (!get_best_ip6_config (self, FALSE, &ip_iface, &best_ac, &best, &vpn)) { gboolean changed; changed = (priv->default_device6 != NULL); priv->default_device6 = NULL; if (changed) - g_object_notify (G_OBJECT (policy), NM_POLICY_DEFAULT_IP6_DEVICE); + _notify (self, PROP_DEFAULT_IP6_DEVICE); return; } @@ -557,56 +583,56 @@ update_ip6_routing (NMPolicy *policy, gboolean force_update) else default_device6 = best; - update_default_ac (policy, best_ac, nm_active_connection_set_default6); + update_default_ac (self, best_ac, nm_active_connection_set_default6); if (default_device6 == priv->default_device6) return; priv->default_device6 = default_device6; connection = nm_active_connection_get_applied_connection (best_ac); - nm_log_info (LOGD_CORE, "Policy set '%s' (%s) as default for IPv6 routing and DNS.", - nm_connection_get_id (connection), ip_iface); - g_object_notify (G_OBJECT (policy), NM_POLICY_DEFAULT_IP6_DEVICE); + _LOGI (LOGD_CORE, "set '%s' (%s) as default for IPv6 routing and DNS", + nm_connection_get_id (connection), ip_iface); + _notify (self, PROP_DEFAULT_IP6_DEVICE); } static void -update_routing_and_dns (NMPolicy *policy, gboolean force_update) +update_routing_and_dns (NMPolicy *self, gboolean force_update) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); nm_dns_manager_begin_updates (priv->dns_manager, __func__); - update_ip4_dns (policy, priv->dns_manager); - update_ip6_dns (policy, priv->dns_manager); + update_ip4_dns (self, priv->dns_manager); + update_ip6_dns (self, priv->dns_manager); - update_ip4_routing (policy, force_update); - update_ip6_routing (policy, force_update); + update_ip4_routing (self, force_update); + update_ip6_routing (self, force_update); /* Update the system hostname */ - update_system_hostname (policy, priv->default_device4, priv->default_device6); + update_system_hostname (self, priv->default_device4, priv->default_device6); nm_dns_manager_end_updates (priv->dns_manager, __func__); } static void -check_activating_devices (NMPolicy *policy) +check_activating_devices (NMPolicy *self) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); - GObject *object = G_OBJECT (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); + GObject *object = G_OBJECT (self); NMDevice *best4, *best6 = NULL; - best4 = get_best_ip4_device (policy, FALSE); - best6 = get_best_ip6_device (policy, FALSE); + best4 = get_best_ip4_device (self, FALSE); + best6 = get_best_ip6_device (self, FALSE); g_object_freeze_notify (object); if (best4 != priv->activating_device4) { priv->activating_device4 = best4; - g_object_notify (object, NM_POLICY_ACTIVATING_IP4_DEVICE); + _notify (self, PROP_ACTIVATING_IP4_DEVICE); } if (best6 != priv->activating_device6) { priv->activating_device6 = best6; - g_object_notify (object, NM_POLICY_ACTIVATING_IP6_DEVICE); + _notify (self, PROP_ACTIVATING_IP6_DEVICE); } g_object_thaw_notify (object); @@ -629,14 +655,15 @@ activate_data_free (ActivateData *data) if (data->autoactivate_id) g_source_remove (data->autoactivate_id); g_object_unref (data->device); - g_free (data); + + g_slice_free (ActivateData, data); } static gboolean auto_activate_device (gpointer user_data) { ActivateData *data = (ActivateData *) user_data; - NMPolicy *policy; + NMPolicy *self; NMPolicyPrivate *priv; NMSettingsConnection *best_connection; char *specific_object = NULL; @@ -645,8 +672,8 @@ auto_activate_device (gpointer user_data) guint i; g_assert (data); - policy = data->policy; - priv = NM_POLICY_GET_PRIVATE (policy); + self = data->policy; + priv = NM_POLICY_GET_PRIVATE (self); data->autoactivate_id = 0; @@ -686,8 +713,8 @@ auto_activate_device (gpointer user_data) GError *error = NULL; NMAuthSubject *subject; - nm_log_info (LOGD_DEVICE, "Auto-activating connection '%s'.", - nm_settings_connection_get_id (best_connection)); + _LOGI (LOGD_DEVICE, "auto-activating connection '%s'", + nm_settings_connection_get_id (best_connection)); subject = nm_auth_subject_new_internal (); if (!nm_manager_activate_connection (priv->manager, best_connection, @@ -695,10 +722,10 @@ auto_activate_device (gpointer user_data) data->device, subject, &error)) { - nm_log_info (LOGD_DEVICE, "Connection '%s' auto-activation failed: (%d) %s", - nm_settings_connection_get_id (best_connection), - error ? error->code : -1, - error ? error->message : "(none)"); + _LOGI (LOGD_DEVICE, "connection '%s' auto-activation failed: (%d) %s", + nm_settings_connection_get_id (best_connection), + error->code, + error->message); g_error_free (error); } g_object_unref (subject); @@ -733,7 +760,7 @@ pending_secondary_data_new (NMDevice *device, GSList *secondaries) { PendingSecondaryData *data; - data = g_malloc0 (sizeof (PendingSecondaryData)); + data = g_slice_new (PendingSecondaryData); data->device = g_object_ref (device); data->secondaries = secondaries; return data; @@ -744,16 +771,15 @@ pending_secondary_data_free (PendingSecondaryData *data) { g_object_unref (data->device); g_slist_free_full (data->secondaries, g_object_unref); - memset (data, 0, sizeof (*data)); - g_free (data); + g_slice_free (PendingSecondaryData, data); } static void -process_secondaries (NMPolicy *policy, +process_secondaries (NMPolicy *self, NMActiveConnection *active, gboolean connected) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); GSList *iter, *iter2, *next, *next2; /* Loop through devices waiting for secondary connections to activate */ @@ -773,9 +799,9 @@ process_secondaries (NMPolicy *policy, continue; if (connected) { - nm_log_dbg (LOGD_DEVICE, "Secondary connection '%s' SUCCEEDED; active path '%s'", - nm_active_connection_get_settings_connection_id (active), - nm_exported_object_get_path (NM_EXPORTED_OBJECT (active))); + _LOGD (LOGD_DEVICE, "secondary connection '%s' succeeded; active path '%s'", + nm_active_connection_get_settings_connection_id (active), + nm_exported_object_get_path (NM_EXPORTED_OBJECT (active))); /* Secondary connection activated */ secondary_data->secondaries = g_slist_remove (secondary_data->secondaries, secondary_active); @@ -789,9 +815,9 @@ process_secondaries (NMPolicy *policy, break; } } else { - nm_log_dbg (LOGD_DEVICE, "Secondary connection '%s' FAILED; active path '%s'", - nm_active_connection_get_settings_connection_id (active), - nm_exported_object_get_path (NM_EXPORTED_OBJECT (active))); + _LOGD (LOGD_DEVICE, "secondary connection '%s' failed; active path '%s'", + nm_active_connection_get_settings_connection_id (active), + nm_exported_object_get_path (NM_EXPORTED_OBJECT (active))); /* Secondary connection failed -> do not watch other connections */ priv->pending_secondaries = g_slist_remove (priv->pending_secondaries, secondary_data); @@ -818,16 +844,16 @@ hostname_changed (NMManager *manager, GParamSpec *pspec, gpointer user_data) } static void -reset_autoconnect_all (NMPolicy *policy, NMDevice *device) +reset_autoconnect_all (NMPolicy *self, NMDevice *device) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); GSList *connections, *iter; if (device) { - nm_log_dbg (LOGD_DEVICE, "Re-enabling autoconnect for all connections on %s", - nm_device_get_iface (device)); + _LOGD (LOGD_DEVICE, "re-enabling autoconnect for all connections on %s", + nm_device_get_iface (device)); } else - nm_log_dbg (LOGD_DEVICE, "Re-enabling autoconnect for all connections"); + _LOGD (LOGD_DEVICE, "re-enabling autoconnect for all connections"); connections = nm_settings_get_connections (priv->settings); for (iter = connections; iter; iter = g_slist_next (iter)) { @@ -840,12 +866,12 @@ reset_autoconnect_all (NMPolicy *policy, NMDevice *device) } static void -reset_autoconnect_for_failed_secrets (NMPolicy *policy) +reset_autoconnect_for_failed_secrets (NMPolicy *self) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); GSList *connections, *iter; - nm_log_dbg (LOGD_DEVICE, "Re-enabling autoconnect for all connections with failed secrets"); + _LOGD (LOGD_DEVICE, "re-enabling autoconnect for all connections with failed secrets"); connections = nm_settings_get_connections (priv->settings); for (iter = connections; iter; iter = g_slist_next (iter)) { @@ -860,13 +886,13 @@ reset_autoconnect_for_failed_secrets (NMPolicy *policy) } static void -block_autoconnect_for_device (NMPolicy *policy, NMDevice *device) +block_autoconnect_for_device (NMPolicy *self, NMDevice *device) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); GSList *connections, *iter; - nm_log_dbg (LOGD_DEVICE, "Blocking autoconnect for all connections on %s", - nm_device_get_iface (device)); + _LOGD (LOGD_DEVICE, "blocking autoconnect for all connections on %s", + nm_device_get_iface (device)); /* NMDevice keeps its own autoconnect-able-ness state; we only need to * explicitly block connections for software devices, where the NMDevice @@ -887,7 +913,7 @@ block_autoconnect_for_device (NMPolicy *policy, NMDevice *device) static void sleeping_changed (NMManager *manager, GParamSpec *pspec, gpointer user_data) { - NMPolicy *policy = user_data; + NMPolicy *self = user_data; gboolean sleeping = FALSE, enabled = FALSE; g_object_get (G_OBJECT (manager), NM_MANAGER_SLEEPING, &sleeping, NULL); @@ -895,13 +921,13 @@ sleeping_changed (NMManager *manager, GParamSpec *pspec, gpointer user_data) /* Reset retries on all connections so they'll checked on wakeup */ if (sleeping || !enabled) - reset_autoconnect_all (policy, NULL); + reset_autoconnect_all (self, NULL); } static void -schedule_activate_check (NMPolicy *policy, NMDevice *device) +schedule_activate_check (NMPolicy *self, NMDevice *device) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); ActivateData *data; const GSList *active_connections, *iter; @@ -925,17 +951,17 @@ schedule_activate_check (NMPolicy *policy, NMDevice *device) nm_device_add_pending_action (device, "autoactivate", TRUE); - data = g_malloc0 (sizeof (ActivateData)); - data->policy = policy; + data = g_slice_new0 (ActivateData); + data->policy = self; data->device = g_object_ref (device); data->autoactivate_id = g_idle_add (auto_activate_device, data); priv->pending_activation_checks = g_slist_append (priv->pending_activation_checks, data); } static void -clear_pending_activate_check (NMPolicy *policy, NMDevice *device) +clear_pending_activate_check (NMPolicy *self, NMDevice *device) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); ActivateData *data; data = find_pending_activation (priv->pending_activation_checks, device); @@ -946,8 +972,8 @@ clear_pending_activate_check (NMPolicy *policy, NMDevice *device) static gboolean reset_connections_retries (gpointer user_data) { - NMPolicy *policy = (NMPolicy *) user_data; - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicy *self = (NMPolicy *) user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); GSList *connections, *iter; gint32 con_stamp, min_stamp, now; gboolean changed = FALSE; @@ -974,21 +1000,21 @@ reset_connections_retries (gpointer user_data) /* Schedule the handler again if there are some stamps left */ if (min_stamp != 0) - priv->reset_retries_id = g_timeout_add_seconds (min_stamp - now, reset_connections_retries, policy); + priv->reset_retries_id = g_timeout_add_seconds (min_stamp - now, reset_connections_retries, self); /* If anything changed, try to activate the newly re-enabled connections */ if (changed) - schedule_activate_all (policy); + schedule_activate_all (self); return FALSE; } -static void schedule_activate_all (NMPolicy *policy); +static void schedule_activate_all (NMPolicy *self); static void -activate_slave_connections (NMPolicy *policy, NMDevice *device) +activate_slave_connections (NMPolicy *self, NMDevice *device) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); const char *master_device, *master_uuid_settings = NULL, *master_uuid_applied = NULL; GSList *connections, *iter; NMActRequest *req; @@ -1034,15 +1060,15 @@ activate_slave_connections (NMPolicy *policy, NMDevice *device) g_slist_free (connections); - schedule_activate_all (policy); + schedule_activate_all (self); } static gboolean -activate_secondary_connections (NMPolicy *policy, +activate_secondary_connections (NMPolicy *self, NMConnection *connection, NMDevice *device) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); NMSettingConnection *s_con; NMSettingsConnection *settings_con; NMActiveConnection *ac; @@ -1061,14 +1087,14 @@ activate_secondary_connections (NMPolicy *policy, settings_con = nm_settings_get_connection_by_uuid (priv->settings, sec_uuid); if (!settings_con) { - nm_log_warn (LOGD_DEVICE, "Secondary connection '%s' auto-activation failed: The connection doesn't exist.", - sec_uuid); + _LOGW (LOGD_DEVICE, "secondary connection '%s' auto-activation failed: The connection doesn't exist.", + sec_uuid); success = FALSE; break; } if (!nm_connection_is_type (NM_CONNECTION (settings_con), NM_SETTING_VPN_SETTING_NAME)) { - nm_log_warn (LOGD_DEVICE, "Secondary connection '%s (%s)' auto-activation failed: The connection is not a VPN.", - nm_settings_connection_get_id (settings_con), sec_uuid); + _LOGW (LOGD_DEVICE, "secondary connection '%s (%s)' auto-activation failed: The connection is not a VPN.", + nm_settings_connection_get_id (settings_con), sec_uuid); success = FALSE; break; } @@ -1076,9 +1102,9 @@ activate_secondary_connections (NMPolicy *policy, req = nm_device_get_act_request (device); g_assert (req); - nm_log_dbg (LOGD_DEVICE, "Activating secondary connection '%s (%s)' for base connection '%s (%s)'", - nm_settings_connection_get_id (settings_con), sec_uuid, - nm_connection_get_id (connection), nm_connection_get_uuid (connection)); + _LOGD (LOGD_DEVICE, "activating secondary connection '%s (%s)' for base connection '%s (%s)'", + nm_settings_connection_get_id (settings_con), sec_uuid, + nm_connection_get_id (connection), nm_connection_get_uuid (connection)); ac = nm_manager_activate_connection (priv->manager, settings_con, nm_exported_object_get_path (NM_EXPORTED_OBJECT (req)), @@ -1088,10 +1114,10 @@ activate_secondary_connections (NMPolicy *policy, if (ac) secondary_ac_list = g_slist_append (secondary_ac_list, g_object_ref (ac)); else { - nm_log_warn (LOGD_DEVICE, "Secondary connection '%s (%s)' auto-activation failed: (%d) %s", - nm_settings_connection_get_id (settings_con), sec_uuid, - error ? error->code : 0, - (error && error->message) ? error->message : "unknown"); + _LOGW (LOGD_DEVICE, "secondary connection '%s (%s)' auto-activation failed: (%d) %s", + nm_settings_connection_get_id (settings_con), sec_uuid, + error->code, + error->message); g_clear_error (&error); success = FALSE; break; @@ -1114,8 +1140,8 @@ device_state_changed (NMDevice *device, NMDeviceStateReason reason, gpointer user_data) { - NMPolicy *policy = (NMPolicy *) user_data; - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicy *self = (NMPolicy *) user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); NMSettingsConnection *connection = nm_device_get_settings_connection (device); @@ -1135,25 +1161,25 @@ device_state_changed (NMDevice *device, guint32 tries = nm_settings_connection_get_autoconnect_retries (connection); if (reason == NM_DEVICE_STATE_REASON_NO_SECRETS) { - nm_log_dbg (LOGD_DEVICE, "Connection '%s' now blocked from autoconnect due to no secrets", - nm_settings_connection_get_id (connection)); + _LOGD (LOGD_DEVICE, "connection '%s' now blocked from autoconnect due to no secrets", + nm_settings_connection_get_id (connection)); nm_settings_connection_set_autoconnect_blocked_reason (connection, NM_DEVICE_STATE_REASON_NO_SECRETS); } else if (tries > 0) { - nm_log_dbg (LOGD_DEVICE, "Connection '%s' failed to autoconnect; %d tries left", - nm_settings_connection_get_id (connection), tries); + _LOGD (LOGD_DEVICE, "connection '%s' failed to autoconnect; %d tries left", + nm_settings_connection_get_id (connection), tries); nm_settings_connection_set_autoconnect_retries (connection, tries - 1); } if (nm_settings_connection_get_autoconnect_retries (connection) == 0) { - nm_log_info (LOGD_DEVICE, "Disabling autoconnect for connection '%s'.", - nm_settings_connection_get_id (connection)); + _LOGI (LOGD_DEVICE, "disabling autoconnect for connection '%s'.", + nm_settings_connection_get_id (connection)); /* Schedule a handler to reset retries count */ if (!priv->reset_retries_id) { gint32 retry_time = nm_settings_connection_get_autoconnect_retry_time (connection); g_warn_if_fail (retry_time != 0); - priv->reset_retries_id = g_timeout_add_seconds (MAX (0, retry_time - nm_utils_get_monotonic_timestamp_s ()), reset_connections_retries, policy); + priv->reset_retries_id = g_timeout_add_seconds (MAX (0, retry_time - nm_utils_get_monotonic_timestamp_s ()), reset_connections_retries, self); } } nm_connection_clear_secrets (NM_CONNECTION (connection)); @@ -1182,25 +1208,25 @@ device_state_changed (NMDevice *device, if (ip6_config) nm_dns_manager_add_ip6_config (priv->dns_manager, ip_iface, ip6_config, NM_DNS_IP_CONFIG_TYPE_DEFAULT); - update_routing_and_dns (policy, FALSE); + update_routing_and_dns (self, FALSE); nm_dns_manager_end_updates (priv->dns_manager, __func__); break; case NM_DEVICE_STATE_UNMANAGED: case NM_DEVICE_STATE_UNAVAILABLE: if (old_state > NM_DEVICE_STATE_DISCONNECTED) - update_routing_and_dns (policy, FALSE); + update_routing_and_dns (self, FALSE); break; case NM_DEVICE_STATE_DEACTIVATING: if (reason == NM_DEVICE_STATE_REASON_USER_REQUESTED) { if (!nm_device_get_autoconnect (device)) { /* The device was disconnected; block all connections on it */ - block_autoconnect_for_device (policy, device); + block_autoconnect_for_device (self, device); } else { if (connection) { /* The connection was deactivated, so block just this connection */ - nm_log_dbg (LOGD_DEVICE, "Blocking autoconnect of connection '%s' by user request", - nm_settings_connection_get_id (connection)); + _LOGD (LOGD_DEVICE, "blocking autoconnect of connection '%s' by user request", + nm_settings_connection_get_id (connection)); nm_settings_connection_set_autoconnect_blocked_reason (connection, NM_DEVICE_STATE_REASON_USER_REQUESTED); } @@ -1212,19 +1238,19 @@ device_state_changed (NMDevice *device, * was unplugged and plugged in again, we should try to reconnect. */ if (reason == NM_DEVICE_STATE_REASON_CARRIER && old_state == NM_DEVICE_STATE_UNAVAILABLE) - reset_autoconnect_all (policy, device); + reset_autoconnect_all (self, device); if (old_state > NM_DEVICE_STATE_DISCONNECTED) - update_routing_and_dns (policy, FALSE); + update_routing_and_dns (self, FALSE); /* Device is now available for auto-activation */ - schedule_activate_check (policy, device); + schedule_activate_check (self, device); break; case NM_DEVICE_STATE_PREPARE: /* Reset auto-connect retries of all slaves and schedule them for * activation. */ - activate_slave_connections (policy, device); + activate_slave_connections (self, device); break; case NM_DEVICE_STATE_IP_CONFIG: /* We must have secrets if we got here. */ @@ -1236,10 +1262,10 @@ device_state_changed (NMDevice *device, s_con = nm_connection_get_setting_connection (NM_CONNECTION (connection)); if (s_con && nm_setting_connection_get_num_secondaries (s_con) > 0) { /* Make routes and DNS up-to-date before activating dependent connections */ - update_routing_and_dns (policy, FALSE); + update_routing_and_dns (self, FALSE); /* Activate secondary (VPN) connections */ - if (!activate_secondary_connections (policy, NM_CONNECTION (connection), device)) + if (!activate_secondary_connections (self, NM_CONNECTION (connection), device)) nm_device_queue_state (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED); } else @@ -1251,7 +1277,7 @@ device_state_changed (NMDevice *device, break; } - check_activating_devices (policy); + check_activating_devices (self); } static void @@ -1260,8 +1286,8 @@ device_ip4_config_changed (NMDevice *device, NMIP4Config *old_config, gpointer user_data) { - NMPolicy *policy = user_data; - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicy *self = user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); const char *ip_iface = nm_device_get_ip_iface (device); nm_dns_manager_begin_updates (priv->dns_manager, __func__); @@ -1277,8 +1303,8 @@ device_ip4_config_changed (NMDevice *device, if (new_config) nm_dns_manager_add_ip4_config (priv->dns_manager, ip_iface, new_config, NM_DNS_IP_CONFIG_TYPE_DEFAULT); } - update_ip4_dns (policy, priv->dns_manager); - update_ip4_routing (policy, TRUE); + update_ip4_dns (self, priv->dns_manager); + update_ip4_routing (self, TRUE); } else { /* Old configs get removed immediately */ if (old_config) @@ -1294,8 +1320,8 @@ device_ip6_config_changed (NMDevice *device, NMIP6Config *old_config, gpointer user_data) { - NMPolicy *policy = user_data; - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicy *self = user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); const char *ip_iface = nm_device_get_ip_iface (device); nm_dns_manager_begin_updates (priv->dns_manager, __func__); @@ -1311,8 +1337,8 @@ device_ip6_config_changed (NMDevice *device, if (new_config) nm_dns_manager_add_ip6_config (priv->dns_manager, ip_iface, new_config, NM_DNS_IP_CONFIG_TYPE_DEFAULT); } - update_ip6_dns (policy, priv->dns_manager); - update_ip6_routing (policy, TRUE); + update_ip6_dns (self, priv->dns_manager); + update_ip6_routing (self, TRUE); } else { /* Old configs get removed immediately */ if (old_config) @@ -1343,21 +1369,21 @@ typedef struct { } DeviceSignalId; static void -_connect_device_signal (NMPolicy *policy, +_connect_device_signal (NMPolicy *self, NMDevice *device, const char *name, gpointer callback, gboolean after) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); DeviceSignalId *data; data = g_slice_new0 (DeviceSignalId); g_assert (data); if (after) - data->id = g_signal_connect_after (device, name, callback, policy); + data->id = g_signal_connect_after (device, name, callback, self); else - data->id = g_signal_connect (device, name, callback, policy); + data->id = g_signal_connect (device, name, callback, self); data->device = device; priv->dev_ids = g_slist_prepend (priv->dev_ids, data); } @@ -1365,25 +1391,25 @@ _connect_device_signal (NMPolicy *policy, static void device_added (NMManager *manager, NMDevice *device, gpointer user_data) { - NMPolicy *policy = (NMPolicy *) user_data; + NMPolicy *self = (NMPolicy *) user_data; /* Connect state-changed with _after, so that the handler is invoked after other handlers. */ - _connect_device_signal (policy, device, NM_DEVICE_STATE_CHANGED, device_state_changed, TRUE); - _connect_device_signal (policy, device, NM_DEVICE_IP4_CONFIG_CHANGED, device_ip4_config_changed, FALSE); - _connect_device_signal (policy, device, NM_DEVICE_IP6_CONFIG_CHANGED, device_ip6_config_changed, FALSE); - _connect_device_signal (policy, device, "notify::" NM_DEVICE_AUTOCONNECT, device_autoconnect_changed, FALSE); - _connect_device_signal (policy, device, NM_DEVICE_RECHECK_AUTO_ACTIVATE, device_recheck_auto_activate, FALSE); + _connect_device_signal (self, device, NM_DEVICE_STATE_CHANGED, device_state_changed, TRUE); + _connect_device_signal (self, device, NM_DEVICE_IP4_CONFIG_CHANGED, device_ip4_config_changed, FALSE); + _connect_device_signal (self, device, NM_DEVICE_IP6_CONFIG_CHANGED, device_ip6_config_changed, FALSE); + _connect_device_signal (self, device, "notify::" NM_DEVICE_AUTOCONNECT, device_autoconnect_changed, FALSE); + _connect_device_signal (self, device, NM_DEVICE_RECHECK_AUTO_ACTIVATE, device_recheck_auto_activate, FALSE); } static void device_removed (NMManager *manager, NMDevice *device, gpointer user_data) { - NMPolicy *policy = (NMPolicy *) user_data; - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicy *self = (NMPolicy *) user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); GSList *iter; /* Clear any idle callbacks for this device */ - clear_pending_activate_check (policy, device); + clear_pending_activate_check (self, device); /* Clear any signal handlers for this device */ iter = priv->dev_ids; @@ -1407,9 +1433,9 @@ device_removed (NMManager *manager, NMDevice *device, gpointer user_data) /**************************************************************************/ static void -vpn_connection_activated (NMPolicy *policy, NMVpnConnection *vpn) +vpn_connection_activated (NMPolicy *self, NMVpnConnection *vpn) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); NMIP4Config *ip4_config; NMIP6Config *ip6_config; const char *ip_iface; @@ -1428,15 +1454,15 @@ vpn_connection_activated (NMPolicy *policy, NMVpnConnection *vpn) if (ip6_config) nm_dns_manager_add_ip6_config (priv->dns_manager, ip_iface, ip6_config, NM_DNS_IP_CONFIG_TYPE_VPN); - update_routing_and_dns (policy, TRUE); + update_routing_and_dns (self, TRUE); nm_dns_manager_end_updates (priv->dns_manager, __func__); } static void -vpn_connection_deactivated (NMPolicy *policy, NMVpnConnection *vpn) +vpn_connection_deactivated (NMPolicy *self, NMVpnConnection *vpn) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); NMIP4Config *ip4_config; NMIP6Config *ip6_config; @@ -1454,7 +1480,7 @@ vpn_connection_deactivated (NMPolicy *policy, NMVpnConnection *vpn) nm_dns_manager_remove_ip6_config (priv->dns_manager, ip6_config); } - update_routing_and_dns (policy, TRUE); + update_routing_and_dns (self, TRUE); nm_dns_manager_end_updates (priv->dns_manager, __func__); } @@ -1464,22 +1490,22 @@ vpn_connection_state_changed (NMVpnConnection *vpn, NMVpnConnectionState new_state, NMVpnConnectionState old_state, NMVpnConnectionStateReason reason, - NMPolicy *policy) + NMPolicy *self) { if (new_state == NM_VPN_CONNECTION_STATE_ACTIVATED) - vpn_connection_activated (policy, vpn); + vpn_connection_activated (self, vpn); else if (new_state >= NM_VPN_CONNECTION_STATE_FAILED) { /* Only clean up IP/DNS if the connection ever got past IP_CONFIG */ if (old_state >= NM_VPN_CONNECTION_STATE_IP_CONFIG_GET && old_state <= NM_VPN_CONNECTION_STATE_ACTIVATED) - vpn_connection_deactivated (policy, vpn); + vpn_connection_deactivated (self, vpn); } } static void -vpn_connection_retry_after_failure (NMVpnConnection *vpn, NMPolicy *policy) +vpn_connection_retry_after_failure (NMVpnConnection *vpn, NMPolicy *self) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); NMActiveConnection *ac = NM_ACTIVE_CONNECTION (vpn); NMSettingsConnection *connection = nm_active_connection_get_settings_connection (ac); GError *error = NULL; @@ -1491,9 +1517,9 @@ vpn_connection_retry_after_failure (NMVpnConnection *vpn, NMPolicy *policy) NULL, nm_active_connection_get_subject (ac), &error)) { - nm_log_warn (LOGD_DEVICE, "VPN '%s' reconnect failed: %s", - nm_settings_connection_get_id (connection), - error->message ? error->message : "unknown"); + _LOGW (LOGD_DEVICE, "VPN '%s' reconnect failed: %s", + nm_settings_connection_get_id (connection), + error->message ? error->message : "unknown"); g_clear_error (&error); } } @@ -1501,14 +1527,14 @@ vpn_connection_retry_after_failure (NMVpnConnection *vpn, NMPolicy *policy) static void active_connection_state_changed (NMActiveConnection *active, GParamSpec *pspec, - NMPolicy *policy) + NMPolicy *self) { NMActiveConnectionState state = nm_active_connection_get_state (active); if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) - process_secondaries (policy, active, TRUE); + process_secondaries (self, active, TRUE); else if (state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) - process_secondaries (policy, active, FALSE); + process_secondaries (self, active, FALSE); } static void @@ -1516,20 +1542,20 @@ active_connection_added (NMManager *manager, NMActiveConnection *active, gpointer user_data) { - NMPolicy *policy = NM_POLICY (user_data); + NMPolicy *self = NM_POLICY (user_data); if (NM_IS_VPN_CONNECTION (active)) { g_signal_connect (active, NM_VPN_CONNECTION_INTERNAL_STATE_CHANGED, G_CALLBACK (vpn_connection_state_changed), - policy); + self); g_signal_connect (active, NM_VPN_CONNECTION_INTERNAL_RETRY_AFTER_FAILURE, G_CALLBACK (vpn_connection_retry_after_failure), - policy); + self); } g_signal_connect (active, "notify::" NM_ACTIVE_CONNECTION_STATE, G_CALLBACK (active_connection_state_changed), - policy); + self); } static void @@ -1537,29 +1563,29 @@ active_connection_removed (NMManager *manager, NMActiveConnection *active, gpointer user_data) { - NMPolicy *policy = NM_POLICY (user_data); + NMPolicy *self = NM_POLICY (user_data); g_signal_handlers_disconnect_by_func (active, vpn_connection_state_changed, - policy); + self); g_signal_handlers_disconnect_by_func (active, vpn_connection_retry_after_failure, - policy); + self); g_signal_handlers_disconnect_by_func (active, active_connection_state_changed, - policy); + self); } /**************************************************************************/ static void -schedule_activate_all (NMPolicy *policy) +schedule_activate_all (NMPolicy *self) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); const GSList *iter; for (iter = nm_manager_get_devices (priv->manager); iter; iter = g_slist_next (iter)) - schedule_activate_check (policy, NM_DEVICE (iter->data)); + schedule_activate_check (self, NM_DEVICE (iter->data)); } static void @@ -1567,17 +1593,17 @@ connection_added (NMSettings *settings, NMSettingsConnection *connection, gpointer user_data) { - NMPolicy *policy = NM_POLICY (user_data); + NMPolicy *self = NM_POLICY (user_data); - schedule_activate_all (policy); + schedule_activate_all (self); } static void firewall_started (NMFirewallManager *manager, gpointer user_data) { - NMPolicy *policy = (NMPolicy *) user_data; - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicy *self = (NMPolicy *) user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); const GSList *iter; /* add interface of each device to correct zone */ @@ -1588,8 +1614,8 @@ firewall_started (NMFirewallManager *manager, static void dns_config_changed (NMDnsManager *dns_manager, gpointer user_data) { - NMPolicy *policy = (NMPolicy *) user_data; - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicy *self = (NMPolicy *) user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); /* Restart a thread for reverse-DNS lookup after we are signalled that * DNS changed. Because the result from a previous run may not be right @@ -1606,15 +1632,15 @@ dns_config_changed (NMDnsManager *dns_manager, gpointer user_data) if (priv->lookup_addr) { char *str = NULL; - nm_log_dbg (LOGD_DNS, "restarting reverse-lookup thread for address %s", - (str = g_inet_address_to_string (priv->lookup_addr))); + _LOGD (LOGD_DNS, "restarting reverse-lookup thread for address %s", + (str = g_inet_address_to_string (priv->lookup_addr))); g_free (str); priv->lookup_cancellable = g_cancellable_new (); g_resolver_lookup_by_address_async (priv->resolver, priv->lookup_addr, priv->lookup_cancellable, - lookup_callback, policy); + lookup_callback, self); } } @@ -1631,8 +1657,8 @@ connection_updated_by_user (NMSettings *settings, NMSettingsConnection *connection, gpointer user_data) { - NMPolicy *policy = (NMPolicy *) user_data; - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicy *self = (NMPolicy *) user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); const GSList *iter; NMDevice *device = NULL; @@ -1670,10 +1696,10 @@ _deactivate_if_active (NMManager *manager, NMSettingsConnection *connection) nm_exported_object_get_path (NM_EXPORTED_OBJECT (ac)), NM_DEVICE_STATE_REASON_CONNECTION_REMOVED, &error)) { - nm_log_warn (LOGD_DEVICE, "Connection '%s' disappeared, but error deactivating it: (%d) %s", - nm_settings_connection_get_id (connection), - error ? error->code : -1, - error ? error->message : "(unknown)"); + _LOGW (LOGD_DEVICE, "connection '%s' disappeared, but error deactivating it: (%d) %s", + nm_settings_connection_get_id (connection), + error ? error->code : -1, + error ? error->message : "(unknown)"); g_clear_error (&error); } } @@ -1685,8 +1711,8 @@ connection_removed (NMSettings *settings, NMSettingsConnection *connection, gpointer user_data) { - NMPolicy *policy = user_data; - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicy *self = user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); _deactivate_if_active (priv->manager, connection); } @@ -1696,11 +1722,11 @@ connection_visibility_changed (NMSettings *settings, NMSettingsConnection *connection, gpointer user_data) { - NMPolicy *policy = user_data; - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicy *self = user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); if (nm_settings_connection_is_visible (connection)) - schedule_activate_all (policy); + schedule_activate_all (self); else _deactivate_if_active (priv->manager, connection); } @@ -1710,52 +1736,125 @@ secret_agent_registered (NMSettings *settings, NMSecretAgent *agent, gpointer user_data) { - NMPolicy *policy = NM_POLICY (user_data); + NMPolicy *self = NM_POLICY (user_data); /* The registered secret agent may provide some missing secrets. Thus we * reset retries count here and schedule activation, so that the * connections failed due to missing secrets may re-try auto-connection. */ - reset_autoconnect_for_failed_secrets (policy); - schedule_activate_all (policy); + reset_autoconnect_for_failed_secrets (self); + schedule_activate_all (self); } +NMDevice * +nm_policy_get_default_ip4_device (NMPolicy *self) +{ + return NM_POLICY_GET_PRIVATE (self)->default_device4; +} + +NMDevice * +nm_policy_get_default_ip6_device (NMPolicy *self) +{ + return NM_POLICY_GET_PRIVATE (self)->default_device6; +} + +NMDevice * +nm_policy_get_activating_ip4_device (NMPolicy *self) +{ + return NM_POLICY_GET_PRIVATE (self)->activating_device4; +} + +NMDevice * +nm_policy_get_activating_ip6_device (NMPolicy *self) +{ + return NM_POLICY_GET_PRIVATE (self)->activating_device6; +} + +/*****************************************************************************/ + static void -_connect_manager_signal (NMPolicy *policy, const char *name, gpointer callback) +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicy *self = NM_POLICY (object); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); + + switch (prop_id) { + case PROP_DEFAULT_IP4_DEVICE: + g_value_set_object (value, priv->default_device4); + break; + case PROP_DEFAULT_IP6_DEVICE: + g_value_set_object (value, priv->default_device6); + break; + case PROP_ACTIVATING_IP4_DEVICE: + g_value_set_object (value, priv->activating_device4); + break; + case PROP_ACTIVATING_IP6_DEVICE: + g_value_set_object (value, priv->activating_device6); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMPolicy *self = NM_POLICY (object); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); + + switch (prop_id) { + case PROP_MANAGER: + /* construct-only */ + priv->manager = g_value_get_object (value); + g_return_if_fail (NM_IS_MANAGER (priv->manager)); + break; + case PROP_SETTINGS: + /* construct-only */ + priv->settings = g_value_dup_object (value); + g_return_if_fail (NM_IS_SETTINGS (priv->settings)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +_connect_manager_signal (NMPolicy *self, const char *name, gpointer callback) +{ + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); gulong id; - id = g_signal_connect (priv->manager, name, callback, policy); + id = g_signal_connect (priv->manager, name, callback, self); priv->manager_ids = g_slist_prepend (priv->manager_ids, (gpointer) id); } static void -_connect_settings_signal (NMPolicy *policy, const char *name, gpointer callback) +_connect_settings_signal (NMPolicy *self, const char *name, gpointer callback) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); gulong id; - id = g_signal_connect (priv->settings, name, callback, policy); + id = g_signal_connect (priv->settings, name, callback, self); priv->settings_ids = g_slist_prepend (priv->settings_ids, (gpointer) id); } -NMPolicy * -nm_policy_new (NMManager *manager, NMSettings *settings) +static void +nm_policy_init (NMPolicy *self) { - NMPolicy *policy; - NMPolicyPrivate *priv; - static gboolean initialized = FALSE; - char hostname[HOST_NAME_MAX + 2]; - - g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); - g_return_val_if_fail (initialized == FALSE, NULL); +} - policy = g_object_new (NM_TYPE_POLICY, NULL); - priv = NM_POLICY_GET_PRIVATE (policy); - priv->manager = manager; - priv->settings = g_object_ref (settings); - priv->update_state_id = 0; +static void +constructed (GObject *object) +{ + NMPolicy *self = NM_POLICY (object); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); + char hostname[HOST_NAME_MAX + 2]; /* Grab hostname on startup and use that if nothing provides one */ memset (hostname, 0, sizeof (hostname)); @@ -1768,103 +1867,56 @@ nm_policy_new (NMManager *manager, NMSettings *settings) priv->firewall_manager = g_object_ref (nm_firewall_manager_get ()); priv->fw_started_id = g_signal_connect (priv->firewall_manager, "started", - G_CALLBACK (firewall_started), policy); + G_CALLBACK (firewall_started), self); priv->dns_manager = g_object_ref (nm_dns_manager_get ()); nm_dns_manager_set_initial_hostname (priv->dns_manager, priv->orig_hostname); priv->config_changed_id = g_signal_connect (priv->dns_manager, "config-changed", - G_CALLBACK (dns_config_changed), policy); + G_CALLBACK (dns_config_changed), self); priv->resolver = g_resolver_get_default (); - _connect_manager_signal (policy, NM_MANAGER_STATE_CHANGED, global_state_changed); - _connect_manager_signal (policy, "notify::" NM_MANAGER_HOSTNAME, hostname_changed); - _connect_manager_signal (policy, "notify::" NM_MANAGER_SLEEPING, sleeping_changed); - _connect_manager_signal (policy, "notify::" NM_MANAGER_NETWORKING_ENABLED, sleeping_changed); - _connect_manager_signal (policy, "internal-device-added", device_added); - _connect_manager_signal (policy, "internal-device-removed", device_removed); - _connect_manager_signal (policy, NM_MANAGER_ACTIVE_CONNECTION_ADDED, active_connection_added); - _connect_manager_signal (policy, NM_MANAGER_ACTIVE_CONNECTION_REMOVED, active_connection_removed); - - _connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTION_ADDED, connection_added); - _connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED, connection_updated); - _connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED_BY_USER, connection_updated_by_user); - _connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTION_REMOVED, connection_removed); - _connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTION_VISIBILITY_CHANGED, + _connect_manager_signal (self, NM_MANAGER_STATE_CHANGED, global_state_changed); + _connect_manager_signal (self, "notify::" NM_MANAGER_HOSTNAME, hostname_changed); + _connect_manager_signal (self, "notify::" NM_MANAGER_SLEEPING, sleeping_changed); + _connect_manager_signal (self, "notify::" NM_MANAGER_NETWORKING_ENABLED, sleeping_changed); + _connect_manager_signal (self, "internal-device-added", device_added); + _connect_manager_signal (self, "internal-device-removed", device_removed); + _connect_manager_signal (self, NM_MANAGER_ACTIVE_CONNECTION_ADDED, active_connection_added); + _connect_manager_signal (self, NM_MANAGER_ACTIVE_CONNECTION_REMOVED, active_connection_removed); + + _connect_settings_signal (self, NM_SETTINGS_SIGNAL_CONNECTION_ADDED, connection_added); + _connect_settings_signal (self, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED, connection_updated); + _connect_settings_signal (self, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED_BY_USER, connection_updated_by_user); + _connect_settings_signal (self, NM_SETTINGS_SIGNAL_CONNECTION_REMOVED, connection_removed); + _connect_settings_signal (self, NM_SETTINGS_SIGNAL_CONNECTION_VISIBILITY_CHANGED, connection_visibility_changed); - _connect_settings_signal (policy, NM_SETTINGS_SIGNAL_AGENT_REGISTERED, secret_agent_registered); + _connect_settings_signal (self, NM_SETTINGS_SIGNAL_AGENT_REGISTERED, secret_agent_registered); - initialized = TRUE; - return policy; + G_OBJECT_CLASS (nm_policy_parent_class)->constructed (object); } -NMDevice * -nm_policy_get_default_ip4_device (NMPolicy *policy) -{ - return NM_POLICY_GET_PRIVATE (policy)->default_device4; -} - -NMDevice * -nm_policy_get_default_ip6_device (NMPolicy *policy) -{ - return NM_POLICY_GET_PRIVATE (policy)->default_device6; -} - -NMDevice * -nm_policy_get_activating_ip4_device (NMPolicy *policy) -{ - return NM_POLICY_GET_PRIVATE (policy)->activating_device4; -} - -NMDevice * -nm_policy_get_activating_ip6_device (NMPolicy *policy) -{ - return NM_POLICY_GET_PRIVATE (policy)->activating_device6; -} - -static void -nm_policy_init (NMPolicy *policy) -{ -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) +NMPolicy * +nm_policy_new (NMManager *manager, NMSettings *settings) { - NMPolicy *policy = NM_POLICY (object); - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); + g_return_val_if_fail (NM_IS_SETTINGS (settings), NULL); - switch (prop_id) { - case PROP_DEFAULT_IP4_DEVICE: - g_value_set_object (value, priv->default_device4); - break; - case PROP_DEFAULT_IP6_DEVICE: - g_value_set_object (value, priv->default_device6); - break; - case PROP_ACTIVATING_IP4_DEVICE: - g_value_set_object (value, priv->activating_device4); - break; - case PROP_ACTIVATING_IP6_DEVICE: - g_value_set_object (value, priv->activating_device6); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } + return g_object_new (NM_TYPE_POLICY, + NM_POLICY_MANAGER, manager, + NM_POLICY_SETTINGS, settings, + NULL); } static void dispose (GObject *object) { - NMPolicy *policy = NM_POLICY (object); - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicy *self = NM_POLICY (object); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); const GSList *connections, *iter; - /* Tell any existing hostname lookup thread to die. */ - if (priv->lookup_cancellable) { - g_cancellable_cancel (priv->lookup_cancellable); - g_clear_object (&priv->lookup_cancellable); - } + nm_clear_g_cancellable (&priv->lookup_cancellable); + g_clear_object (&priv->lookup_addr); g_clear_object (&priv->resolver); @@ -1876,13 +1928,12 @@ dispose (GObject *object) if (priv->firewall_manager) { g_assert (priv->fw_started_id); - g_signal_handler_disconnect (priv->firewall_manager, priv->fw_started_id); - priv->fw_started_id = 0; + nm_clear_g_signal_handler (priv->firewall_manager, &priv->fw_started_id); g_clear_object (&priv->firewall_manager); } if (priv->dns_manager) { - g_signal_handler_disconnect (priv->dns_manager, priv->config_changed_id); + nm_clear_g_signal_handler (priv->dns_manager, &priv->config_changed_id); g_clear_object (&priv->dns_manager); } @@ -1916,6 +1967,8 @@ dispose (GObject *object) g_clear_object (&priv->settings); + nm_assert (NM_IS_MANAGER (priv->manager)); + G_OBJECT_CLASS (nm_policy_parent_class)->dispose (object); } @@ -1927,30 +1980,41 @@ nm_policy_class_init (NMPolicyClass *policy_class) g_type_class_add_private (policy_class, sizeof (NMPolicyPrivate)); object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->constructed = constructed; object_class->dispose = dispose; - g_object_class_install_property - (object_class, PROP_DEFAULT_IP4_DEVICE, - g_param_spec_object (NM_POLICY_DEFAULT_IP4_DEVICE, "", "", - NM_TYPE_DEVICE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - g_object_class_install_property - (object_class, PROP_DEFAULT_IP6_DEVICE, - g_param_spec_object (NM_POLICY_DEFAULT_IP6_DEVICE, "", "", - NM_TYPE_DEVICE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - g_object_class_install_property - (object_class, PROP_ACTIVATING_IP4_DEVICE, - g_param_spec_object (NM_POLICY_ACTIVATING_IP4_DEVICE, "", "", - NM_TYPE_DEVICE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - g_object_class_install_property - (object_class, PROP_ACTIVATING_IP6_DEVICE, - g_param_spec_object (NM_POLICY_ACTIVATING_IP6_DEVICE, "", "", - NM_TYPE_DEVICE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_MANAGER] = + g_param_spec_object (NM_POLICY_MANAGER, "", "", + NM_TYPE_MANAGER, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_SETTINGS] = + g_param_spec_object (NM_POLICY_SETTINGS, "", "", + NM_TYPE_SETTINGS, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_DEFAULT_IP4_DEVICE] = + g_param_spec_object (NM_POLICY_DEFAULT_IP4_DEVICE, "", "", + NM_TYPE_DEVICE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_DEFAULT_IP6_DEVICE] = + g_param_spec_object (NM_POLICY_DEFAULT_IP6_DEVICE, "", "", + NM_TYPE_DEVICE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_ACTIVATING_IP4_DEVICE] = + g_param_spec_object (NM_POLICY_ACTIVATING_IP4_DEVICE, "", "", + NM_TYPE_DEVICE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_ACTIVATING_IP6_DEVICE] = + g_param_spec_object (NM_POLICY_ACTIVATING_IP6_DEVICE, "", "", + NM_TYPE_DEVICE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); } diff --git a/src/nm-policy.h b/src/nm-policy.h index 7824f3ea..4d504cdd 100644 --- a/src/nm-policy.h +++ b/src/nm-policy.h @@ -31,8 +31,10 @@ #define NM_IS_POLICY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_POLICY)) #define NM_POLICY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_POLICY, NMPolicyClass)) -#define NM_POLICY_DEFAULT_IP4_DEVICE "default-ip4-device" -#define NM_POLICY_DEFAULT_IP6_DEVICE "default-ip6-device" +#define NM_POLICY_MANAGER "manager" +#define NM_POLICY_SETTINGS "settings" +#define NM_POLICY_DEFAULT_IP4_DEVICE "default-ip4-device" +#define NM_POLICY_DEFAULT_IP6_DEVICE "default-ip6-device" #define NM_POLICY_ACTIVATING_IP4_DEVICE "activating-ip4-device" #define NM_POLICY_ACTIVATING_IP6_DEVICE "activating-ip6-device" diff --git a/src/nm-route-manager.c b/src/nm-route-manager.c index 84811d5a..3cf24118 100644 --- a/src/nm-route-manager.c +++ b/src/nm-route-manager.c @@ -73,6 +73,10 @@ typedef struct { G_DEFINE_TYPE (NMRouteManager, nm_route_manager, G_TYPE_OBJECT); +NM_GOBJECT_PROPERTIES_DEFINE_BASE ( + PROP_PLATFORM, +); + NM_DEFINE_SINGLETON_GETTER (NMRouteManager, nm_route_manager_get, NM_TYPE_ROUTE_MANAGER); /*********************************************************************************************/ @@ -1139,11 +1143,30 @@ static const VTableIP vtable_v6 = { /*********************************************************************************************/ static void -nm_route_manager_init (NMRouteManager *self) +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) { + NMRouteManager *self = NM_ROUTE_MANAGER (object); NMRouteManagerPrivate *priv = NM_ROUTE_MANAGER_GET_PRIVATE (self); - priv->platform = g_object_ref (NM_PLATFORM_GET); + switch (prop_id) { + case PROP_PLATFORM: + /* construct-only */ + priv->platform = g_value_get_object (value) ? : NM_PLATFORM_GET; + if (!priv->platform) + g_return_if_reached (); + g_object_ref (priv->platform); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_route_manager_init (NMRouteManager *self) +{ + NMRouteManagerPrivate *priv = NM_ROUTE_MANAGER_GET_PRIVATE (self); priv->ip4_routes.entries = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP4Route)); priv->ip6_routes.entries = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP6Route)); @@ -1159,6 +1182,14 @@ nm_route_manager_init (NMRouteManager *self) (GDestroyNotify) _ip4_device_routes_purge_entry_free); } +NMRouteManager * +nm_route_manager_new (NMPlatform *platform) +{ + return g_object_new (NM_TYPE_ROUTE_MANAGER, + NM_ROUTE_MANAGER_PLATFORM, platform, + NULL); +} + static void dispose (GObject *object) { @@ -1168,8 +1199,6 @@ dispose (GObject *object) g_hash_table_remove_all (priv->ip4_device_routes.entries); _ip4_device_routes_cancel (self); - g_clear_object (&priv->platform); - G_OBJECT_CLASS (nm_route_manager_parent_class)->dispose (object); } @@ -1189,6 +1218,8 @@ finalize (GObject *object) g_hash_table_unref (priv->ip4_device_routes.entries); + g_clear_object (&priv->platform); + G_OBJECT_CLASS (nm_route_manager_parent_class)->finalize (object); } @@ -1200,6 +1231,15 @@ nm_route_manager_class_init (NMRouteManagerClass *klass) g_type_class_add_private (klass, sizeof (NMRouteManagerPrivate)); /* virtual methods */ + object_class->set_property = set_property; object_class->dispose = dispose; object_class->finalize = finalize; + + obj_properties[PROP_PLATFORM] = + g_param_spec_object (NM_ROUTE_MANAGER_PLATFORM, "", "", + NM_TYPE_PLATFORM, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); } diff --git a/src/nm-route-manager.h b/src/nm-route-manager.h index 9a08496f..1f4b8174 100644 --- a/src/nm-route-manager.h +++ b/src/nm-route-manager.h @@ -31,6 +31,8 @@ #define NM_IS_ROUTE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_ROUTE_MANAGER)) #define NM_ROUTE_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_ROUTE_MANAGER, NMRouteManagerClass)) +#define NM_ROUTE_MANAGER_PLATFORM "platform" + struct _NMRouteManager { GObject parent; }; @@ -48,5 +50,6 @@ gboolean nm_route_manager_route_flush (NMRouteManager *self, int ifindex); void nm_route_manager_ip4_route_register_device_route_purge_list (NMRouteManager *self, GArray *device_route_purge_list); NMRouteManager *nm_route_manager_get (void); +NMRouteManager *nm_route_manager_new (NMPlatform *platform); #endif /* NM_ROUTE_MANAGER_H */ diff --git a/src/nm-session-monitor.c b/src/nm-session-monitor.c index d8b046e6..46709427 100644 --- a/src/nm-session-monitor.c +++ b/src/nm-session-monitor.c @@ -80,7 +80,7 @@ static guint signals[LAST_SIGNAL] = { 0 }; #ifdef SESSION_TRACKING_SYSTEMD static gboolean -sd_session_exists (NMSessionMonitor *monitor, uid_t uid, gboolean active) +st_sd_session_exists (NMSessionMonitor *monitor, uid_t uid, gboolean active) { int status; @@ -97,7 +97,7 @@ sd_session_exists (NMSessionMonitor *monitor, uid_t uid, gboolean active) } static gboolean -sd_changed (GIOChannel *stream, GIOCondition condition, gpointer user_data) +st_sd_changed (GIOChannel *stream, GIOCondition condition, gpointer user_data) { NMSessionMonitor *monitor = user_data; @@ -109,7 +109,7 @@ sd_changed (GIOChannel *stream, GIOCondition condition, gpointer user_data) } static void -sd_init (NMSessionMonitor *monitor) +st_sd_init (NMSessionMonitor *monitor) { int status; GIOChannel *stream; @@ -123,13 +123,13 @@ sd_init (NMSessionMonitor *monitor) } stream = g_io_channel_unix_new (sd_login_monitor_get_fd (monitor->sd.monitor)); - monitor->sd.watch = g_io_add_watch (stream, G_IO_IN, sd_changed, monitor); + monitor->sd.watch = g_io_add_watch (stream, G_IO_IN, st_sd_changed, monitor); g_io_channel_unref (stream); } static void -sd_finalize (NMSessionMonitor *monitor) +st_sd_finalize (NMSessionMonitor *monitor) { g_clear_pointer (&monitor->sd.monitor, sd_login_monitor_unref); g_source_remove (monitor->sd.watch); @@ -383,7 +383,7 @@ nm_session_monitor_session_exists (NMSessionMonitor *self, g_return_val_if_fail (NM_IS_SESSION_MONITOR (self), FALSE); #ifdef SESSION_TRACKING_SYSTEMD - if (sd_session_exists (self, uid, active)) + if (st_sd_session_exists (self, uid, active)) return TRUE; #endif @@ -401,7 +401,7 @@ static void nm_session_monitor_init (NMSessionMonitor *monitor) { #ifdef SESSION_TRACKING_SYSTEMD - sd_init (monitor); + st_sd_init (monitor); #endif #ifdef SESSION_TRACKING_CONSOLEKIT @@ -413,7 +413,7 @@ static void nm_session_monitor_finalize (GObject *object) { #ifdef SESSION_TRACKING_SYSTEMD - sd_finalize (NM_SESSION_MONITOR (object)); + st_sd_finalize (NM_SESSION_MONITOR (object)); #endif #ifdef SESSION_TRACKING_CONSOLEKIT diff --git a/src/nm-types.h b/src/nm-types.h index 0fda9216..997723e6 100644 --- a/src/nm-types.h +++ b/src/nm-types.h @@ -74,12 +74,13 @@ typedef enum { } NMIPConfigSource; /* platform */ +typedef struct _NMPlatform NMPlatform; typedef struct _NMPlatformIP4Address NMPlatformIP4Address; typedef struct _NMPlatformIP4Route NMPlatformIP4Route; typedef struct _NMPlatformIP6Address NMPlatformIP6Address; typedef struct _NMPlatformIP6Route NMPlatformIP6Route; typedef struct _NMPlatformLink NMPlatformLink; - +typedef struct _NMPNetns NMPNetns; typedef struct _NMPObject NMPObject; typedef enum { diff --git a/src/org.freedesktop.NetworkManager.conf b/src/org.freedesktop.NetworkManager.conf index 801d9a7d..dd630e19 100644 --- a/src/org.freedesktop.NetworkManager.conf +++ b/src/org.freedesktop.NetworkManager.conf @@ -11,7 +11,7 @@ <allow send_interface="org.freedesktop.NetworkManager.SecretAgent"/> <!-- These are there because some broken policies do - <allow send_interface="..." /> (see dbus-daemon(8) for details). + <deny send_interface="..." /> (see dbus-daemon(8) for details). This seems to override that for the known VPN plugins. --> <allow send_destination="org.freedesktop.NetworkManager.openconnect"/> @@ -113,13 +113,20 @@ to the agents themselves. --> <allow send_destination="org.freedesktop.NetworkManager" send_interface="org.freedesktop.NetworkManager.AgentManager"/> - <deny send_interface="org.freedesktop.NetworkManager.SecretAgent"/> <!-- Root-only functions --> - <deny send_interface="org.freedesktop.NetworkManager" send_member="SetLogging"/> - <deny send_interface="org.freedesktop.NetworkManager" send_member="Sleep"/> - <deny send_interface="org.freedesktop.NetworkManager.Settings" send_member="LoadConnections"/> - <deny send_interface="org.freedesktop.NetworkManager.Settings" send_member="ReloadConnections"/> + <deny send_destination="org.freedesktop.NetworkManager" + send_interface="org.freedesktop.NetworkManager" + send_member="SetLogging"/> + <deny send_destination="org.freedesktop.NetworkManager" + send_interface="org.freedesktop.NetworkManager" + send_member="Sleep"/> + <deny send_destination="org.freedesktop.NetworkManager" + send_interface="org.freedesktop.NetworkManager.Settings" + send_member="LoadConnections"/> + <deny send_destination="org.freedesktop.NetworkManager" + send_interface="org.freedesktop.NetworkManager.Settings" + send_member="ReloadConnections"/> </policy> <limit name="max_replies_per_connection">1024</limit> diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c index 68b72b19..fdb11eac 100644 --- a/src/platform/nm-fake-platform.c +++ b/src/platform/nm-fake-platform.c @@ -890,6 +890,7 @@ ip4_address_add (NMPlatform *platform, in_addr_t peer_addr, guint32 lifetime, guint32 preferred, + guint32 flags, const char *label) { NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); @@ -905,6 +906,7 @@ ip4_address_add (NMPlatform *platform, address.timestamp = nm_utils_get_monotonic_timestamp_s (); address.lifetime = lifetime; address.preferred = preferred; + address.n_ifa_flags = flags; if (label) g_strlcpy (address.label, label, sizeof (address.label)); diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 196e75cb..e2ff1f61 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -50,6 +50,7 @@ #include "nm-core-utils.h" #include "nmp-object.h" +#include "nmp-netns.h" #include "nm-platform-utils.h" #include "wifi/wifi-utils.h" #include "wifi/wifi-utils-wext.h" @@ -221,6 +222,7 @@ static void do_request_all_no_delayed_actions (NMPlatform *platform, DelayedActi static void cache_pre_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMPCacheOpsType ops_type, gpointer user_data); static void cache_prune_candidates_prune (NMPlatform *platform); static gboolean event_handler_read_netlink (NMPlatform *platform, gboolean wait_for_acks); +static void _assert_netns_current (NMPlatform *platform); /*****************************************************************************/ @@ -647,6 +649,8 @@ _linktype_get_type (NMPlatform *platform, { guint i; + _assert_netns_current (platform); + if (completed_from_cache) { const NMPObject *obj; @@ -1673,11 +1677,9 @@ _new_from_nl_addr (struct nlmsghdr *nlh, gboolean id_only) obj->ip_address.source = NM_IP_CONFIG_SOURCE_KERNEL; - if (!is_v4) { - obj->ip6_address.n_ifa_flags = tb[IFA_FLAGS] - ? nla_get_u32 (tb[IFA_FLAGS]) - : ifa->ifa_flags; - } + obj->ip_address.n_ifa_flags = tb[IFA_FLAGS] + ? nla_get_u32 (tb[IFA_FLAGS]) + : ifa->ifa_flags; if (is_v4) { if (tb[IFA_LABEL]) { @@ -2225,7 +2227,7 @@ _nl_msg_new_address (int nlmsg_type, NLA_PUT (msg, IFA_CACHEINFO, sizeof(ca), &ca); } - if (flags & ~0xFF) { + if (flags & ~((guint32) 0xFF)) { /* only set the IFA_FLAGS attribute, if they actually contain additional * flags that are not already set to am.ifa_flags. * @@ -2412,6 +2414,7 @@ void nm_linux_platform_setup (void) { g_object_new (NM_TYPE_LINUX_PLATFORM, + NM_PLATFORM_NETNS_SUPPORT, FALSE, NM_PLATFORM_REGISTER_SINGLETON, TRUE, NULL); } @@ -2419,6 +2422,16 @@ nm_linux_platform_setup (void) /******************************************************************/ static void +_assert_netns_current (NMPlatform *platform) +{ +#if NM_MORE_ASSERTS + nm_assert (NM_IS_LINUX_PLATFORM (platform)); + + nm_assert (NM_IN_SET (nm_platform_netns_get (platform), NULL, nmp_netns_get_current ())); +#endif +} + +static void _log_dbg_sysctl_set_impl (NMPlatform *platform, const char *path, const char *value) { GError *error = NULL; @@ -2451,6 +2464,7 @@ _log_dbg_sysctl_set_impl (NMPlatform *platform, const char *path, const char *va static gboolean sysctl_set (NMPlatform *platform, const char *path, const char *value) { + nm_auto_pop_netns NMPNetns *netns = NULL; int fd, tries; gssize nwrote; gsize len; @@ -2466,6 +2480,9 @@ sysctl_set (NMPlatform *platform, const char *path, const char *value) /* Don't write to suspicious locations */ g_assert (!strstr (path, "/../")); + if (!nm_platform_netns_push (platform, &netns)) + return FALSE; + fd = open (path, O_WRONLY | O_TRUNC); if (fd == -1) { if (errno == ENOENT) { @@ -2580,6 +2597,7 @@ _log_dbg_sysctl_get_impl (NMPlatform *platform, const char *path, const char *co static char * sysctl_get (NMPlatform *platform, const char *path) { + nm_auto_pop_netns NMPNetns *netns = NULL; GError *error = NULL; char *contents; @@ -2589,6 +2607,9 @@ sysctl_get (NMPlatform *platform, const char *path) /* Don't write to suspicious locations */ g_assert (!strstr (path, "/../")); + if (!nm_platform_netns_push (platform, &netns)) + return NULL; + if (!g_file_get_contents (path, &contents, NULL, &error)) { /* We assume FAILED means EOPNOTSUP */ if ( g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT) @@ -2653,6 +2674,9 @@ do_emit_signal (NMPlatform *platform, const NMPObject *obj, NMPCacheOpsType cach nm_assert (!obj || cache_op == NMP_CACHE_OPS_REMOVED || obj == nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, obj)); nm_assert (!obj || cache_op != NMP_CACHE_OPS_REMOVED || obj != nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, obj)); + /* we raise the signals inside the namespace of the NMPlatform instance. */ + _assert_netns_current (platform); + switch (cache_op) { case NMP_CACHE_OPS_ADDED: if (!nmp_object_is_visible (obj)) @@ -3857,6 +3881,7 @@ do_change_link (NMPlatform *platform, int ifindex, struct nl_msg *nlmsg) { + nm_auto_pop_netns NMPNetns *netns = NULL; WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; int nle; char s_buf[256]; @@ -3864,6 +3889,9 @@ do_change_link (NMPlatform *platform, NMLogLevel log_level = LOGL_DEBUG; const char *log_result = "failure", *log_detail = ""; + if (!nm_platform_netns_push (platform, &netns)) + return NM_PLATFORM_ERROR_UNSPECIFIED; + retry: nle = _nl_send_auto_with_seq (platform, nlmsg, &seq_result); if (nle < 0) { @@ -3927,7 +3955,7 @@ link_add (NMPlatform *platform, * bond0 automatically. */ if (!g_file_test ("/sys/class/net/bonding_masters", G_FILE_TEST_EXISTS)) - nm_utils_modprobe (NULL, TRUE, "bonding", "max_bonds=0", NULL); + (void) nm_utils_modprobe (NULL, TRUE, "bonding", "max_bonds=0", NULL); } _LOGD ("link: add link '%s' of type '%s' (%d)", @@ -3994,7 +4022,7 @@ link_get_type_name (NMPlatform *platform, int ifindex) return nm_link_type_to_string (obj->link.type); } /* Link type not detected. Fallback to rtnl_link_get_type()/IFLA_INFO_KIND. */ - return str_if_set (obj->link.kind, "unknown"); + return obj->link.kind ?: "unknown"; } static gboolean @@ -4023,6 +4051,31 @@ link_refresh (NMPlatform *platform, int ifindex) return !!cache_lookup_link (platform, ifindex); } +static gboolean +link_set_netns (NMPlatform *platform, + int ifindex, + int netns_fd) +{ + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + + _LOGD ("link: move link %d to network namespace with fd %d", ifindex, netns_fd); + + nlmsg = _nl_msg_new_link (RTM_NEWLINK, + 0, + ifindex, + NULL, + 0, + 0); + if (!nlmsg) + return FALSE; + + NLA_PUT (nlmsg, IFLA_NET_NS_FD, 4, &netns_fd); + return do_change_link (platform, ifindex, nlmsg) == NM_PLATFORM_ERROR_SUCCESS; + +nla_put_failure: + g_return_val_if_reached (FALSE); +} + static NMPlatformError link_change_flags (NMPlatform *platform, int ifindex, @@ -4137,11 +4190,15 @@ link_set_user_ipv6ll_enabled (NMPlatform *platform, int ifindex, gboolean enable static gboolean link_supports_carrier_detect (NMPlatform *platform, int ifindex) { + nm_auto_pop_netns NMPNetns *netns = NULL; const char *name = nm_platform_link_get_name (platform, ifindex); if (!name) return FALSE; + if (!nm_platform_netns_push (platform, &netns)) + return FALSE; + /* We use netlink for the actual carrier detection, but netlink can't tell * us whether the device actually supports carrier detection in the first * place. We assume any device that does implements one of these two APIs. @@ -4152,6 +4209,7 @@ link_supports_carrier_detect (NMPlatform *platform, int ifindex) static gboolean link_supports_vlans (NMPlatform *platform, int ifindex) { + nm_auto_pop_netns NMPNetns *netns = NULL; const NMPObject *obj; obj = cache_lookup_link (platform, ifindex); @@ -4160,6 +4218,9 @@ link_supports_vlans (NMPlatform *platform, int ifindex) if (!obj || obj->link.arptype != ARPHRD_ETHER) return FALSE; + if (!nm_platform_netns_push (platform, &netns)) + return FALSE; + return nmp_utils_ethtool_supports_vlans (obj->link.name); } @@ -4198,6 +4259,11 @@ link_get_permanent_address (NMPlatform *platform, guint8 *buf, size_t *length) { + nm_auto_pop_netns NMPNetns *netns = NULL; + + if (!nm_platform_netns_push (platform, &netns)) + return FALSE; + return nmp_utils_ethtool_get_permanent_address (nm_platform_link_get_name (platform, ifindex), buf, length); } @@ -4234,7 +4300,7 @@ link_get_physical_port_id (NMPlatform *platform, int ifindex) if (!ifname) return NULL; - ifname = ASSERT_VALID_PATH_COMPONENT (ifname); + ifname = NM_ASSERT_VALID_PATH_COMPONENT (ifname); path = g_strdup_printf ("/sys/class/net/%s/phys_port_id", ifname); id = sysctl_get (platform, path); @@ -4254,7 +4320,7 @@ link_get_dev_id (NMPlatform *platform, int ifindex) if (!ifname) return 0; - ifname = ASSERT_VALID_PATH_COMPONENT (ifname); + ifname = NM_ASSERT_VALID_PATH_COMPONENT (ifname); path = g_strdup_printf ("/sys/class/net/%s/dev_id", ifname); id = sysctl_get (platform, path); @@ -4837,7 +4903,7 @@ tun_add (NMPlatform *platform, const char *name, gboolean tap, if (fd < 0) return FALSE; - strncpy (ifr.ifr_name, name, IFNAMSIZ); + nm_utils_ifname_cpy (ifr.ifr_name, name); ifr.ifr_flags = tap ? IFF_TAP : IFF_TUN; if (!pi) @@ -4930,7 +4996,7 @@ infiniband_partition_add (NMPlatform *platform, int parent, int p_key, const NMP ifname = g_strdup_printf ("%s.%04x", obj_parent->link.name, p_key); - path = g_strdup_printf ("/sys/class/net/%s/create_child", ASSERT_VALID_PATH_COMPONENT (obj_parent->link.name)); + path = g_strdup_printf ("/sys/class/net/%s/create_child", NM_ASSERT_VALID_PATH_COMPONENT (obj_parent->link.name)); id = g_strdup_printf ("0x%04x", p_key); if (!nm_platform_sysctl_set (platform, path, id)) return FALSE; @@ -4977,15 +5043,19 @@ wifi_get_wifi_data (NMPlatform *platform, int ifindex) return wifi_data; } +#define WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, retval) \ + nm_auto_pop_netns NMPNetns *netns = NULL; \ + WifiData *wifi_data; \ + if (!nm_platform_netns_push (platform, &netns)) \ + return retval; \ + wifi_data = wifi_get_wifi_data (platform, ifindex); \ + if (!wifi_data) \ + return retval; static gboolean wifi_get_capabilities (NMPlatform *platform, int ifindex, NMDeviceWifiCapabilities *caps) { - WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); - - if (!wifi_data) - return FALSE; - + WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, FALSE); if (caps) *caps = wifi_utils_get_caps (wifi_data); return TRUE; @@ -4994,90 +5064,64 @@ wifi_get_capabilities (NMPlatform *platform, int ifindex, NMDeviceWifiCapabiliti static gboolean wifi_get_bssid (NMPlatform *platform, int ifindex, guint8 *bssid) { - WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); - - if (!wifi_data) - return FALSE; + WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, FALSE); return wifi_utils_get_bssid (wifi_data, bssid); } static guint32 wifi_get_frequency (NMPlatform *platform, int ifindex) { - WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); - - if (!wifi_data) - return 0; + WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, 0); return wifi_utils_get_freq (wifi_data); } static gboolean wifi_get_quality (NMPlatform *platform, int ifindex) { - WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); - - if (!wifi_data) - return FALSE; + WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, FALSE); return wifi_utils_get_qual (wifi_data); } static guint32 wifi_get_rate (NMPlatform *platform, int ifindex) { - WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); - - if (!wifi_data) - return FALSE; + WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, FALSE); return wifi_utils_get_rate (wifi_data); } static NM80211Mode wifi_get_mode (NMPlatform *platform, int ifindex) { - WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); - - if (!wifi_data) - return NM_802_11_MODE_UNKNOWN; - + WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, NM_802_11_MODE_UNKNOWN); return wifi_utils_get_mode (wifi_data); } static void wifi_set_mode (NMPlatform *platform, int ifindex, NM80211Mode mode) { - WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); - - if (wifi_data) - wifi_utils_set_mode (wifi_data, mode); + WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, ); + wifi_utils_set_mode (wifi_data, mode); } static void wifi_set_powersave (NMPlatform *platform, int ifindex, guint32 powersave) { - WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); - - if (wifi_data) - wifi_utils_set_powersave (wifi_data, powersave); + WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, ); + wifi_utils_set_powersave (wifi_data, powersave); } static guint32 wifi_find_frequency (NMPlatform *platform, int ifindex, const guint32 *freqs) { - WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); - - if (!wifi_data) - return 0; - + WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, 0); return wifi_utils_find_freq (wifi_data, freqs); } static void wifi_indicate_addressing_running (NMPlatform *platform, int ifindex, gboolean running) { - WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); - - if (wifi_data) - wifi_utils_indicate_addressing_running (wifi_data, running); + WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, ); + wifi_utils_indicate_addressing_running (wifi_data, running); } /******************************************************************/ @@ -5085,33 +5129,21 @@ wifi_indicate_addressing_running (NMPlatform *platform, int ifindex, gboolean ru static guint32 mesh_get_channel (NMPlatform *platform, int ifindex) { - WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); - - if (!wifi_data) - return 0; - + WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, 0); return wifi_utils_get_mesh_channel (wifi_data); } static gboolean mesh_set_channel (NMPlatform *platform, int ifindex, guint32 channel) { - WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); - - if (!wifi_data) - return FALSE; - + WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, FALSE); return wifi_utils_set_mesh_channel (wifi_data, channel); } static gboolean mesh_set_ssid (NMPlatform *platform, int ifindex, const guint8 *ssid, gsize len) { - WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); - - if (!wifi_data) - return FALSE; - + WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, FALSE); return wifi_utils_set_mesh_ssid (wifi_data, ssid, len); } @@ -5120,8 +5152,12 @@ mesh_set_ssid (NMPlatform *platform, int ifindex, const guint8 *ssid, gsize len) static gboolean link_get_wake_on_lan (NMPlatform *platform, int ifindex) { + nm_auto_pop_netns NMPNetns *netns = NULL; NMLinkType type = nm_platform_link_get_type (platform, ifindex); + if (!nm_platform_netns_push (platform, &netns)) + return FALSE; + if (type == NM_LINK_TYPE_ETHERNET) return nmp_utils_ethtool_get_wake_on_lan (nm_platform_link_get_name (platform, ifindex)); else if (type == NM_LINK_TYPE_WIFI) { @@ -5142,6 +5178,11 @@ link_get_driver_info (NMPlatform *platform, char **out_driver_version, char **out_fw_version) { + nm_auto_pop_netns NMPNetns *netns = NULL; + + if (!nm_platform_netns_push (platform, &netns)) + return FALSE; + return nmp_utils_ethtool_get_driver_info (nm_platform_link_get_name (platform, ifindex), out_driver_name, out_driver_version, @@ -5184,6 +5225,7 @@ ip4_address_add (NMPlatform *platform, in_addr_t peer_addr, guint32 lifetime, guint32 preferred, + guint32 flags, const char *label) { NMPObject obj_id; @@ -5196,8 +5238,8 @@ ip4_address_add (NMPlatform *platform, &addr, plen, &peer_addr, - 0, - nmp_utils_ip4_address_is_link_local (addr) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE, + flags, + nm_utils_ip4_address_is_link_local (addr) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE, lifetime, preferred, label); @@ -5722,6 +5764,7 @@ out: static gboolean event_handler_read_netlink (NMPlatform *platform, gboolean wait_for_acks) { + nm_auto_pop_netns NMPNetns *netns = NULL; NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); int r, nle; struct pollfd pfd; @@ -5734,6 +5777,9 @@ event_handler_read_netlink (NMPlatform *platform, gboolean wait_for_acks) gint64 timeout_abs_ns; } data_next; + if (!nm_platform_netns_push (platform, &netns)) + return FALSE; + while (TRUE) { while (TRUE) { @@ -5838,7 +5884,14 @@ cache_update_link_udev (NMPlatform *platform, int ifindex, GUdevDevice *udev_dev NMPCacheOpsType cache_op; cache_op = nmp_cache_update_link_udev (priv->cache, ifindex, udev_device, &obj_cache, &was_visible, cache_pre_hook, platform); - do_emit_signal (platform, obj_cache, cache_op, was_visible); + + if (cache_op != NMP_CACHE_OPS_UNCHANGED) { + nm_auto_pop_netns NMPNetns *netns = NULL; + + if (!nm_platform_netns_push (platform, &netns)) + return; + do_emit_signal (platform, obj_cache, cache_op, was_visible); + } } static void @@ -5854,22 +5907,22 @@ udev_device_added (NMPlatform *platform, return; } - if (g_udev_device_get_property (udev_device, "IFINDEX")) - ifindex = g_udev_device_get_property_as_int (udev_device, "IFINDEX"); - else { - _LOGW ("(%s): udev-add: failed to get device's ifindex", ifname); + if (!g_udev_device_get_property (udev_device, "IFINDEX")) { + _LOGW ("udev-add[%s]failed to get device's ifindex", ifname); return; } + ifindex = g_udev_device_get_property_as_int (udev_device, "IFINDEX"); if (ifindex <= 0) { - _LOGW ("(%s): udev-add: retrieved invalid IFINDEX=%d", ifname, ifindex); + _LOGW ("udev-add[%s]: retrieved invalid IFINDEX=%d", ifname, ifindex); return; } if (!g_udev_device_get_sysfs_path (udev_device)) { - _LOGD ("(%s): udev-add: couldn't determine device path; ignoring...", ifname); + _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); } @@ -5909,6 +5962,7 @@ handle_udev_event (GUdevClient *client, GUdevDevice *udev_device, gpointer user_data) { + nm_auto_pop_netns NMPNetns *netns = NULL; NMPlatform *platform = NM_PLATFORM (user_data); const char *subsys; const char *ifindex; @@ -5916,6 +5970,9 @@ handle_udev_event (GUdevClient *client, g_return_if_fail (action != NULL); + 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")); @@ -5938,15 +5995,22 @@ static void nm_linux_platform_init (NMLinuxPlatform *self) { NMLinuxPlatformPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_LINUX_PLATFORM, NMLinuxPlatformPrivate); + gboolean use_udev; + + use_udev = nmp_netns_is_initial () + && access ("/sys", W_OK) == 0; self->priv = priv; priv->nlh_seq_next = 1; - priv->cache = nmp_cache_new (); + priv->cache = nmp_cache_new (use_udev); priv->delayed_action.list_master_connected = g_ptr_array_new (); priv->delayed_action.list_refresh_link = g_ptr_array_new (); 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 }); } static void @@ -5954,14 +6018,22 @@ constructed (GObject *_object) { NMPlatform *platform = NM_PLATFORM (_object); NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); - const char *udev_subsys[] = { "net", NULL }; int channel_flags; gboolean status; int nle; - GUdevEnumerator *enumerator; - GList *devices, *iter; - _LOGD ("create"); + nm_assert (!platform->_netns || platform->_netns == nmp_netns_get_current ()); + + _LOGD ("create (%s netns, %s, %s udev)", + !platform->_netns ? "ignore" : "use", + !platform->_netns && nmp_netns_is_initial () + ? "initial netns" + : (!nmp_netns_get_current () + ? "no netns support" + : nm_sprintf_bufa (100, "in netns[%p]%s", + nmp_netns_get_current (), + nmp_netns_get_current () == nmp_netns_get_initial () ? "/main" : "")), + nmp_cache_use_udev_get (priv->cache) ? "use" : "no"); priv->nlh = nl_socket_alloc (); g_assert (priv->nlh); @@ -5993,16 +6065,12 @@ constructed (GObject *_object) channel_flags = g_io_channel_get_flags (priv->event_channel); status = g_io_channel_set_flags (priv->event_channel, - channel_flags | G_IO_FLAG_NONBLOCK, NULL); + channel_flags | G_IO_FLAG_NONBLOCK, NULL); g_assert (status); priv->event_id = g_io_add_watch (priv->event_channel, (EVENT_CONDITIONS | ERROR_CONDITIONS | DISCONNECT_CONDITIONS), event_handler, platform); - /* Set up udev monitoring */ - priv->udev_client = g_udev_client_new (udev_subsys); - g_signal_connect (priv->udev_client, "uevent", G_CALLBACK (handle_udev_event), platform); - /* complete construction of the GObject instance before populating the cache. */ G_OBJECT_CLASS (nm_linux_platform_parent_class)->constructed (_object); @@ -6017,19 +6085,27 @@ constructed (GObject *_object) delayed_action_handle_all (platform, FALSE); - /* And read initial device list */ - enumerator = g_udev_enumerator_new (priv->udev_client); - g_udev_enumerator_add_match_subsystem (enumerator, "net"); + /* 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); + + /* And read initial device list */ + enumerator = g_udev_enumerator_new (priv->udev_client); + g_udev_enumerator_add_match_subsystem (enumerator, "net"); - g_udev_enumerator_add_match_is_initialized (enumerator); + g_udev_enumerator_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)); + 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)); + } + g_list_free (devices); + g_object_unref (enumerator); } - g_list_free (devices); - g_object_unref (enumerator); } static void @@ -6048,6 +6124,11 @@ 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); } @@ -6067,7 +6148,6 @@ nm_linux_platform_finalize (GObject *object) g_io_channel_unref (priv->event_channel); nl_socket_free (priv->nlh); - g_object_unref (priv->udev_client); g_hash_table_unref (priv->wifi_data); if (priv->sysctl_get_prev_values) { @@ -6109,6 +6189,8 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass) platform_class->link_refresh = link_refresh; + platform_class->link_set_netns = link_set_netns; + platform_class->link_set_up = link_set_up; platform_class->link_set_down = link_set_down; platform_class->link_set_arp = link_set_arp; diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c index 0f2656f2..d0c92a78 100644 --- a/src/platform/nm-platform-utils.c +++ b/src/platform/nm-platform-utils.c @@ -56,7 +56,7 @@ ethtool_get (const char *name, gpointer edata) nm_assert (strlen (name) < IFNAMSIZ); memset (&ifr, 0, sizeof (ifr)); - strcpy (ifr.ifr_name, name); + nm_utils_ifname_cpy (ifr.ifr_name, name); ifr.ifr_data = edata; fd = socket (PF_INET, SOCK_DGRAM, 0); @@ -344,7 +344,7 @@ nmp_utils_mii_supports_carrier_detect (const char *ifname) } memset (&ifr, 0, sizeof (struct ifreq)); - strncpy (ifr.ifr_name, ifname, IFNAMSIZ); + nm_utils_ifname_cpy (ifr.ifr_name, ifname); errno = 0; if (ioctl (fd, SIOCGMIIPHY, &ifr) < 0) { @@ -412,114 +412,18 @@ out: return g_intern_string (driver); } -/****************************************************************** - * utils - ******************************************************************/ - -#define IPV4LL_NETWORK (htonl (0xA9FE0000L)) -#define IPV4LL_NETMASK (htonl (0xFFFF0000L)) - -gboolean -nmp_utils_ip4_address_is_link_local (in_addr_t addr) -{ - return (addr & IPV4LL_NETMASK) == IPV4LL_NETWORK; -} - -/** - * Takes a pair @timestamp and @duration, and returns the remaining duration based - * on the new timestamp @now. - */ -guint32 -nmp_utils_lifetime_rebase_relative_time_on_now (guint32 timestamp, - guint32 duration, - guint32 now, - guint32 padding) -{ - gint64 t; - - if (duration == NM_PLATFORM_LIFETIME_PERMANENT) - return NM_PLATFORM_LIFETIME_PERMANENT; - - if (timestamp == 0) { - /* if the @timestamp is zero, assume it was just left unset and that the relative - * @duration starts counting from @now. This is convenient to construct an address - * and print it in nm_platform_ip4_address_to_string(). - * - * In general it does not make sense to set the @duration without anchoring at - * @timestamp because you don't know the absolute expiration time when looking - * at the address at a later moment. */ - timestamp = now; - } - - /* For timestamp > now, just accept it and calculate the expected(?) result. */ - t = (gint64) timestamp + (gint64) duration - (gint64) now; - - /* Optional padding to avoid potential races. */ - t += (gint64) padding; - - if (t <= 0) - return 0; - if (t >= NM_PLATFORM_LIFETIME_PERMANENT) - return NM_PLATFORM_LIFETIME_PERMANENT - 1; - return t; -} - -gboolean -nmp_utils_lifetime_get (guint32 timestamp, - guint32 lifetime, - guint32 preferred, - guint32 now, - guint32 padding, - guint32 *out_lifetime, - guint32 *out_preferred) -{ - guint32 t_lifetime, t_preferred; - - if (lifetime == 0) { - *out_lifetime = NM_PLATFORM_LIFETIME_PERMANENT; - *out_preferred = NM_PLATFORM_LIFETIME_PERMANENT; - - /* We treat lifetime==0 as permanent addresses to allow easy creation of such addresses - * (without requiring to set the lifetime fields to NM_PLATFORM_LIFETIME_PERMANENT). - * In that case we also expect that the other fields (timestamp and preferred) are left unset. */ - g_return_val_if_fail (timestamp == 0 && preferred == 0, TRUE); - } else { - if (!now) - now = nm_utils_get_monotonic_timestamp_s (); - t_lifetime = nmp_utils_lifetime_rebase_relative_time_on_now (timestamp, lifetime, now, padding); - if (!t_lifetime) { - *out_lifetime = 0; - *out_preferred = 0; - return FALSE; - } - t_preferred = nmp_utils_lifetime_rebase_relative_time_on_now (timestamp, preferred, now, padding); - - *out_lifetime = t_lifetime; - *out_preferred = MIN (t_preferred, t_lifetime); - - /* Assert that non-permanent addresses have a (positive) @timestamp. nmp_utils_lifetime_rebase_relative_time_on_now() - * treats addresses with timestamp 0 as *now*. Addresses passed to _address_get_lifetime() always - * should have a valid @timestamp, otherwise on every re-sync, their lifetime will be extended anew. - */ - g_return_val_if_fail ( timestamp != 0 - || ( lifetime == NM_PLATFORM_LIFETIME_PERMANENT - && preferred == NM_PLATFORM_LIFETIME_PERMANENT), TRUE); - g_return_val_if_fail (t_preferred <= t_lifetime, TRUE); - } - return TRUE; -} - gboolean nmp_utils_device_exists (const char *name) { #define SYS_CLASS_NET "/sys/class/net/" - char sysdir[NM_STRLEN (SYS_CLASS_NET) + IFNAMSIZ] = SYS_CLASS_NET; + char sysdir[NM_STRLEN (SYS_CLASS_NET) + IFNAMSIZ]; if ( !name || strlen (name) >= IFNAMSIZ || !nm_utils_is_valid_path_component (name)) g_return_val_if_reached (FALSE); - strcpy (&sysdir[NM_STRLEN (SYS_CLASS_NET)], name); + memcpy (sysdir, SYS_CLASS_NET, NM_STRLEN (SYS_CLASS_NET)); + nm_utils_ifname_cpy (&sysdir[NM_STRLEN (SYS_CLASS_NET)], name); return g_file_test (sysdir, G_FILE_TEST_EXISTS); } diff --git a/src/platform/nm-platform-utils.h b/src/platform/nm-platform-utils.h index a9d29c04..976bd8db 100644 --- a/src/platform/nm-platform-utils.h +++ b/src/platform/nm-platform-utils.h @@ -52,21 +52,6 @@ gboolean nmp_utils_mii_supports_carrier_detect (const char *ifname); const char *nmp_utils_udev_get_driver (GUdevDevice *device); -guint32 nmp_utils_lifetime_rebase_relative_time_on_now (guint32 timestamp, - guint32 duration, - guint32 now, - guint32 padding); - -gboolean nmp_utils_lifetime_get (guint32 timestamp, - guint32 lifetime, - guint32 preferred, - guint32 now, - guint32 padding, - guint32 *out_lifetime, - guint32 *out_preferred); - gboolean nmp_utils_device_exists (const char *name); -gboolean nmp_utils_ip4_address_is_link_local (in_addr_t addr); - #endif /* __NM_PLATFORM_UTILS_H__ */ diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index e3126442..d5ee48d4 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -41,6 +41,7 @@ #include "nm-enum-types.h" #include "nm-platform-utils.h" #include "nmp-object.h" +#include "nmp-netns.h" /*****************************************************************************/ @@ -48,8 +49,6 @@ const NMIPAddr nm_ip_addr_zero = NMIPAddrInit; /*****************************************************************************/ -#define ADDRESS_LIFETIME_PADDING 5 - G_STATIC_ASSERT (sizeof ( ((NMPlatformLink *) NULL)->addr.data ) == NM_UTILS_HWADDR_LEN_MAX); G_STATIC_ASSERT (G_STRUCT_OFFSET (NMPlatformIPAddress, address_ptr) == G_STRUCT_OFFSET (NMPlatformIP4Address, address)); G_STATIC_ASSERT (G_STRUCT_OFFSET (NMPlatformIPAddress, address_ptr) == G_STRUCT_OFFSET (NMPlatformIP6Address, address)); @@ -89,6 +88,7 @@ static guint signals[_NM_PLATFORM_SIGNAL_ID_LAST] = { 0 }; enum { PROP_0, + PROP_NETNS_SUPPORT, PROP_REGISTER_SINGLETON, LAST_PROP, }; @@ -666,6 +666,32 @@ nm_platform_link_delete (NMPlatform *self, int ifindex) } /** + * nm_platform_link_set_netns: + * @self: platform instance + * @ifindex: Interface index + * @netns_fd: the file descriptor for the new netns. + * + * Returns: %TRUE on success. + */ +gboolean +nm_platform_link_set_netns (NMPlatform *self, int ifindex, int netns_fd) +{ + const NMPlatformLink *pllink; + + _CHECK_SELF (self, klass, FALSE); + + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (netns_fd > 0, FALSE); + + pllink = nm_platform_link_get (self, ifindex); + if (!pllink) + return FALSE; + + _LOGD ("link: ifindex %d changing network namespace to %d", ifindex, netns_fd); + return klass->link_set_netns (self, ifindex, netns_fd); +} + +/** * nm_platform_link_get_index: * @self: platform instance * @name: Interface name @@ -1625,9 +1651,9 @@ link_option_path (NMPlatform *self, int master, const char *category, const char return NULL; return g_strdup_printf ("/sys/class/net/%s/%s/%s", - ASSERT_VALID_PATH_COMPONENT (name), - ASSERT_VALID_PATH_COMPONENT (category), - ASSERT_VALID_PATH_COMPONENT (option)); + NM_ASSERT_VALID_PATH_COMPONENT (name), + NM_ASSERT_VALID_PATH_COMPONENT (category), + NM_ASSERT_VALID_PATH_COMPONENT (option)); } static gboolean @@ -1916,7 +1942,7 @@ nm_platform_link_infiniband_get_properties (NMPlatform *self, /* Could not get the link information via netlink. To support older kernels, * fallback to reading sysfs. */ - iface = ASSERT_VALID_PATH_COMPONENT (plink->name); + iface = NM_ASSERT_VALID_PATH_COMPONENT (plink->name); /* Fall back to reading sysfs */ path = g_strdup_printf ("/sys/class/net/%s/mode", iface); @@ -2128,6 +2154,10 @@ nm_platform_link_veth_get_properties (NMPlatform *self, int ifindex, int *out_pe /* Pre-4.1 kernel did not expose the peer_ifindex as IFA_LINK. Lookup via ethtool. */ if (out_peer_ifindex) { + nm_auto_pop_netns NMPNetns *netns = NULL; + + if (!nm_platform_netns_push (self, &netns)) + return FALSE; peer_ifindex = nmp_utils_ethtool_get_peer_ifindex (plink->name); if (peer_ifindex <= 0) return FALSE; @@ -2368,6 +2398,52 @@ _to_string_dev (NMPlatform *self, int ifindex, char *buf, size_t size) return buf; } +#define TO_STRING_IFA_FLAGS_BUF_SIZE 256 + +static const char * +_to_string_ifa_flags (guint32 ifa_flags, char *buf, gsize size) +{ +#define S_FLAGS_PREFIX " flags " + nm_assert (buf && size >= TO_STRING_IFA_FLAGS_BUF_SIZE && size > NM_STRLEN (S_FLAGS_PREFIX)); + + if (!ifa_flags) + buf[0] = '\0'; + else { + nm_platform_addr_flags2str (ifa_flags, &buf[NM_STRLEN (S_FLAGS_PREFIX)], size - NM_STRLEN (S_FLAGS_PREFIX)); + if (buf[NM_STRLEN (S_FLAGS_PREFIX)] == '\0') + buf[0] = '\0'; + else + memcpy (buf, S_FLAGS_PREFIX, NM_STRLEN (S_FLAGS_PREFIX)); + } + return buf; +} + +/******************************************************************/ + +gboolean +nm_platform_ethtool_set_wake_on_lan (NMPlatform *self, const char *ifname, NMSettingWiredWakeOnLan wol, const char *wol_password) +{ + nm_auto_pop_netns NMPNetns *netns = NULL; + _CHECK_SELF (self, klass, FALSE); + + if (!nm_platform_netns_push (self, &netns)) + return FALSE; + + return nmp_utils_ethtool_set_wake_on_lan (ifname, wol, wol_password); +} + +gboolean +nm_platform_ethtool_get_link_speed (NMPlatform *self, const char *ifname, guint32 *out_speed) +{ + nm_auto_pop_netns NMPNetns *netns = NULL; + _CHECK_SELF (self, klass, FALSE); + + if (!nm_platform_netns_push (self, &netns)) + return FALSE; + + return nmp_utils_ethtool_get_link_speed (ifname, out_speed); +} + /******************************************************************/ void @@ -2415,6 +2491,7 @@ nm_platform_ip4_address_add (NMPlatform *self, in_addr_t peer_address, guint32 lifetime, guint32 preferred, + guint32 flags, const char *label) { _CHECK_SELF (self, klass, FALSE); @@ -2435,12 +2512,13 @@ nm_platform_ip4_address_add (NMPlatform *self, addr.timestamp = 0; /* set it at zero, which to_string will treat as *now* */ addr.lifetime = lifetime; addr.preferred = preferred; + addr.n_ifa_flags = flags; if (label) g_strlcpy (addr.label, label, sizeof (addr.label)); _LOGD ("address: adding or updating IPv4 address: %s", nm_platform_ip4_address_to_string (&addr, NULL, 0)); } - return klass->ip4_address_add (self, ifindex, address, plen, peer_address, lifetime, preferred, label); + return klass->ip4_address_add (self, ifindex, address, plen, peer_address, lifetime, preferred, flags, label); } gboolean @@ -2535,7 +2613,7 @@ nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr addr } static gboolean -array_contains_ip4_address (const GArray *addresses, const NMPlatformIP4Address *address, gint64 now, guint32 padding) +array_contains_ip4_address (const GArray *addresses, const NMPlatformIP4Address *address, gint32 now) { guint len = addresses ? addresses->len : 0; guint i; @@ -2548,8 +2626,8 @@ array_contains_ip4_address (const GArray *addresses, const NMPlatformIP4Address && ((candidate->peer_address ^ address->peer_address) & nm_utils_ip4_prefix_to_netmask (address->plen)) == 0) { guint32 lifetime, preferred; - if (nmp_utils_lifetime_get (candidate->timestamp, candidate->lifetime, candidate->preferred, - now, padding, &lifetime, &preferred)) + if (nm_utils_lifetime_get (candidate->timestamp, candidate->lifetime, candidate->preferred, + now, &lifetime, &preferred)) return TRUE; } } @@ -2558,7 +2636,7 @@ array_contains_ip4_address (const GArray *addresses, const NMPlatformIP4Address } static gboolean -array_contains_ip6_address (const GArray *addresses, const NMPlatformIP6Address *address, gint64 now, guint32 padding) +array_contains_ip6_address (const GArray *addresses, const NMPlatformIP6Address *address, gint32 now) { guint len = addresses ? addresses->len : 0; guint i; @@ -2569,8 +2647,8 @@ array_contains_ip6_address (const GArray *addresses, const NMPlatformIP6Address if (IN6_ARE_ADDR_EQUAL (&candidate->address, &address->address) && candidate->plen == address->plen) { guint32 lifetime, preferred; - if (nmp_utils_lifetime_get (candidate->timestamp, candidate->lifetime, candidate->preferred, - now, padding, &lifetime, &preferred)) + if (nm_utils_lifetime_get (candidate->timestamp, candidate->lifetime, candidate->preferred, + now, &lifetime, &preferred)) return TRUE; } } @@ -2599,7 +2677,7 @@ nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, const GArray *known { GArray *addresses; NMPlatformIP4Address *address; - guint32 now = nm_utils_get_monotonic_timestamp_s (); + gint32 now = nm_utils_get_monotonic_timestamp_s (); int i; _CHECK_SELF (self, klass, FALSE); @@ -2609,7 +2687,7 @@ nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, const GArray *known for (i = 0; i < addresses->len; i++) { address = &g_array_index (addresses, NMPlatformIP4Address, i); - if (!array_contains_ip4_address (known_addresses, address, now, ADDRESS_LIFETIME_PADDING)) + if (!array_contains_ip4_address (known_addresses, address, now)) nm_platform_ip4_address_delete (self, ifindex, address->address, address->plen, address->peer_address); } g_array_free (addresses, TRUE); @@ -2625,11 +2703,13 @@ nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, const GArray *known const NMPlatformIP4Address *known_address = &g_array_index (known_addresses, NMPlatformIP4Address, i); guint32 lifetime, preferred; - if (!nmp_utils_lifetime_get (known_address->timestamp, known_address->lifetime, known_address->preferred, - now, ADDRESS_LIFETIME_PADDING, &lifetime, &preferred)) + if (!nm_utils_lifetime_get (known_address->timestamp, known_address->lifetime, known_address->preferred, + now, &lifetime, &preferred)) continue; - if (!nm_platform_ip4_address_add (self, ifindex, known_address->address, known_address->plen, known_address->peer_address, lifetime, preferred, known_address->label)) + if (!nm_platform_ip4_address_add (self, ifindex, known_address->address, known_address->plen, + known_address->peer_address, lifetime, preferred, + 0, known_address->label)) return FALSE; if (out_added_addresses) { @@ -2660,7 +2740,7 @@ nm_platform_ip6_address_sync (NMPlatform *self, int ifindex, const GArray *known { GArray *addresses; NMPlatformIP6Address *address; - guint32 now = nm_utils_get_monotonic_timestamp_s (); + gint32 now = nm_utils_get_monotonic_timestamp_s (); int i; /* Delete unknown addresses */ @@ -2672,7 +2752,7 @@ nm_platform_ip6_address_sync (NMPlatform *self, int ifindex, const GArray *known if (keep_link_local && IN6_IS_ADDR_LINKLOCAL (&address->address)) continue; - if (!array_contains_ip6_address (known_addresses, address, now, ADDRESS_LIFETIME_PADDING)) + if (!array_contains_ip6_address (known_addresses, address, now)) nm_platform_ip6_address_delete (self, ifindex, address->address, address->plen); } g_array_free (addresses, TRUE); @@ -2685,8 +2765,8 @@ nm_platform_ip6_address_sync (NMPlatform *self, int ifindex, const GArray *known const NMPlatformIP6Address *known_address = &g_array_index (known_addresses, NMPlatformIP6Address, i); guint32 lifetime, preferred; - if (!nmp_utils_lifetime_get (known_address->timestamp, known_address->lifetime, known_address->preferred, - now, ADDRESS_LIFETIME_PADDING, &lifetime, &preferred)) + if (!nm_utils_lifetime_get (known_address->timestamp, known_address->lifetime, known_address->preferred, + now, &lifetime, &preferred)) continue; if (!nm_platform_ip6_address_add (self, ifindex, known_address->address, @@ -2930,7 +3010,7 @@ _lifetime_to_string (guint32 timestamp, guint32 lifetime, gint32 now, char *buf, return "forever"; g_snprintf (buf, buf_size, "%usec", - nmp_utils_lifetime_rebase_relative_time_on_now (timestamp, lifetime, now, 0)); + nm_utils_lifetime_rebase_relative_time_on_now (timestamp, lifetime, now)); return buf; } @@ -3025,7 +3105,7 @@ nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len) str_flags->str, link->mtu, master, link->arptype, - str_if_set (str_link_type, "???"), + str_link_type ?: "???", link->kind ? (g_strcmp0 (str_link_type, link->kind) ? "/" : "*") : "?", link->kind && g_strcmp0 (str_link_type, link->kind) ? link->kind : "", link->initialized ? " init" : " not-init", @@ -3346,6 +3426,7 @@ nm_platform_lnk_vxlan_to_string (const NMPlatformLnkVxlan *lnk, char *buf, gsize const char * nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address, char *buf, gsize len) { + char s_flags[TO_STRING_IFA_FLAGS_BUF_SIZE]; char s_address[INET_ADDRSTRLEN]; char s_peer[INET_ADDRSTRLEN]; char str_dev[TO_STRING_DEV_BUF_SIZE]; @@ -3383,10 +3464,11 @@ nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address, char *bu str_time_p = _lifetime_summary_to_string (now, address->timestamp, address->preferred, address->lifetime, str_time, sizeof (str_time)); g_snprintf (buf, len, - "%s/%d lft %s pref %s%s%s%s%s src %s", + "%s/%d lft %s pref %s%s%s%s%s%s src %s", s_address, address->plen, str_lft_p, str_pref_p, str_time_p, str_peer ? str_peer : "", str_dev, + _to_string_ifa_flags (address->n_ifa_flags, s_flags, sizeof (s_flags)), str_label, source_to_string (address->source)); g_free (str_peer); @@ -3457,8 +3539,7 @@ NM_UTILS_ENUM2STR_DEFINE (nm_platform_route_scope2str, int, const char * nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address, char *buf, gsize len) { -#define S_FLAGS_PREFIX " flags " - char s_flags[256]; + char s_flags[TO_STRING_IFA_FLAGS_BUF_SIZE]; char s_address[INET6_ADDRSTRLEN]; char s_peer[INET6_ADDRSTRLEN]; char str_lft[30], str_pref[30], str_time[50]; @@ -3479,12 +3560,6 @@ nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address, char *bu _to_string_dev (NULL, address->ifindex, str_dev, sizeof (str_dev)); - nm_platform_addr_flags2str (address->n_ifa_flags, &s_flags[NM_STRLEN (S_FLAGS_PREFIX)], sizeof (s_flags) - NM_STRLEN (S_FLAGS_PREFIX)); - if (s_flags[NM_STRLEN (S_FLAGS_PREFIX)] == '\0') - s_flags[0] = '\0'; - else - memcpy (s_flags, S_FLAGS_PREFIX, NM_STRLEN (S_FLAGS_PREFIX)); - str_lft_p = _lifetime_to_string (address->timestamp, address->lifetime ? address->lifetime : NM_PLATFORM_LIFETIME_PERMANENT, now, str_lft, sizeof (str_lft)), @@ -3500,7 +3575,7 @@ nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address, char *bu s_address, address->plen, str_lft_p, str_pref_p, str_time_p, str_peer ? str_peer : "", str_dev, - s_flags, + _to_string_ifa_flags (address->n_ifa_flags, s_flags, sizeof (s_flags)), source_to_string (address->source)); g_free (str_peer); return buf; @@ -3825,6 +3900,7 @@ nm_platform_ip4_address_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4A _CMP_FIELD (a, b, timestamp); _CMP_FIELD (a, b, lifetime); _CMP_FIELD (a, b, preferred); + _CMP_FIELD (a, b, n_ifa_flags); _CMP_FIELD_STR (a, b, label); return 0; } @@ -3980,6 +4056,31 @@ log_ip6_route (NMPlatform *self, NMPObjectType obj_type, int ifindex, NMPlatform /******************************************************************/ +NMPNetns * +nm_platform_netns_get (NMPlatform *self) +{ + _CHECK_SELF (self, klass, NULL); + + return self->_netns; +} + +gboolean +nm_platform_netns_push (NMPlatform *platform, NMPNetns **netns) +{ + g_return_val_if_fail (NM_IS_PLATFORM (platform), FALSE); + + if ( platform->_netns + && !nmp_netns_push (platform->_netns)) { + NM_SET_OUT (netns, NULL); + return FALSE; + } + + NM_SET_OUT (netns, platform->_netns); + return TRUE; +} + +/******************************************************************/ + static gboolean _vtr_v4_route_add (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *route, gint64 metric) { @@ -4079,9 +4180,20 @@ static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { - NMPlatformPrivate *priv = NM_PLATFORM_GET_PRIVATE (object); + NMPlatform *self = NM_PLATFORM (object); + NMPlatformPrivate *priv = NM_PLATFORM_GET_PRIVATE (self); switch (prop_id) { + case PROP_NETNS_SUPPORT: + /* construct-only */ + if (g_value_get_boolean (value)) { + NMPNetns *netns; + + netns = nmp_netns_get_current (); + if (netns) + self->_netns = g_object_ref (netns); + } + break; case PROP_REGISTER_SINGLETON: /* construct-only */ priv->register_singleton = g_value_get_boolean (value); @@ -4110,6 +4222,14 @@ nm_platform_init (NMPlatform *object) } static void +finalize (GObject *object) +{ + NMPlatform *self = NM_PLATFORM (object); + + g_clear_object (&self->_netns); +} + +static void nm_platform_class_init (NMPlatformClass *platform_class) { GObjectClass *object_class = G_OBJECT_CLASS (platform_class); @@ -4118,10 +4238,19 @@ nm_platform_class_init (NMPlatformClass *platform_class) object_class->set_property = set_property; object_class->constructed = constructed; + object_class->finalize = finalize; platform_class->wifi_set_powersave = wifi_set_powersave; g_object_class_install_property + (object_class, PROP_NETNS_SUPPORT, + g_param_spec_boolean (NM_PLATFORM_NETNS_SUPPORT, "", "", + FALSE, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, PROP_REGISTER_SINGLETON, g_param_spec_boolean (NM_PLATFORM_REGISTER_SINGLETON, "", "", FALSE, diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index b94c440a..8c97f766 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -31,6 +31,7 @@ #include "nm-core-utils.h" #include "nm-setting-vlan.h" +#include "nm-setting-wired.h" #define NM_TYPE_PLATFORM (nm_platform_get_type ()) #define NM_PLATFORM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_PLATFORM, NMPlatform)) @@ -41,6 +42,7 @@ /******************************************************************/ +#define NM_PLATFORM_NETNS_SUPPORT "netns-support" #define NM_PLATFORM_REGISTER_SINGLETON "register-singleton" /******************************************************************/ @@ -177,8 +179,6 @@ typedef enum { NM_PLATFORM_SIGNAL_REMOVED, } NMPlatformSignalChangeType; -#define NM_PLATFORM_LIFETIME_PERMANENT G_MAXUINT32 - typedef enum { /*< skip >*/ NM_PLATFORM_GET_ROUTE_FLAGS_NONE = 0, @@ -221,6 +221,11 @@ typedef struct { guint32 timestamp; \ guint32 lifetime; /* seconds since timestamp */ \ guint32 preferred; /* seconds since timestamp */ \ + \ + /* ifa_flags in 'struct ifaddrmsg' from <linux/if_addr.h>, extended to 32 bit by + * IFA_FLAGS attribute. */ \ + guint32 n_ifa_flags; \ + \ int plen; \ ; @@ -269,7 +274,6 @@ struct _NMPlatformIP6Address { __NMPlatformIPAddress_COMMON; struct in6_addr address; struct in6_addr peer_address; - guint32 n_ifa_flags; /* ifa_flags from <linux/if_addr.h>, field type "unsigned int" is as used in rtnl_addr_get_flags. */ }; typedef union { @@ -459,6 +463,8 @@ typedef struct { struct _NMPlatform { GObject parent; + + NMPNetns *_netns; }; typedef struct { @@ -485,6 +491,9 @@ typedef struct { gboolean (*link_get_unmanaged) (NMPlatform *, int ifindex, gboolean *unmanaged); gboolean (*link_refresh) (NMPlatform *, int ifindex); + + gboolean (*link_set_netns) (NMPlatform *, int ifindex, int netns_fd); + void (*process_events) (NMPlatform *self); gboolean (*link_set_up) (NMPlatform *, int ifindex, gboolean *out_no_firmware); @@ -586,6 +595,7 @@ typedef struct { in_addr_t peer_address, guint32 lifetime, guint32 preferred_lft, + guint32 flags, const char *label); gboolean (*ip6_address_add) (NMPlatform *, int ifindex, @@ -665,6 +675,9 @@ _nm_platform_uint8_inv (guint8 scope) return (guint8) ~scope; } +NMPNetns *nm_platform_netns_get (NMPlatform *self); +gboolean nm_platform_netns_push (NMPlatform *platform, NMPNetns **netns); + const char *nm_link_type_to_string (NMLinkType link_type); const char *_nm_platform_error_to_string (NMPlatformError error); @@ -688,6 +701,8 @@ NMPlatformError nm_platform_link_bond_add (NMPlatform *self, const char *name, c NMPlatformError nm_platform_link_team_add (NMPlatform *self, const char *name, const NMPlatformLink **out_link); gboolean nm_platform_link_delete (NMPlatform *self, int ifindex); +gboolean nm_platform_link_set_netns (NMPlatform *self, int ifindex, int netns_fd); + /* convienience methods to lookup the link and access fields of NMPlatformLink. */ int nm_platform_link_get_ifindex (NMPlatform *self, const char *name); const char *nm_platform_link_get_name (NMPlatform *self, int ifindex); @@ -853,6 +868,7 @@ gboolean nm_platform_ip4_address_add (NMPlatform *self, in_addr_t peer_address, guint32 lifetime, guint32 preferred_lft, + guint32 flags, const char *label); gboolean nm_platform_ip6_address_add (NMPlatform *self, int ifindex, @@ -925,4 +941,7 @@ const char *nm_platform_route_scope2str (int scope, char *buf, gsize len); int nm_platform_ip_address_cmp_expiry (const NMPlatformIPAddress *a, const NMPlatformIPAddress *b); +gboolean nm_platform_ethtool_set_wake_on_lan (NMPlatform *self, const char *ifname, NMSettingWiredWakeOnLan wol, const char *wol_password); +gboolean nm_platform_ethtool_get_link_speed (NMPlatform *self, const char *ifname, guint32 *out_speed); + #endif /* __NETWORKMANAGER_PLATFORM_H__ */ diff --git a/src/platform/nmp-netns.c b/src/platform/nmp-netns.c new file mode 100644 index 00000000..26295855 --- /dev/null +++ b/src/platform/nmp-netns.c @@ -0,0 +1,732 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* nm-platform.c - Handle runtime kernel networking configuration + * + * 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) 2016 Red Hat, Inc. + */ + +#include "nm-default.h" +#include "nmp-netns.h" + +#include <fcntl.h> +#include <errno.h> +#include <sys/mount.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include "NetworkManagerUtils.h" + +#define PROC_SELF_NS_MNT "/proc/self/ns/mnt" +#define PROC_SELF_NS_NET "/proc/self/ns/net" + +#define _CLONE_NS_ALL ((int) (CLONE_NEWNS | CLONE_NEWNET)) +#define _CLONE_NS_ALL_V CLONE_NEWNS , CLONE_NEWNET + +NM_UTILS_FLAGS2STR_DEFINE_STATIC (_clone_ns_to_str, int, + NM_UTILS_FLAGS2STR (CLONE_NEWNS, "mnt"), + NM_UTILS_FLAGS2STR (CLONE_NEWNET, "net"), +); + +static const char * +__ns_types_to_str (int ns_types, int ns_types_already_set, char *buf, gsize len) +{ + const char *b = buf; + char bb[200]; + + nm_utils_strbuf_append_c (&buf, &len, '['); + if (ns_types & ~ns_types_already_set) { + nm_utils_strbuf_append_str (&buf, &len, + _clone_ns_to_str (ns_types & ~ns_types_already_set, bb, sizeof (bb))); + } + if (ns_types & ns_types_already_set) { + if (ns_types & ~ns_types_already_set) + nm_utils_strbuf_append_c (&buf, &len, '/'); + nm_utils_strbuf_append_str (&buf, &len, + _clone_ns_to_str (ns_types & ns_types_already_set, bb, sizeof (bb))); + } + nm_utils_strbuf_append_c (&buf, &len, ']'); + return b; +} +#define _ns_types_to_str(ns_types, ns_types_already_set, buf) \ + __ns_types_to_str (ns_types, ns_types_already_set, buf, sizeof (buf)) + +/*********************************************************************************************/ + +#define _NMLOG_DOMAIN LOGD_PLATFORM +#define _NMLOG_PREFIX_NAME "netns" +#define _NMLOG(level, netns, ...) \ + G_STMT_START { \ + NMLogLevel _level = (level); \ + \ + if (nm_logging_enabled (_level, _NMLOG_DOMAIN)) { \ + NMPNetns *_netns = (netns); \ + char _sbuf[20]; \ + \ + _nm_log (_level, _NMLOG_DOMAIN, 0, \ + "%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, \ + (_netns ? nm_sprintf_buf (_sbuf, "[%p]", _netns) : "") \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + } G_STMT_END + +/*********************************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE ( + PROP_FD_NET, + PROP_FD_MNT, +); + +typedef struct _NMPNetnsPrivate NMPNetnsPrivate; + +struct _NMPNetnsPrivate { + int fd_net; + int fd_mnt; +}; + +typedef struct { + NMPNetns *netns; + int count; + int ns_types; +} NetnsInfo; + +static void _stack_push (NMPNetns *netns, int ns_types); +static NMPNetns *_netns_new (GError **error); + +/*********************************************************************************************/ + +static GArray *netns_stack = NULL; + +static void +_stack_ensure_init_impl (void) +{ + NMPNetns *netns; + GError *error = NULL; + + nm_assert (!netns_stack); + + netns_stack = g_array_new (FALSE, FALSE, sizeof (NetnsInfo)); + + /* at the bottom of the stack we must try to create a netns instance + * that we never pop. It's the base to which we need to return. */ + + netns = _netns_new (&error); + + if (!netns) { + /* don't know how to recover from this error. Netns are not supported. */ + _LOGE (NULL, "failed to create initial netns: %s", error->message); + g_clear_error (&error); + return; + } + + _stack_push (netns, _CLONE_NS_ALL); + + /* we leak this instance inside netns_stack. It cannot be popped. */ + g_object_unref (netns); +} +#define _stack_ensure_init() \ + G_STMT_START { \ + if (G_UNLIKELY (!netns_stack)) { \ + _stack_ensure_init_impl (); \ + } \ + } G_STMT_END + +static NMPNetns * +_stack_current_netns (int ns_types) +{ + guint j; + + nm_assert (netns_stack && netns_stack->len > 0); + + /* we search the stack top-down to find the netns that has + * all @ns_types set. */ + for (j = netns_stack->len; ns_types && j >= 1; ) { + NetnsInfo *info; + + info = &g_array_index (netns_stack, NetnsInfo, --j); + + if (NM_FLAGS_ALL (info->ns_types, ns_types)) + return info->netns; + } + + g_return_val_if_reached (NULL); +} + +static int +_stack_current_ns_types (NMPNetns *netns, int ns_types) +{ + const int ns_types_check[] = { _CLONE_NS_ALL_V }; + guint i, j; + int res = 0; + + nm_assert (netns); + nm_assert (netns_stack && netns_stack->len > 0); + + /* we search the stack top-down to check which of @ns_types + * are already set to @netns. */ + for (j = netns_stack->len; ns_types && j >= 1; ) { + NetnsInfo *info; + + info = &g_array_index (netns_stack, NetnsInfo, --j); + if (info->netns != netns) { + ns_types = NM_FLAGS_UNSET (ns_types, info->ns_types); + continue; + } + + for (i = 0; i < G_N_ELEMENTS (ns_types_check); i++) { + if ( NM_FLAGS_HAS (ns_types, ns_types_check[i]) + && NM_FLAGS_HAS (info->ns_types, ns_types_check[i])) { + res = NM_FLAGS_SET (res, ns_types_check[i]); + ns_types = NM_FLAGS_UNSET (ns_types, ns_types_check[i]); + } + } + } + + return res; +} + +static NetnsInfo * +_stack_peek (void) +{ + nm_assert (netns_stack); + + if (netns_stack->len > 0) + return &g_array_index (netns_stack, NetnsInfo, (netns_stack->len - 1)); + return NULL; +} + +static NetnsInfo * +_stack_bottom (void) +{ + nm_assert (netns_stack); + + if (netns_stack->len > 0) + return &g_array_index (netns_stack, NetnsInfo, 0); + return NULL; +} + +static void +_stack_push (NMPNetns *netns, int ns_types) +{ + NetnsInfo *info; + + nm_assert (netns_stack); + nm_assert (NMP_IS_NETNS (netns)); + nm_assert (NM_FLAGS_ANY (ns_types, _CLONE_NS_ALL)); + nm_assert (!NM_FLAGS_ANY (ns_types, ~_CLONE_NS_ALL)); + + g_array_set_size (netns_stack, netns_stack->len + 1); + + info = &g_array_index (netns_stack, NetnsInfo, (netns_stack->len - 1)); + info->netns = g_object_ref (netns); + info->ns_types = ns_types; + info->count = 1; +} + +static void +_stack_pop (void) +{ + NetnsInfo *info; + + nm_assert (netns_stack); + nm_assert (netns_stack->len > 1); + + info = &g_array_index (netns_stack, NetnsInfo, (netns_stack->len - 1)); + + nm_assert (NMP_IS_NETNS (info->netns)); + nm_assert (info->count == 1); + + g_object_unref (info->netns); + + g_array_set_size (netns_stack, netns_stack->len - 1); +} + +static guint +_stack_size (void) +{ + nm_assert (netns_stack); + + return netns_stack->len; +} + +/*********************************************************************************************/ + +G_DEFINE_TYPE (NMPNetns, nmp_netns, G_TYPE_OBJECT); + +#define NMP_NETNS_GET_PRIVATE(o) ((o)->priv) + +/*********************************************************************************************/ + +static NMPNetns * +_netns_new (GError **error) +{ + NMPNetns *self; + int fd_net, fd_mnt; + int errsv; + + fd_net = open (PROC_SELF_NS_NET, O_RDONLY); + if (fd_net == -1) { + errsv = errno; + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "Failed opening netns: %s", + g_strerror (errsv)); + return NULL; + } + + fd_mnt = open (PROC_SELF_NS_MNT, O_RDONLY); + if (fd_mnt == -1) { + errsv = errno; + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "Failed opening mntns: %s", + g_strerror (errsv)); + close (fd_net); + return NULL; + } + + self = g_object_new (NMP_TYPE_NETNS, + NMP_NETNS_FD_NET, fd_net, + NMP_NETNS_FD_MNT, fd_mnt, + NULL); + + _LOGD (self, "new netns (net:%d, mnt:%d)", fd_net, fd_mnt); + + return self; +} + +static int +_setns (NMPNetns *self, int type) +{ + char buf[100]; + int fd; + + nm_assert (NM_IN_SET (type, _CLONE_NS_ALL_V)); + + fd = (type == CLONE_NEWNET) ? self->priv->fd_net : self->priv->fd_mnt; + + _LOGt (self, "set netns(%s, %d)", _ns_types_to_str (type, 0, buf), fd); + + return setns (fd, type); +} + +static gboolean +_netns_switch_push (NMPNetns *self, int ns_types) +{ + int errsv; + + if ( NM_FLAGS_HAS (ns_types, CLONE_NEWNET) + && !_stack_current_ns_types (self, CLONE_NEWNET) + && _setns (self, CLONE_NEWNET) != 0) { + errsv = errno; + _LOGE (self, "failed to switch netns: %s", g_strerror (errsv)); + return FALSE; + } + if ( NM_FLAGS_HAS (ns_types, CLONE_NEWNS) + && !_stack_current_ns_types (self, CLONE_NEWNS) + && _setns (self, CLONE_NEWNS) != 0) { + errsv = errno; + _LOGE (self, "failed to switch mntns: %s", g_strerror (errsv)); + + /* try to fix the mess by returning to the previous netns. */ + if ( NM_FLAGS_HAS (ns_types, CLONE_NEWNET) + && !_stack_current_ns_types (self, CLONE_NEWNET)) { + self = _stack_current_netns (CLONE_NEWNET); + if ( self + && _setns (self, CLONE_NEWNET) != 0) { + errsv = errno; + _LOGE (self, "failed to restore netns: %s", g_strerror (errsv)); + } + } + return FALSE; + } + + return TRUE; +} + +static gboolean +_netns_switch_pop (NMPNetns *self, int ns_types) +{ + int errsv; + NMPNetns *current; + int success = TRUE; + + if ( NM_FLAGS_HAS (ns_types, CLONE_NEWNET) + && (!self || !_stack_current_ns_types (self, CLONE_NEWNET))) { + current = _stack_current_netns (CLONE_NEWNET); + if (!current) { + g_warn_if_reached (); + success = FALSE; + } else if (_setns (current, CLONE_NEWNET) != 0) { + errsv = errno; + _LOGE (self, "failed to switch netns: %s", g_strerror (errsv)); + success = FALSE; + } + } + if ( NM_FLAGS_HAS (ns_types, CLONE_NEWNS) + && (!self || !_stack_current_ns_types (self, CLONE_NEWNS))) { + current = _stack_current_netns (CLONE_NEWNS); + if (!current) { + g_warn_if_reached (); + success = FALSE; + } else if (_setns (current, CLONE_NEWNS) != 0) { + errsv = errno; + _LOGE (self, "failed to switch mntns: %s", g_strerror (errsv)); + success = FALSE; + } + } + + return success; +} + +/*********************************************************************************************/ + +int +nmp_netns_get_fd_net (NMPNetns *self) +{ + g_return_val_if_fail (NMP_IS_NETNS (self), 0); + + return self->priv->fd_net; +} + +int +nmp_netns_get_fd_mnt (NMPNetns *self) +{ + g_return_val_if_fail (NMP_IS_NETNS (self), 0); + + return self->priv->fd_mnt; +} + +/*********************************************************************************************/ + +static gboolean +_nmp_netns_push_type (NMPNetns *self, int ns_types) +{ + NetnsInfo *info; + char sbuf[100]; + + _stack_ensure_init (); + + info = _stack_peek (); + g_return_val_if_fail (info, FALSE); + + if (info->netns == self && info->ns_types == ns_types) { + info->count++; + _LOGt (self, "push#%u* %s (increase count to %d)", + _stack_size () - 1, + _ns_types_to_str (ns_types, ns_types, sbuf), info->count); + return TRUE; + } + + _LOGD (self, "push#%u %s", + _stack_size (), + _ns_types_to_str (ns_types, + _stack_current_ns_types (self, ns_types), + sbuf)); + + if (!_netns_switch_push (self, ns_types)) + return FALSE; + + _stack_push (self, ns_types); + return TRUE; +} + +gboolean +nmp_netns_push (NMPNetns *self) +{ + g_return_val_if_fail (NMP_IS_NETNS (self), FALSE); + + return _nmp_netns_push_type (self, _CLONE_NS_ALL); +} + +gboolean +nmp_netns_push_type (NMPNetns *self, int ns_types) +{ + g_return_val_if_fail (NMP_IS_NETNS (self), FALSE); + g_return_val_if_fail (!NM_FLAGS_ANY (ns_types, ~_CLONE_NS_ALL), FALSE); + + return _nmp_netns_push_type (self, ns_types == 0 ? _CLONE_NS_ALL : ns_types); +} + +NMPNetns * +nmp_netns_new (void) +{ + NMPNetns *self; + int errsv; + GError *error = NULL; + + _stack_ensure_init (); + + if (!_stack_peek ()) { + /* there are no netns instances. We cannot create a new one + * (because after unshare we couldn't return to the original one). */ + return NULL; + } + + if (unshare (_CLONE_NS_ALL) != 0) { + errsv = errno; + _LOGE (NULL, "failed to create new net and mnt namespace: %s", g_strerror (errsv)); + return NULL; + } + + if (mount ("", "/", "none", MS_SLAVE | MS_REC, NULL) != 0) { + errsv = errno; + _LOGE (NULL, "failed mount --make-rslave: %s", g_strerror (errsv)); + goto err_out; + } + + if (umount2 ("/sys", MNT_DETACH) != 0) { + errsv = errno; + _LOGE (NULL, "failed umount /sys: %s", g_strerror (errsv)); + goto err_out; + } + + if (mount ("sysfs", "/sys", "sysfs", 0, NULL) != 0) { + errsv = errno; + _LOGE (NULL, "failed mount /sys: %s", g_strerror (errsv)); + goto err_out; + } + + self = _netns_new (&error); + if (!self) { + _LOGE (NULL, "failed to create netns after unshare: %s", error->message); + g_clear_error (&error); + goto err_out; + } + + _stack_push (self, _CLONE_NS_ALL); + + return self; +err_out: + _netns_switch_pop (NULL, _CLONE_NS_ALL); + return NULL; +} + +gboolean +nmp_netns_pop (NMPNetns *self) +{ + NetnsInfo *info; + int ns_types; + + g_return_val_if_fail (NMP_IS_NETNS (self), FALSE); + + _stack_ensure_init (); + + info = _stack_peek (); + + g_return_val_if_fail (info, FALSE); + g_return_val_if_fail (info->netns == self, FALSE); + + if (info->count > 1) { + info->count--; + _LOGt (self, "pop#%u* (decrease count to %d)", + _stack_size () - 1, info->count); + return TRUE; + } + g_return_val_if_fail (info->count == 1, FALSE); + + /* cannot pop the original netns. */ + g_return_val_if_fail (_stack_size () > 1, FALSE); + + _LOGD (self, "pop#%u", _stack_size () - 1); + + ns_types = info->ns_types; + + _stack_pop (); + + return _netns_switch_pop (self, ns_types); +} + +NMPNetns * +nmp_netns_get_current (void) +{ + NetnsInfo *info; + + _stack_ensure_init (); + + info = _stack_peek (); + return info ? info->netns : NULL; +} + +NMPNetns * +nmp_netns_get_initial (void) +{ + NetnsInfo *info; + + _stack_ensure_init (); + + info = _stack_bottom (); + return info ? info->netns : NULL; +} + +gboolean +nmp_netns_is_initial (void) +{ + if (G_UNLIKELY (!netns_stack)) + return TRUE; + + return nmp_netns_get_current () == nmp_netns_get_initial (); +} + +/*********************************************************************************************/ + +gboolean +nmp_netns_bind_to_path (NMPNetns *self, const char *filename, int *out_fd) +{ + gs_free char *dirname = NULL; + int errsv; + int fd; + nm_auto_pop_netns NMPNetns *netns_pop = NULL; + + g_return_val_if_fail (NMP_IS_NETNS (self), FALSE); + g_return_val_if_fail (filename && filename[0] == '/', FALSE); + + if (!nmp_netns_push_type (self, CLONE_NEWNET)) + return FALSE; + netns_pop = self; + + dirname = g_path_get_dirname (filename); + if (mkdir (dirname, 0) != 0) { + errsv = errno; + if (errsv != EEXIST) { + _LOGE (self, "bind: failed to create directory %s: %s", + dirname, g_strerror (errsv)); + return FALSE; + } + } + + if ((fd = creat (filename, S_IRUSR | S_IRGRP | S_IROTH)) == -1) { + errsv = errno; + _LOGE (self, "bind: failed to create %s: %s", + filename, g_strerror (errsv)); + return FALSE; + } + close (fd); + + if (mount (PROC_SELF_NS_NET, filename, "none", MS_BIND, NULL) != 0) { + errsv = errno; + _LOGE (self, "bind: failed to mount %s to %s: %s", + PROC_SELF_NS_NET, filename, g_strerror (errsv)); + unlink (filename); + return FALSE; + } + + if (out_fd) { + if ((fd = open (filename, O_RDONLY)) == -1) { + errsv = errno; + _LOGE (self, "bind: failed to open %s: %s", filename, g_strerror (errsv)); + umount2 (filename, MNT_DETACH); + unlink (filename); + return FALSE; + } + *out_fd = fd; + } + + return TRUE; +} + +gboolean +nmp_netns_bind_to_path_destroy (NMPNetns *self, const char *filename) +{ + int errsv; + + g_return_val_if_fail (NMP_IS_NETNS (self), FALSE); + g_return_val_if_fail (filename && filename[0] == '/', FALSE); + + if (umount2 (filename, MNT_DETACH) != 0) { + errsv = errno; + _LOGE (self, "bind: failed to unmount2 %s: %s", filename, g_strerror (errsv)); + return FALSE; + } + if (unlink (filename) != 0) { + errsv = errno; + _LOGE (self, "bind: failed to unlink %s: %s", filename, g_strerror (errsv)); + return FALSE; + } + return TRUE; +} + +/******************************************************************************/ + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMPNetns *self = NMP_NETNS (object); + + switch (prop_id) { + case PROP_FD_NET: + /* construct only */ + self->priv->fd_net = g_value_get_int (value); + g_return_if_fail (self->priv->fd_net > 0); + break; + case PROP_FD_MNT: + /* construct only */ + self->priv->fd_mnt = g_value_get_int (value); + g_return_if_fail (self->priv->fd_mnt > 0); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nmp_netns_init (NMPNetns *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NMP_TYPE_NETNS, NMPNetnsPrivate); +} + +static void +dispose (GObject *object) +{ + NMPNetns *self = NMP_NETNS (object); + + if (self->priv->fd_net > 0) { + close (self->priv->fd_net); + self->priv->fd_net = 0; + } + + if (self->priv->fd_mnt > 0) { + close (self->priv->fd_mnt); + self->priv->fd_mnt = 0; + } + + G_OBJECT_CLASS (nmp_netns_parent_class)->dispose (object); +} + +static void +nmp_netns_class_init (NMPNetnsClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMPNetnsPrivate)); + + object_class->set_property = set_property; + object_class->dispose = dispose; + + obj_properties[PROP_FD_NET] + = g_param_spec_int (NMP_NETNS_FD_NET, "", "", + 0, G_MAXINT, 0, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_FD_MNT] + = g_param_spec_int (NMP_NETNS_FD_MNT, "", "", + 0, G_MAXINT, 0, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); +} diff --git a/src/platform/nmp-netns.h b/src/platform/nmp-netns.h new file mode 100644 index 00000000..4eac07ac --- /dev/null +++ b/src/platform/nmp-netns.h @@ -0,0 +1,74 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* nm-platform.c - Handle runtime kernel networking configuration + * + * 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) 2016 Red Hat, Inc. + */ + +#ifndef __NMP_NETNS_UTILS_H__ +#define __NMP_NETNS_UTILS_H__ + +/*****************************************************************************/ + +#define NMP_TYPE_NETNS (nmp_netns_get_type ()) +#define NMP_NETNS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMP_TYPE_NETNS, NMPNetns)) +#define NMP_NETNS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NMP_TYPE_NETNS, NMPNetnsClass)) +#define NMP_IS_NETNS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NMP_TYPE_NETNS)) +#define NMP_IS_NETNS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NMP_TYPE_NETNS)) +#define NMP_NETNS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NMP_TYPE_NETNS, NMPNetnsClass)) + +#define NMP_NETNS_FD_NET "fd-net" +#define NMP_NETNS_FD_MNT "fd-mnt" + +struct _NMPNetnsPrivate; + +struct _NMPNetns { + GObject parent; + struct _NMPNetnsPrivate *priv; +}; + +typedef struct { + GObjectClass parent; +} NMPNetnsClass; + +GType nmp_netns_get_type (void); + +NMPNetns *nmp_netns_new (void); + +gboolean nmp_netns_push (NMPNetns *self); +gboolean nmp_netns_push_type (NMPNetns *self, int ns_types); +gboolean nmp_netns_pop (NMPNetns *self); + +NMPNetns *nmp_netns_get_current (void); +NMPNetns *nmp_netns_get_initial (void); +gboolean nmp_netns_is_initial (void); + +int nmp_netns_get_fd_net (NMPNetns *self); +int nmp_netns_get_fd_mnt (NMPNetns *self); + +static inline void +_nm_auto_pop_netns (NMPNetns **p) +{ + if (*p) + nmp_netns_pop (*p); +} + +#define nm_auto_pop_netns __attribute__((cleanup(_nm_auto_pop_netns))) + +gboolean nmp_netns_bind_to_path (NMPNetns *self, const char *filename, int *out_fd); +gboolean nmp_netns_bind_to_path_destroy (NMPNetns *self, const char *filename); + +#endif /* __NMP_NETNS_UTILS_H__ */ diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c index b7b04490..adeb3aab 100644 --- a/src/platform/nmp-object.c +++ b/src/platform/nmp-object.c @@ -174,10 +174,6 @@ _nmp_object_fixup_link_udev_fields (NMPObject *obj, gboolean use_udev) * nmp_cache_use_udev_get(). It is on purpose not to test * for a writable /sys on every call. A minor reason for that is * performance, but the real reason is reproducibility. - * - * If you want to support changing of whether udev is enabled, - * reset the value via nmp_cache_use_udev_set() carefully -- and - * possibly update the links in the cache accordingly. * */ initialized = TRUE; } @@ -1192,12 +1188,6 @@ _vt_cmd_obj_init_cache_id_ipx_route (const NMPObject *obj, NMPCacheIdType id_typ /******************************************************************/ gboolean -nmp_cache_use_udev_detect () -{ - return access ("/sys", W_OK) == 0; -} - -gboolean nmp_cache_use_udev_get (const NMPCache *cache) { g_return_val_if_fail (cache, TRUE); @@ -1205,19 +1195,6 @@ nmp_cache_use_udev_get (const NMPCache *cache) return cache->use_udev; } -gboolean -nmp_cache_use_udev_set (NMPCache *cache, gboolean use_udev) -{ - g_return_val_if_fail (cache, FALSE); - - use_udev = !!use_udev; - if (use_udev == cache->use_udev) - return FALSE; - - cache->use_udev = use_udev; - return TRUE; -} - /******************************************************************/ /** @@ -1858,7 +1835,7 @@ nmp_cache_update_link_master_connected (NMPCache *cache, int ifindex, NMPObject /******************************************************************/ NMPCache * -nmp_cache_new () +nmp_cache_new (gboolean use_udev) { NMPCache *cache = g_new (NMPCache, 1); @@ -1870,7 +1847,7 @@ nmp_cache_new () (NMMultiIndexFuncEqual) nmp_cache_id_equal, (NMMultiIndexFuncClone) nmp_cache_id_clone, (NMMultiIndexFuncDestroy) nmp_cache_id_destroy); - cache->use_udev = nmp_cache_use_udev_detect (); + cache->use_udev = !!use_udev; return cache; } diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h index 7758798f..6d5b9627 100644 --- a/src/platform/nmp-object.h +++ b/src/platform/nmp-object.h @@ -399,9 +399,7 @@ GHashTable *nmp_cache_lookup_all_to_hash (const NMPCache *cache, gboolean nmp_cache_link_connected_needs_toggle (const NMPCache *cache, const NMPObject *master, const NMPObject *potential_slave, const NMPObject *ignore_slave); const NMPObject *nmp_cache_link_connected_needs_toggle_by_ifindex (const NMPCache *cache, int master_ifindex, const NMPObject *potential_slave, const NMPObject *ignore_slave); -gboolean nmp_cache_use_udev_detect (void); gboolean nmp_cache_use_udev_get (const NMPCache *cache); -gboolean nmp_cache_use_udev_set (NMPCache *cache, gboolean use_udev); void ASSERT_nmp_cache_is_consistent (const NMPCache *cache); @@ -411,7 +409,7 @@ NMPCacheOpsType nmp_cache_update_netlink (NMPCache *cache, NMPObject *obj, NMPOb 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_master_connected (NMPCache *cache, int ifindex, NMPObject **out_obj, gboolean *out_was_visible, NMPCachePreHook pre_hook, gpointer user_data); -NMPCache *nmp_cache_new (void); +NMPCache *nmp_cache_new (gboolean use_udev); void nmp_cache_free (NMPCache *cache); #endif /* __NMP_OBJECT_H__ */ diff --git a/src/platform/tests/test-address.c b/src/platform/tests/test-address.c index 3b52a7be..83a0bfd3 100644 --- a/src/platform/tests/test-address.c +++ b/src/platform/tests/test-address.c @@ -94,12 +94,12 @@ test_ip4_address_general (void) /* Add address */ g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr)); - nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, NULL); + nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, 0, NULL); g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr)); accept_signal (address_added); /* Add address again (aka update) */ - nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr, lifetime + 100, preferred + 50, NULL); + nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr, lifetime + 100, preferred + 50, 0, NULL); accept_signals (address_changed, 0, 1); /* Test address listing */ @@ -197,7 +197,7 @@ test_ip4_address_general_2 (void) g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, DEVICE_IFINDEX, NULL)); /* Add/delete notification */ - nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, NULL); + nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, 0, NULL); accept_signal (address_added); g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr)); nmtstp_ip4_address_del (EX, ifindex, addr, IP4_PLEN, addr); @@ -205,7 +205,7 @@ test_ip4_address_general_2 (void) g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr)); /* Add/delete conflict */ - nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, NULL); + nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, 0, NULL); g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr)); accept_signal (address_added); @@ -273,7 +273,7 @@ test_ip4_address_peer (void) accept_signals (address_added, 0, G_MAXINT); /* Add/delete notification */ - nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr_peer, lifetime, preferred, NULL); + nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr_peer, lifetime, preferred, 0, NULL); accept_signal (address_added); a = nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer); g_assert (a); @@ -281,7 +281,7 @@ test_ip4_address_peer (void) nmtstp_ip_address_assert_lifetime ((NMPlatformIPAddress *) a, -1, lifetime, preferred); - nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr_peer2, lifetime, preferred, NULL); + nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr_peer2, lifetime, preferred, 0, NULL); accept_signal (address_added); g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer)); a = nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer2); @@ -328,7 +328,7 @@ test_ip4_address_peer_zero (void) for (i = 0; i < G_N_ELEMENTS (peers); i++) { g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, plen, r_peers[i])); - nmtstp_ip4_address_add (EX, ifindex, addr, plen, r_peers[i], lifetime, preferred, label); + nmtstp_ip4_address_add (EX, ifindex, addr, plen, r_peers[i], lifetime, preferred, 0, label); addrs = nm_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex); g_assert (addrs); diff --git a/src/platform/tests/test-cleanup.c b/src/platform/tests/test-cleanup.c index 6ad24478..4036daad 100644 --- a/src/platform/tests/test-cleanup.c +++ b/src/platform/tests/test-cleanup.c @@ -63,7 +63,7 @@ test_cleanup_internal (void) g_assert (ifindex > 0); /* Add routes and addresses */ - g_assert (nm_platform_ip4_address_add (NM_PLATFORM_GET, ifindex, addr4, plen4, addr4, lifetime, preferred, NULL)); + g_assert (nm_platform_ip4_address_add (NM_PLATFORM_GET, ifindex, addr4, plen4, addr4, lifetime, preferred, 0, NULL)); g_assert (nm_platform_ip6_address_add (NM_PLATFORM_GET, ifindex, addr6, plen6, in6addr_any, lifetime, preferred, flags)); g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, gateway4, 32, INADDR_ANY, 0, metric, mss)); g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network4, plen4, gateway4, 0, metric, mss)); diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index 268a5c92..e9fffe90 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -338,30 +338,32 @@ _wait_for_signal_timeout (gpointer user_data) } gboolean -nmtstp_wait_for_signal (guint timeout_ms) +nmtstp_wait_for_signal (NMPlatform *platform, guint timeout_ms) { WaitForSignalData data = { 0 }; - gulong id_link, id_ip4_address, id_ip6_address, id_ip4_route, id_ip6_route; + if (!platform) + platform = NM_PLATFORM_GET; + data.loop = g_main_loop_new (NULL, FALSE); - id_link = g_signal_connect (NM_PLATFORM_GET, NM_PLATFORM_SIGNAL_LINK_CHANGED, G_CALLBACK (_wait_for_signal_cb), &data); - id_ip4_address = g_signal_connect (NM_PLATFORM_GET, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, G_CALLBACK (_wait_for_signal_cb), &data); - id_ip6_address = g_signal_connect (NM_PLATFORM_GET, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, G_CALLBACK (_wait_for_signal_cb), &data); - id_ip4_route = g_signal_connect (NM_PLATFORM_GET, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, G_CALLBACK (_wait_for_signal_cb), &data); - id_ip6_route = g_signal_connect (NM_PLATFORM_GET, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, G_CALLBACK (_wait_for_signal_cb), &data); + id_link = g_signal_connect (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, G_CALLBACK (_wait_for_signal_cb), &data); + id_ip4_address = g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, G_CALLBACK (_wait_for_signal_cb), &data); + id_ip6_address = g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, G_CALLBACK (_wait_for_signal_cb), &data); + id_ip4_route = g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, G_CALLBACK (_wait_for_signal_cb), &data); + id_ip6_route = g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, G_CALLBACK (_wait_for_signal_cb), &data); if (timeout_ms != 0) data.id = g_timeout_add (timeout_ms, _wait_for_signal_timeout, &data); g_main_loop_run (data.loop); - g_assert (nm_clear_g_signal_handler (NM_PLATFORM_GET, &id_link)); - g_assert (nm_clear_g_signal_handler (NM_PLATFORM_GET, &id_ip4_address)); - g_assert (nm_clear_g_signal_handler (NM_PLATFORM_GET, &id_ip6_address)); - g_assert (nm_clear_g_signal_handler (NM_PLATFORM_GET, &id_ip4_route)); - g_assert (nm_clear_g_signal_handler (NM_PLATFORM_GET, &id_ip6_route)); + g_assert (nm_clear_g_signal_handler (platform, &id_link)); + g_assert (nm_clear_g_signal_handler (platform, &id_ip4_address)); + g_assert (nm_clear_g_signal_handler (platform, &id_ip6_address)); + g_assert (nm_clear_g_signal_handler (platform, &id_ip4_route)); + g_assert (nm_clear_g_signal_handler (platform, &id_ip6_route)); if (nm_clear_g_source (&data.id)) g_assert (timeout_ms != 0 && !data.timeout); @@ -372,7 +374,7 @@ nmtstp_wait_for_signal (guint timeout_ms) } gboolean -nmtstp_wait_for_signal_until (gint64 until_ms) +nmtstp_wait_for_signal_until (NMPlatform *platform, gint64 until_ms) { gint64 now; @@ -382,19 +384,19 @@ nmtstp_wait_for_signal_until (gint64 until_ms) if (until_ms < now) return FALSE; - if (nmtstp_wait_for_signal (MAX (1, until_ms - now))) + if (nmtstp_wait_for_signal (platform, MAX (1, until_ms - now))) return TRUE; } } const NMPlatformLink * -nmtstp_wait_for_link (const char *ifname, NMLinkType expected_link_type, guint timeout_ms) +nmtstp_wait_for_link (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, guint timeout_ms) { - return nmtstp_wait_for_link_until (ifname, expected_link_type, nm_utils_get_monotonic_timestamp_ms () + timeout_ms); + return nmtstp_wait_for_link_until (platform, ifname, expected_link_type, nm_utils_get_monotonic_timestamp_ms () + timeout_ms); } const NMPlatformLink * -nmtstp_wait_for_link_until (const char *ifname, NMLinkType expected_link_type, gint64 until_ms) +nmtstp_wait_for_link_until (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, gint64 until_ms) { const NMPlatformLink *plink; gint64 now; @@ -402,7 +404,7 @@ nmtstp_wait_for_link_until (const char *ifname, NMLinkType expected_link_type, g while (TRUE) { now = nm_utils_get_monotonic_timestamp_ms (); - plink = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, ifname); + plink = nm_platform_link_get_by_ifname (platform ?: NM_PLATFORM_GET, ifname); if ( plink && (expected_link_type == NM_LINK_TYPE_NONE || plink->type == expected_link_type)) return plink; @@ -410,22 +412,22 @@ nmtstp_wait_for_link_until (const char *ifname, NMLinkType expected_link_type, g if (until_ms < now) return NULL; - nmtstp_wait_for_signal (MAX (1, until_ms - now)); + nmtstp_wait_for_signal (platform, MAX (1, until_ms - now)); } } const NMPlatformLink * -nmtstp_assert_wait_for_link (const char *ifname, NMLinkType expected_link_type, guint timeout_ms) +nmtstp_assert_wait_for_link (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, guint timeout_ms) { - return nmtstp_assert_wait_for_link_until (ifname, expected_link_type, nm_utils_get_monotonic_timestamp_ms () + timeout_ms); + return nmtstp_assert_wait_for_link_until (platform, ifname, expected_link_type, nm_utils_get_monotonic_timestamp_ms () + timeout_ms); } const NMPlatformLink * -nmtstp_assert_wait_for_link_until (const char *ifname, NMLinkType expected_link_type, gint64 until_ms) +nmtstp_assert_wait_for_link_until (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, gint64 until_ms) { const NMPlatformLink *plink; - plink = nmtstp_wait_for_link_until (ifname, expected_link_type, until_ms); + plink = nmtstp_wait_for_link_until (platform, ifname, expected_link_type, until_ms); g_assert (plink); return plink; } @@ -563,8 +565,8 @@ _ip_address_add (gboolean external_command, const NMIPAddr *peer_address, guint32 lifetime, guint32 preferred, - const char *label, - guint32 flags) + guint32 flags, + const char *label) { gint64 end_time; @@ -626,7 +628,6 @@ _ip_address_add (gboolean external_command, gboolean success; if (is_v4) { - g_assert (flags == 0); success = nm_platform_ip4_address_add (NM_PLATFORM_GET, ifindex, address->addr4, @@ -634,6 +635,7 @@ _ip_address_add (gboolean external_command, peer_address->addr4, lifetime, preferred, + flags, label); } else { g_assert (label == NULL); @@ -686,20 +688,20 @@ _ip_address_add (gboolean external_command, /* for internal command, we expect not to reach this line.*/ g_assert (external_command); - g_assert (nmtstp_wait_for_signal_until (end_time)); + g_assert (nmtstp_wait_for_signal_until (NM_PLATFORM_GET, end_time)); } while (TRUE); } -#define _assert_pllink(success, pllink, name, type) \ +#define _assert_pllink(platform, success, pllink, name, type) \ G_STMT_START { \ const NMPlatformLink *_pllink = (pllink); \ \ if ((success)) { \ g_assert (_pllink); \ - g_assert (_pllink == nmtstp_link_get_typed (_pllink->ifindex, (name), (type))); \ + g_assert (_pllink == nmtstp_link_get_typed (platform, _pllink->ifindex, (name), (type))); \ } else { \ g_assert (!_pllink); \ - g_assert (!nmtstp_link_get (0, (name))); \ + g_assert (!nmtstp_link_get (platform, 0, (name))); \ } \ } G_STMT_END @@ -718,12 +720,12 @@ nmtstp_link_dummy_add (gboolean external_command, success = !nmtstp_run_command ("ip link add %s type dummy", name); if (success) - pllink = nmtstp_assert_wait_for_link (name, NM_LINK_TYPE_DUMMY, 100); + pllink = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, name, NM_LINK_TYPE_DUMMY, 100); } else success = nm_platform_link_dummy_add (NM_PLATFORM_GET, name, &pllink) == NM_PLATFORM_ERROR_SUCCESS; g_assert (success); - _assert_pllink (success, pllink, name, NM_LINK_TYPE_DUMMY); + _assert_pllink (NM_PLATFORM_GET, success, pllink, name, NM_LINK_TYPE_DUMMY); return pllink; } @@ -755,11 +757,11 @@ nmtstp_link_gre_add (gboolean external_command, lnk->tos, lnk->path_mtu_discovery ? "pmtudisc" : "nopmtudisc"); if (success) - pllink = nmtstp_assert_wait_for_link (name, NM_LINK_TYPE_GRE, 100); + pllink = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, name, NM_LINK_TYPE_GRE, 100); } else success = nm_platform_link_gre_add (NM_PLATFORM_GET, name, lnk, &pllink) == NM_PLATFORM_ERROR_SUCCESS; - _assert_pllink (success, pllink, name, NM_LINK_TYPE_GRE); + _assert_pllink (NM_PLATFORM_GET, success, pllink, name, NM_LINK_TYPE_GRE); return pllink; } @@ -806,11 +808,11 @@ nmtstp_link_ip6tnl_add (gboolean external_command, lnk->encap_limit, lnk->flow_label); if (success) - pllink = nmtstp_assert_wait_for_link (name, NM_LINK_TYPE_IP6TNL, 100); + pllink = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, name, NM_LINK_TYPE_IP6TNL, 100); } else success = nm_platform_link_ip6tnl_add (NM_PLATFORM_GET, name, lnk, &pllink) == NM_PLATFORM_ERROR_SUCCESS; - _assert_pllink (success, pllink, name, NM_LINK_TYPE_IP6TNL); + _assert_pllink (NM_PLATFORM_GET, success, pllink, name, NM_LINK_TYPE_IP6TNL); return pllink; } @@ -843,11 +845,11 @@ nmtstp_link_ipip_add (gboolean external_command, lnk->tos, lnk->path_mtu_discovery ? "pmtudisc" : "nopmtudisc"); if (success) - pllink = nmtstp_assert_wait_for_link (name, NM_LINK_TYPE_IPIP, 100); + pllink = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, name, NM_LINK_TYPE_IPIP, 100); } else success = nm_platform_link_ipip_add (NM_PLATFORM_GET, name, lnk, &pllink) == NM_PLATFORM_ERROR_SUCCESS; - _assert_pllink (success, pllink, name, NM_LINK_TYPE_IPIP); + _assert_pllink (NM_PLATFORM_GET, success, pllink, name, NM_LINK_TYPE_IPIP); return pllink; } @@ -888,11 +890,11 @@ nmtstp_link_macvlan_add (gboolean external_command, modes[lnk->mode], lnk->no_promisc ? "nopromisc" : ""); if (success) - pllink = nmtstp_assert_wait_for_link (name, link_type, 100); + pllink = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, name, link_type, 100); } else success = nm_platform_link_macvlan_add (NM_PLATFORM_GET, name, parent, lnk, &pllink) == NM_PLATFORM_ERROR_SUCCESS; - _assert_pllink (success, pllink, name, link_type); + _assert_pllink (NM_PLATFORM_GET, success, pllink, name, link_type); return pllink; } @@ -930,11 +932,11 @@ nmtstp_link_sit_add (gboolean external_command, lnk->tos, lnk->path_mtu_discovery ? "pmtudisc" : "nopmtudisc"); if (success) - pllink = nmtstp_assert_wait_for_link (name, NM_LINK_TYPE_SIT, 100); + pllink = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, name, NM_LINK_TYPE_SIT, 100); } else success = nm_platform_link_sit_add (NM_PLATFORM_GET, name, lnk, &pllink) == NM_PLATFORM_ERROR_SUCCESS; - _assert_pllink (success, pllink, name, NM_LINK_TYPE_SIT); + _assert_pllink (NM_PLATFORM_GET, success, pllink, name, NM_LINK_TYPE_SIT); return pllink; } @@ -983,7 +985,7 @@ nmtstp_link_vxlan_add (gboolean external_command, /* Older versions of iproute2 don't support adding vxlan devices. * On failure, fallback to using platform code. */ if (err == 0) - pllink = nmtstp_assert_wait_for_link (name, NM_LINK_TYPE_VXLAN, 100); + pllink = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, name, NM_LINK_TYPE_VXLAN, 100); else _LOGI ("Adding vxlan device via iproute2 failed. Assume iproute2 is not up to the task."); } @@ -1006,6 +1008,7 @@ nmtstp_ip4_address_add (gboolean external_command, in_addr_t peer_address, guint32 lifetime, guint32 preferred, + guint32 flags, const char *label) { _ip_address_add (external_command, @@ -1016,8 +1019,8 @@ nmtstp_ip4_address_add (gboolean external_command, (NMIPAddr *) &peer_address, lifetime, preferred, - label, - 0); + flags, + label); } void @@ -1038,8 +1041,8 @@ nmtstp_ip6_address_add (gboolean external_command, (NMIPAddr *) &peer_address, lifetime, preferred, - NULL, - flags); + flags, + NULL); } static void @@ -1127,7 +1130,7 @@ _ip_address_del (gboolean external_command, /* for internal command, we expect not to reach this line.*/ g_assert (external_command); - g_assert (nmtstp_wait_for_signal_until (end_time)); + g_assert (nmtstp_wait_for_signal_until (NM_PLATFORM_GET, end_time)); } while (TRUE); } @@ -1161,14 +1164,18 @@ nmtstp_ip6_address_del (gboolean external_command, } const NMPlatformLink * -nmtstp_link_get_typed (int ifindex, +nmtstp_link_get_typed (NMPlatform *platform, + int ifindex, const char *name, NMLinkType link_type) { const NMPlatformLink *pllink = NULL; + if (!platform) + platform = NM_PLATFORM_GET; + if (ifindex > 0) { - pllink = nm_platform_link_get (NM_PLATFORM_GET, ifindex); + pllink = nm_platform_link_get (platform, ifindex); if (pllink) { g_assert_cmpint (pllink->ifindex, ==, ifindex); @@ -1176,12 +1183,12 @@ nmtstp_link_get_typed (int ifindex, g_assert_cmpstr (name, ==, pllink->name); } else { if (name) - g_assert (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, name)); + g_assert (!nm_platform_link_get_by_ifname (platform, name)); } } else { g_assert (name); - pllink = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, name); + pllink = nm_platform_link_get_by_ifname (platform, name); if (pllink) g_assert_cmpstr (name, ==, pllink->name); @@ -1196,10 +1203,11 @@ nmtstp_link_get_typed (int ifindex, } const NMPlatformLink * -nmtstp_link_get (int ifindex, +nmtstp_link_get (NMPlatform *platform, + int ifindex, const char *name) { - return nmtstp_link_get_typed (ifindex, name, NM_LINK_TYPE_NONE); + return nmtstp_link_get_typed (platform, ifindex, name, NM_LINK_TYPE_NONE); } void @@ -1212,7 +1220,7 @@ nmtstp_link_del (gboolean external_command, gboolean success; gs_free char *name_copy = NULL; - pllink = nmtstp_link_get (ifindex, name); + pllink = nmtstp_link_get (NM_PLATFORM_GET, ifindex, name); g_assert (pllink); @@ -1242,7 +1250,7 @@ nmtstp_link_del (gboolean external_command, /* for internal command, we expect not to reach this line.*/ g_assert (external_command); - g_assert (nmtstp_wait_for_signal_until (end_time)); + g_assert (nmtstp_wait_for_signal_until (NM_PLATFORM_GET, end_time)); } while (TRUE); } @@ -1288,7 +1296,7 @@ nmtstp_link_set_updown (gboolean external_command, /* for internal command, we expect not to reach this line.*/ g_assert (external_command); - g_assert (nmtstp_wait_for_signal_until (end_time)); + g_assert (nmtstp_wait_for_signal_until (NM_PLATFORM_GET, end_time)); } while (TRUE); } diff --git a/src/platform/tests/test-common.h b/src/platform/tests/test-common.h index 0281d3c5..82561193 100644 --- a/src/platform/tests/test-common.h +++ b/src/platform/tests/test-common.h @@ -91,13 +91,13 @@ void link_callback (NMPlatform *platform, NMPObjectType obj_type, int ifindex, N int nmtstp_run_command (const char *format, ...) __attribute__((__format__ (__printf__, 1, 2))); #define nmtstp_run_command_check(...) do { g_assert_cmpint (nmtstp_run_command (__VA_ARGS__), ==, 0); } while (0) -gboolean nmtstp_wait_for_signal (guint timeout_ms); -gboolean nmtstp_wait_for_signal_until (gint64 until_ms); -const NMPlatformLink *nmtstp_wait_for_link (const char *ifname, NMLinkType expected_link_type, guint timeout_ms); -const NMPlatformLink *nmtstp_wait_for_link_until (const char *ifname, NMLinkType expected_link_type, gint64 until_ms); +gboolean nmtstp_wait_for_signal (NMPlatform *platform, guint timeout_ms); +gboolean nmtstp_wait_for_signal_until (NMPlatform *platform, gint64 until_ms); +const NMPlatformLink *nmtstp_wait_for_link (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, guint timeout_ms); +const NMPlatformLink *nmtstp_wait_for_link_until (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, gint64 until_ms); -const NMPlatformLink *nmtstp_assert_wait_for_link (const char *ifname, NMLinkType expected_link_type, guint timeout_ms); -const NMPlatformLink *nmtstp_assert_wait_for_link_until (const char *ifname, NMLinkType expected_link_type, gint64 until_ms); +const NMPlatformLink *nmtstp_assert_wait_for_link (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, guint timeout_ms); +const NMPlatformLink *nmtstp_assert_wait_for_link_until (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, gint64 until_ms); int nmtstp_run_command_check_external_global (void); gboolean nmtstp_run_command_check_external (int external_command); @@ -117,6 +117,7 @@ void nmtstp_ip4_address_add (gboolean external_command, in_addr_t peer_address, guint32 lifetime, guint32 preferred, + guint32 flags, const char *label); void nmtstp_ip6_address_add (gboolean external_command, int ifindex, @@ -125,7 +126,7 @@ void nmtstp_ip6_address_add (gboolean external_command, struct in6_addr peer_address, guint32 lifetime, guint32 preferred, - guint flags); + guint32 flags); void nmtstp_ip4_address_del (gboolean external_command, int ifindex, in_addr_t address, @@ -136,8 +137,8 @@ void nmtstp_ip6_address_del (gboolean external_command, struct in6_addr address, int plen); -const NMPlatformLink *nmtstp_link_get_typed (int ifindex, const char *name, NMLinkType link_type); -const NMPlatformLink *nmtstp_link_get (int ifindex, const char *name); +const NMPlatformLink *nmtstp_link_get_typed (NMPlatform *platform, int ifindex, const char *name, NMLinkType link_type); +const NMPlatformLink *nmtstp_link_get (NMPlatform *platform, int ifindex, const char *name); void nmtstp_link_set_updown (gboolean external_command, int ifindex, diff --git a/src/platform/tests/test-general.c b/src/platform/tests/test-general.c index f342e565..66f72fa5 100644 --- a/src/platform/tests/test-general.c +++ b/src/platform/tests/test-general.c @@ -18,12 +18,12 @@ * Copyright (C) 2015 Red Hat, Inc. */ -#include "nm-platform-utils.h" +#include "nm-default.h" #include <linux/rtnetlink.h> +#include "nm-platform-utils.h" #include "nm-linux-platform.h" -#include "nm-default.h" #include "nm-test-utils.h" diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index 3fa5ad50..94695edc 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -21,8 +21,13 @@ #include "nm-default.h" #include <sched.h> +#include <sys/mount.h> +#include <sys/stat.h> +#include <sys/types.h> #include "nmp-object.h" +#include "nmp-netns.h" +#include "nm-platform-utils.h" #include "test-common.h" #include "nm-test-utils.h" @@ -40,6 +45,9 @@ #define VLAN_FLAGS 0 #define MTU 1357 +#define _ADD_DUMMY(platform, name) \ + g_assert_cmpint (nm_platform_link_dummy_add ((platform), (name), NULL), ==, NM_PLATFORM_ERROR_SUCCESS) + static void test_bogus(void) { @@ -52,16 +60,16 @@ test_bogus(void) g_assert (!nm_platform_link_get_type (NM_PLATFORM_GET, BOGUS_IFINDEX)); g_assert (!nm_platform_link_get_type_name (NM_PLATFORM_GET, BOGUS_IFINDEX)); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*failure changing link: *"); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*failure changing link: *"); g_assert (!nm_platform_link_set_up (NM_PLATFORM_GET, BOGUS_IFINDEX, NULL)); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*failure changing link: *"); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*failure changing link: *"); g_assert (!nm_platform_link_set_down (NM_PLATFORM_GET, BOGUS_IFINDEX)); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*failure changing link: *"); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*failure changing link: *"); g_assert (!nm_platform_link_set_arp (NM_PLATFORM_GET, BOGUS_IFINDEX)); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*failure changing link: *"); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*failure changing link: *"); g_assert (!nm_platform_link_set_noarp (NM_PLATFORM_GET, BOGUS_IFINDEX)); g_assert (!nm_platform_link_is_up (NM_PLATFORM_GET, BOGUS_IFINDEX)); @@ -72,7 +80,7 @@ test_bogus(void) g_assert (!addrlen); g_assert (!nm_platform_link_get_address (NM_PLATFORM_GET, BOGUS_IFINDEX, NULL)); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*failure changing link: *"); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*failure changing link: *"); g_assert (!nm_platform_link_set_mtu (NM_PLATFORM_GET, BOGUS_IFINDEX, MTU)); g_assert (!nm_platform_link_get_mtu (NM_PLATFORM_GET, BOGUS_IFINDEX)); @@ -690,7 +698,7 @@ test_software_detect (gconstpointer user_data) const gboolean ext = test_data->external_command; nmtstp_run_command_check ("ip link add %s type dummy", PARENT_NAME); - ifindex_parent = nmtstp_assert_wait_for_link (PARENT_NAME, NM_LINK_TYPE_DUMMY, 100)->ifindex; + ifindex_parent = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, PARENT_NAME, NM_LINK_TYPE_DUMMY, 100)->ifindex; switch (test_data->link_type) { case NM_LINK_TYPE_GRE: { @@ -852,7 +860,7 @@ test_software_detect (gconstpointer user_data) g_assert_not_reached (); } - ifindex = nmtstp_assert_wait_for_link (DEVICE_NAME, test_data->link_type, 100)->ifindex; + ifindex = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, DEVICE_NAME, test_data->link_type, 100)->ifindex; nmtstp_link_set_updown (-1, ifindex_parent, TRUE); @@ -1137,10 +1145,10 @@ test_vlan_set_xgress (void) int ifindex, ifindex_parent; nmtstp_run_command_check ("ip link add %s type dummy", PARENT_NAME); - ifindex_parent = nmtstp_assert_wait_for_link (PARENT_NAME, NM_LINK_TYPE_DUMMY, 100)->ifindex; + ifindex_parent = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, PARENT_NAME, NM_LINK_TYPE_DUMMY, 100)->ifindex; nmtstp_run_command_check ("ip link add name %s link %s type vlan id 1245", DEVICE_NAME, PARENT_NAME); - ifindex = nmtstp_assert_wait_for_link (DEVICE_NAME, NM_LINK_TYPE_VLAN, 100)->ifindex; + ifindex = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, DEVICE_NAME, NM_LINK_TYPE_VLAN, 100)->ifindex; /* ingress-qos-map */ @@ -1662,7 +1670,7 @@ test_create_many_links (gconstpointer user_data) guint n_devices = GPOINTER_TO_UINT (user_data); if (n_devices > 100 && nmtst_test_quick ()) { - g_print ("Skipping test: don't run long running test %s (NMTST_DEBUG=slow)\n", str_if_set (g_get_prgname (), "test-link-linux")); + g_print ("Skipping test: don't run long running test %s (NMTST_DEBUG=slow)\n", g_get_prgname () ?: "test-link-linux"); g_test_skip ("Skip long running test"); return; } @@ -1685,8 +1693,8 @@ test_nl_bugs_veth (void) /* create veth pair. */ nmtstp_run_command_check ("ip link add dev %s type veth peer name %s", IFACE_VETH0, IFACE_VETH1); - ifindex_veth0 = nmtstp_assert_wait_for_link (IFACE_VETH0, NM_LINK_TYPE_VETH, 100)->ifindex; - ifindex_veth1 = nmtstp_assert_wait_for_link (IFACE_VETH1, NM_LINK_TYPE_VETH, 100)->ifindex; + ifindex_veth0 = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, IFACE_VETH0, NM_LINK_TYPE_VETH, 100)->ifindex; + ifindex_veth1 = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, IFACE_VETH1, NM_LINK_TYPE_VETH, 100)->ifindex; /* assert that nm_platform_link_veth_get_properties() returns the expected peer ifindexes. */ g_assert (nm_platform_link_veth_get_properties (NM_PLATFORM_GET, ifindex_veth0, &i)); @@ -1722,7 +1730,7 @@ test_nl_bugs_veth (void) nmtstp_run_command_check ("ip link set %s netns %ld", IFACE_VETH1, (long) nmtstp_namespace_handle_get_pid (ns_handle)); NMTST_WAIT_ASSERT (100, { - nmtstp_wait_for_signal (50); + nmtstp_wait_for_signal (NM_PLATFORM_GET, 50); nm_platform_process_events (NM_PLATFORM_GET); pllink_veth1 = nm_platform_link_get (NM_PLATFORM_GET, ifindex_veth1); @@ -1736,8 +1744,8 @@ test_nl_bugs_veth (void) out: nmtstp_link_del (-1, ifindex_veth0, IFACE_VETH0); - g_assert (!nmtstp_link_get (ifindex_veth0, IFACE_VETH0)); - g_assert (!nmtstp_link_get (ifindex_veth1, IFACE_VETH1)); + g_assert (!nmtstp_link_get (NM_PLATFORM_GET, ifindex_veth0, IFACE_VETH0)); + g_assert (!nmtstp_link_get (NM_PLATFORM_GET, ifindex_veth1, IFACE_VETH1)); nmtstp_namespace_handle_release (ns_handle); } @@ -1755,16 +1763,16 @@ test_nl_bugs_spuroius_newlink (void) /* see https://bugzilla.redhat.com/show_bug.cgi?id=1285719 */ nmtstp_run_command_check ("ip link add %s type dummy", IFACE_DUMMY0); - ifindex_dummy0 = nmtstp_assert_wait_for_link (IFACE_DUMMY0, NM_LINK_TYPE_DUMMY, 100)->ifindex; + ifindex_dummy0 = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, IFACE_DUMMY0, NM_LINK_TYPE_DUMMY, 100)->ifindex; nmtstp_run_command_check ("ip link add %s type bond", IFACE_BOND0); - ifindex_bond0 = nmtstp_assert_wait_for_link (IFACE_BOND0, NM_LINK_TYPE_BOND, 100)->ifindex; + ifindex_bond0 = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, IFACE_BOND0, NM_LINK_TYPE_BOND, 100)->ifindex; nmtstp_link_set_updown (-1, ifindex_bond0, TRUE); nmtstp_run_command_check ("ip link set %s master %s", IFACE_DUMMY0, IFACE_BOND0); NMTST_WAIT_ASSERT (100, { - nmtstp_wait_for_signal (50); + nmtstp_wait_for_signal (NM_PLATFORM_GET, 50); pllink = nm_platform_link_get (NM_PLATFORM_GET, ifindex_dummy0); g_assert (pllink); @@ -1775,7 +1783,7 @@ test_nl_bugs_spuroius_newlink (void) nmtstp_run_command_check ("ip link del %s", IFACE_BOND0); wait_for_settle = TRUE; - nmtstp_wait_for_signal (50); + nmtstp_wait_for_signal (NM_PLATFORM_GET, 50); again: nm_platform_process_events (NM_PLATFORM_GET); pllink = nm_platform_link_get (NM_PLATFORM_GET, ifindex_bond0); @@ -1783,11 +1791,11 @@ again: if (wait_for_settle) { wait_for_settle = FALSE; - NMTST_WAIT (300, { nmtstp_wait_for_signal (50); }); + NMTST_WAIT (300, { nmtstp_wait_for_signal (NM_PLATFORM_GET, 50); }); goto again; } - g_assert (!nmtstp_link_get (ifindex_bond0, IFACE_BOND0)); + g_assert (!nmtstp_link_get (NM_PLATFORM_GET, ifindex_bond0, IFACE_BOND0)); nmtstp_link_del (-1, ifindex_dummy0, IFACE_DUMMY0); } @@ -1805,16 +1813,16 @@ test_nl_bugs_spuroius_dellink (void) /* see https://bugzilla.redhat.com/show_bug.cgi?id=1285719 */ nmtstp_run_command_check ("ip link add %s type dummy", IFACE_DUMMY0); - ifindex_dummy0 = nmtstp_assert_wait_for_link (IFACE_DUMMY0, NM_LINK_TYPE_DUMMY, 100)->ifindex; + ifindex_dummy0 = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, IFACE_DUMMY0, NM_LINK_TYPE_DUMMY, 100)->ifindex; nmtstp_run_command_check ("ip link add %s type bridge", IFACE_BRIDGE0); - ifindex_bridge0 = nmtstp_assert_wait_for_link (IFACE_BRIDGE0, NM_LINK_TYPE_BRIDGE, 100)->ifindex; + ifindex_bridge0 = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, IFACE_BRIDGE0, NM_LINK_TYPE_BRIDGE, 100)->ifindex; nmtstp_link_set_updown (-1, ifindex_bridge0, TRUE); nmtstp_run_command_check ("ip link set %s master %s", IFACE_DUMMY0, IFACE_BRIDGE0); NMTST_WAIT_ASSERT (100, { - nmtstp_wait_for_signal (50); + nmtstp_wait_for_signal (NM_PLATFORM_GET, 50); pllink = nm_platform_link_get (NM_PLATFORM_GET, ifindex_dummy0); g_assert (pllink); @@ -1827,7 +1835,7 @@ test_nl_bugs_spuroius_dellink (void) nmtstp_run_command_check ("ip link set %s nomaster", IFACE_DUMMY0); wait_for_settle = TRUE; - nmtstp_wait_for_signal (50); + nmtstp_wait_for_signal (NM_PLATFORM_GET, 50); again: nm_platform_process_events (NM_PLATFORM_GET); pllink = nm_platform_link_get (NM_PLATFORM_GET, ifindex_bridge0); @@ -1838,7 +1846,7 @@ again: if (wait_for_settle) { wait_for_settle = FALSE; - NMTST_WAIT (300, { nmtstp_wait_for_signal (50); }); + NMTST_WAIT (300, { nmtstp_wait_for_signal (NM_PLATFORM_GET, 50); }); goto again; } @@ -1846,6 +1854,442 @@ again: nmtstp_link_del (-1, ifindex_dummy0, IFACE_DUMMY0); } +/******************************************************************/ + +static void +_test_netns_setup (gpointer fixture, gconstpointer test_data) +{ + /* the singleton platform instance has netns support disabled. + * Destroy the instance before the test and re-create it afterwards. */ + g_object_unref (nm_platform_get ()); +} + +static void +_test_netns_teardown (gpointer fixture, gconstpointer test_data) +{ + /* re-create platform instance */ + SETUP (); +} + +static NMPlatform * +_test_netns_create_platform (void) +{ + NMPNetns *netns; + NMPlatform *platform; + + netns = nmp_netns_new (); + g_assert (NMP_IS_NETNS (netns)); + + platform = g_object_new (NM_TYPE_LINUX_PLATFORM, NM_PLATFORM_NETNS_SUPPORT, TRUE, NULL); + g_assert (NM_IS_LINUX_PLATFORM (platform)); + + nmp_netns_pop (netns); + g_object_unref (netns); + + return platform; +} + +static gboolean +_test_netns_check_skip (void) +{ + static int support = -1; + static int support_errsv = 0; + NMPNetns *netns; + + netns = nmp_netns_get_current (); + if (!netns) { + g_test_skip ("No netns support"); + return TRUE; + } + + g_assert (nmp_netns_get_fd_net (netns) > 0); + + if (support == -1) { + support = (setns (nmp_netns_get_fd_net (netns), CLONE_NEWNET) == 0); + if (!support) + support_errsv = errno; + } + if (!support) { + _LOGD ("setns() failed with \"%s\". This indicates missing support (valgrind?)", g_strerror (support_errsv)); + g_test_skip ("No netns support (setns failed)"); + return TRUE; + } + return FALSE; +} + +/******************************************************************/ + +static void +test_netns_general (gpointer fixture, gconstpointer test_data) +{ + gs_unref_object NMPlatform *platform_1 = NULL; + gs_unref_object NMPlatform *platform_2 = NULL; + NMPNetns *netns_tmp; + char sbuf[100]; + int i, j, k; + gboolean ethtool_support; + + if (_test_netns_check_skip ()) + return; + + platform_1 = g_object_new (NM_TYPE_LINUX_PLATFORM, NM_PLATFORM_NETNS_SUPPORT, TRUE, NULL); + platform_2 = _test_netns_create_platform (); + + /* add some dummy devices. The "other-*" devices are there to bump the ifindex */ + for (k = 0; k < 2; k++) { + NMPlatform *p = (k == 0 ? platform_1 : platform_2); + const char *id = (k == 0 ? "a" : "b"); + + for (i = 0, j = nmtst_get_rand_int () % 5; i < j; i++) + _ADD_DUMMY (p, nm_sprintf_buf (sbuf, "other-a-%s-%02d", id, i)); + + _ADD_DUMMY (p, "dummy1_"); + + for (i = 0, j = nmtst_get_rand_int () % 5; i < j; i++) + _ADD_DUMMY (p, nm_sprintf_buf (sbuf, "other-b-%s-%02d", id, i)); + + _ADD_DUMMY (p, nm_sprintf_buf (sbuf, "dummy2%s", id)); + + for (i = 0, j = nmtst_get_rand_int () % 5; i < j; i++) + _ADD_DUMMY (p, nm_sprintf_buf (sbuf, "other-c-%s-%02d", id, i)); + } + + g_assert_cmpstr (nm_platform_sysctl_get (platform_1, "/sys/devices/virtual/net/dummy1_/ifindex"), ==, nm_sprintf_buf (sbuf, "%d", nmtstp_link_get_typed (platform_1, 0, "dummy1_", NM_LINK_TYPE_DUMMY)->ifindex)); + g_assert_cmpstr (nm_platform_sysctl_get (platform_1, "/sys/devices/virtual/net/dummy2a/ifindex"), ==, nm_sprintf_buf (sbuf, "%d", nmtstp_link_get_typed (platform_1, 0, "dummy2a", NM_LINK_TYPE_DUMMY)->ifindex)); + g_assert_cmpstr (nm_platform_sysctl_get (platform_1, "/sys/devices/virtual/net/dummy2b/ifindex"), ==, NULL); + + g_assert_cmpstr (nm_platform_sysctl_get (platform_2, "/sys/devices/virtual/net/dummy1_/ifindex"), ==, nm_sprintf_buf (sbuf, "%d", nmtstp_link_get_typed (platform_2, 0, "dummy1_", NM_LINK_TYPE_DUMMY)->ifindex)); + g_assert_cmpstr (nm_platform_sysctl_get (platform_2, "/sys/devices/virtual/net/dummy2a/ifindex"), ==, NULL); + g_assert_cmpstr (nm_platform_sysctl_get (platform_2, "/sys/devices/virtual/net/dummy2b/ifindex"), ==, nm_sprintf_buf (sbuf, "%d", nmtstp_link_get_typed (platform_2, 0, "dummy2b", NM_LINK_TYPE_DUMMY)->ifindex)); + + for (i = 0; i < 10; i++) { + NMPlatform *pl; + const char *path; + + j = nmtst_get_rand_int () % 2; + + if (nmtst_get_rand_int () % 2) { + pl = platform_1; + if (nmtst_get_rand_int () % 2) + path = "/proc/sys/net/ipv6/conf/dummy1_/disable_ipv6"; + else + path = "/proc/sys/net/ipv6/conf/dummy2a/disable_ipv6"; + } else { + pl = platform_2; + if (nmtst_get_rand_int () % 2) + path = "/proc/sys/net/ipv6/conf/dummy1_/disable_ipv6"; + else + path = "/proc/sys/net/ipv6/conf/dummy2b/disable_ipv6"; + } + g_assert (nm_platform_sysctl_set (pl, path, nm_sprintf_buf (sbuf, "%d", j))); + g_assert_cmpstr (nm_platform_sysctl_get (pl, path), ==, nm_sprintf_buf (sbuf, "%d", j)); + } + g_assert_cmpstr (nm_platform_sysctl_get (platform_1, "/proc/sys/net/ipv6/conf/dummy2b/disable_ipv6"), ==, NULL); + g_assert_cmpstr (nm_platform_sysctl_get (platform_2, "/proc/sys/net/ipv6/conf/dummy2a/disable_ipv6"), ==, NULL); + + /* older kernels (Ubuntu 12.04) don't support ethtool -i for dummy devices. Work around that and + * skip asserts that are known to fail. */ + ethtool_support = nmtstp_run_command ("ethtool -i dummy1_ > /dev/null") == 0; + if (ethtool_support) { + g_assert ( nmp_utils_ethtool_get_driver_info ("dummy1_", NULL, NULL, NULL)); + g_assert ( nmp_utils_ethtool_get_driver_info ("dummy2a", NULL, NULL, NULL)); + g_assert (!nmp_utils_ethtool_get_driver_info ("dummy2b", NULL, NULL, NULL)); + g_assert_cmpint (nmtstp_run_command ("ethtool -i dummy1_ > /dev/null"), ==, 0); + g_assert_cmpint (nmtstp_run_command ("ethtool -i dummy2a > /dev/null"), ==, 0); + g_assert_cmpint (nmtstp_run_command ("ethtool -i dummy2b 2> /dev/null"), !=, 0); + } + + g_assert (nm_platform_netns_push (platform_2, &netns_tmp)); + + if (ethtool_support) { + g_assert ( nmp_utils_ethtool_get_driver_info ("dummy1_", NULL, NULL, NULL)); + g_assert (!nmp_utils_ethtool_get_driver_info ("dummy2a", NULL, NULL, NULL)); + g_assert ( nmp_utils_ethtool_get_driver_info ("dummy2b", NULL, NULL, NULL)); + g_assert_cmpint (nmtstp_run_command ("ethtool -i dummy1_ > /dev/null"), ==, 0); + g_assert_cmpint (nmtstp_run_command ("ethtool -i dummy2a 2> /dev/null"), !=, 0); + g_assert_cmpint (nmtstp_run_command ("ethtool -i dummy2b > /dev/null"), ==, 0); + } + + nmp_netns_pop (netns_tmp); +} + +/*****************************************************************************/ + +static void +test_netns_set_netns (gpointer fixture, gconstpointer test_data) +{ + NMPlatform *platforms[3]; + gs_unref_object NMPlatform *platform_0 = NULL; + gs_unref_object NMPlatform *platform_1 = NULL; + gs_unref_object NMPlatform *platform_2 = NULL; + nm_auto_pop_netns NMPNetns *netns_pop = NULL; + int i; + + if (_test_netns_check_skip ()) + return; + + platforms[0] = platform_0 = g_object_new (NM_TYPE_LINUX_PLATFORM, NM_PLATFORM_NETNS_SUPPORT, TRUE, NULL); + platforms[1] = platform_1 = _test_netns_create_platform (); + platforms[2] = platform_2 = _test_netns_create_platform (); + + i = nmtst_get_rand_int () % 4; + if (i != 3) + g_assert (nm_platform_netns_push (platforms[i], &netns_pop)); + +#define LINK_MOVE_NAME "link-move" + g_assert (!nm_platform_link_get_by_ifname (platform_1, LINK_MOVE_NAME)); + g_assert (!nm_platform_link_get_by_ifname (platform_2, LINK_MOVE_NAME)); + _ADD_DUMMY (platform_1, LINK_MOVE_NAME); + g_assert ( nm_platform_link_get_by_ifname (platform_1, LINK_MOVE_NAME)); + g_assert (!nm_platform_link_get_by_ifname (platform_2, LINK_MOVE_NAME)); + g_assert (nm_platform_link_set_netns (platform_1, + nm_platform_link_get_by_ifname (platform_1, LINK_MOVE_NAME)->ifindex, + nmp_netns_get_fd_net (nm_platform_netns_get (platform_2)))); + g_assert (!nm_platform_link_get_by_ifname (platform_1, LINK_MOVE_NAME)); + g_assert (!nm_platform_link_get_by_ifname (platform_2, LINK_MOVE_NAME)); + nmtstp_assert_wait_for_link (platform_2, LINK_MOVE_NAME, NM_LINK_TYPE_DUMMY, 100); + g_assert (!nm_platform_link_get_by_ifname (platform_1, LINK_MOVE_NAME)); + g_assert ( nm_platform_link_get_by_ifname (platform_2, LINK_MOVE_NAME)); +} + +/*****************************************************************************/ + +static char * +_get_current_namespace_id (int ns_type) +{ + const char *p; + GError *error = NULL; + char *id; + + switch (ns_type) { + case CLONE_NEWNET: + p = "/proc/self/ns/net"; + break; + case CLONE_NEWNS: + p = "/proc/self/ns/mnt"; + break; + default: + g_assert_not_reached (); + } + + id = g_file_read_link (p, &error); + g_assert_no_error (error); + g_assert (id); + return id; +} + +static char * +_get_sysctl_value (const char *path) +{ + char *data = NULL; + gs_free_error GError *error = NULL; + + if (!g_file_get_contents (path, &data, NULL, &error)) { + nmtst_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_NOENT, NULL); + g_assert (!data); + } else { + g_assert_no_error (error); + g_assert (data); + g_strstrip (data); + } + return data; +} + +static void +test_netns_push (gpointer fixture, gconstpointer test_data) +{ + gs_unref_object NMPlatform *platform_0 = NULL; + gs_unref_object NMPlatform *platform_1 = NULL; + gs_unref_object NMPlatform *platform_2 = NULL; + nm_auto_pop_netns NMPNetns *netns_pop = NULL; + gs_unref_ptrarray GPtrArray *device_names = g_ptr_array_new_with_free_func (g_free); + int i, j; + const int ns_types_list[] = { CLONE_NEWNET, CLONE_NEWNS, CLONE_NEWNET | CLONE_NEWNS }; + const int ns_types_test[] = { CLONE_NEWNET, CLONE_NEWNS }; + typedef struct { + NMPlatform *platform; + const char *device_name; + const char *sysctl_path; + const char *sysctl_value; + const char *ns_net; + const char *ns_mnt; + } PlatformData; + PlatformData pl[3] = { }; + PlatformData *pl_base; + struct { + PlatformData *pl; + int ns_types; + } stack[6] = { }; + int nstack; + + if (_test_netns_check_skip ()) + return; + + pl[0].platform = platform_0 = g_object_new (NM_TYPE_LINUX_PLATFORM, NM_PLATFORM_NETNS_SUPPORT, TRUE, NULL); + pl[1].platform = platform_1 = _test_netns_create_platform (); + pl[2].platform = platform_2 = _test_netns_create_platform (); + + pl_base = &pl[0]; + i = nmtst_get_rand_int () % (G_N_ELEMENTS (pl) + 1); + if (i < G_N_ELEMENTS (pl)) { + pl_base = &pl[i]; + g_assert (nm_platform_netns_push (pl[i].platform, &netns_pop)); + } + + for (i = 0; i < G_N_ELEMENTS (pl); i++) { + nm_auto_pop_netns NMPNetns *netns_free = NULL; + char *tmp; + + g_assert (nm_platform_netns_push (pl[i].platform, &netns_free)); + + tmp = g_strdup_printf ("nmtst-dev-%d", i); + g_ptr_array_add (device_names, tmp); + pl[i].device_name = tmp; + + tmp = g_strdup_printf ("/proc/sys/net/ipv6/conf/%s/disable_ipv6", pl[i].device_name); + g_ptr_array_add (device_names, tmp); + pl[i].sysctl_path = tmp; + + pl[i].sysctl_value = nmtst_get_rand_int () % 2 ? "1" : "0"; + + _ADD_DUMMY (pl[i].platform, pl[i].device_name); + + g_assert (nm_platform_sysctl_set (pl[i].platform, pl[i].sysctl_path, pl[i].sysctl_value)); + + tmp = _get_current_namespace_id (CLONE_NEWNET); + g_ptr_array_add (device_names, tmp); + pl[i].ns_net = tmp; + + tmp = _get_current_namespace_id (CLONE_NEWNS); + g_ptr_array_add (device_names, tmp); + pl[i].ns_mnt = tmp; + } + + nstack = nmtst_get_rand_int () % (G_N_ELEMENTS (stack) + 1); + for (i = 0; i < nstack; i++) { + stack[i].pl = &pl[nmtst_get_rand_int () % G_N_ELEMENTS (pl)]; + stack[i].ns_types = ns_types_list[nmtst_get_rand_int () % G_N_ELEMENTS (ns_types_list)]; + + nmp_netns_push_type (nm_platform_netns_get (stack[i].pl->platform), stack[i].ns_types); + } + + /* pop some again. */ + for (i = nmtst_get_rand_int () % (nstack + 1); i > 0; i--) { + g_assert (nstack > 0); + nstack--; + nmp_netns_pop (nm_platform_netns_get (stack[nstack].pl->platform)); + } + + for (i = 0; i < G_N_ELEMENTS (ns_types_test); i++) { + int ns_type = ns_types_test[i]; + PlatformData *p; + gs_free char *current_namespace_id = NULL; + + p = pl_base; + for (j = nstack; j >= 1; ) { + j--; + if (NM_FLAGS_HAS (stack[j].ns_types, ns_type)) { + p = stack[j].pl; + break; + } + } + + current_namespace_id = _get_current_namespace_id (ns_type); + + if (ns_type == CLONE_NEWNET) { + g_assert_cmpstr (current_namespace_id, ==, p->ns_net); + for (j = 0; j < G_N_ELEMENTS (pl); j++) { + gs_free char *data = NULL; + + if (p == &pl[j]) + g_assert_cmpint (nmtstp_run_command ("ip link show %s 1>/dev/null", pl[j].device_name), ==, 0); + else + g_assert_cmpint (nmtstp_run_command ("ip link show %s 2>/dev/null", pl[j].device_name), !=, 0); + + data = _get_sysctl_value (pl[j].sysctl_path); + if (p == &pl[j]) + g_assert_cmpstr (data, ==, pl[j].sysctl_value); + else + g_assert (!data); + } + } else if (ns_type == CLONE_NEWNS) { + g_assert_cmpstr (current_namespace_id, ==, p->ns_mnt); + for (j = 0; j < G_N_ELEMENTS (pl); j++) { + char path[600]; + gs_free char *data = NULL; + + nm_sprintf_buf (path, "/sys/devices/virtual/net/%s/ifindex", pl[j].device_name); + + data = _get_sysctl_value (path); + if (p == &pl[j]) + g_assert_cmpstr (data, ==, nm_sprintf_buf (path, "%d", nmtstp_link_get_typed (p->platform, 0, p->device_name, NM_LINK_TYPE_DUMMY)->ifindex)); + else + g_assert (!data); + } + } else + g_assert_not_reached (); + } + + + for (i = nstack; i >= 1; ) { + i--; + nmp_netns_pop (nm_platform_netns_get (stack[i].pl->platform)); + } +} + +/*****************************************************************************/ + +static void +test_netns_bind_to_path (gpointer fixture, gconstpointer test_data) +{ +#define P_VAR_RUN "/var/run" +#define P_VAR_RUN_NETNS "/var/run/netns" +#define P_VAR_RUN_NETNS_BINDNAME "/var/run/netns/"P_NETNS_BINDNAME +#define P_NETNS_BINDNAME "nmtst-iproute2-netns" + gs_unref_object NMPlatform *platform_0 = NULL; + gs_unref_object NMPlatform *platform_1 = NULL; + gs_unref_object NMPlatform *platform_2 = NULL; + nm_auto_pop_netns NMPNetns *netns_pop = NULL; + NMPlatform *platforms[3]; + NMPNetns *netns; + int i; + + if (_test_netns_check_skip ()) + return; + + platforms[0] = platform_0 = g_object_new (NM_TYPE_LINUX_PLATFORM, NM_PLATFORM_NETNS_SUPPORT, TRUE, NULL); + platforms[1] = platform_1 = _test_netns_create_platform (); + platforms[2] = platform_2 = _test_netns_create_platform (); + + i = nmtst_get_rand_int () % 4; + if (i != 3) + g_assert (nm_platform_netns_push (platforms[i], &netns_pop)); + + g_assert_cmpint (mount ("tmpfs", P_VAR_RUN, "tmpfs", MS_NOATIME | MS_NODEV | MS_NOSUID, "mode=0755,size=32K"), ==, 0); + g_assert_cmpint (mkdir (P_VAR_RUN_NETNS, 755), ==, 0); + + i = (nmtst_get_rand_int () % 2) + 1; + netns = nm_platform_netns_get (platforms[i]); + + _ADD_DUMMY (platforms[i], "dummy2b"); + + g_assert (!g_file_test (P_VAR_RUN_NETNS_BINDNAME, G_FILE_TEST_EXISTS)); + g_assert_cmpint (nmtstp_run_command ("ip netns exec "P_NETNS_BINDNAME" true 2>/dev/null"), !=, 0); + + g_assert (nmp_netns_bind_to_path (netns, P_VAR_RUN_NETNS_BINDNAME, NULL)); + + g_assert (g_file_test (P_VAR_RUN_NETNS_BINDNAME, G_FILE_TEST_EXISTS)); + g_assert_cmpint (nmtstp_run_command ("ip netns exec "P_NETNS_BINDNAME" true"), ==, 0); + g_assert_cmpint (nmtstp_run_command ("ip netns exec "P_NETNS_BINDNAME" ip link show dummy2b 1>/dev/null"), ==, 0); + + g_assert (nmp_netns_bind_to_path_destroy (netns, P_VAR_RUN_NETNS_BINDNAME)); + + g_assert (!g_file_test (P_VAR_RUN_NETNS_BINDNAME, G_FILE_TEST_EXISTS)); + g_assert_cmpint (nmtstp_run_command ("ip netns exec "P_NETNS_BINDNAME" true 2>/dev/null"), !=, 0); + + g_assert_cmpint (umount (P_VAR_RUN), ==, 0); +} + /*****************************************************************************/ void @@ -1894,5 +2338,10 @@ setup_tests (void) g_test_add_func ("/link/nl-bugs/veth", test_nl_bugs_veth); g_test_add_func ("/link/nl-bugs/spurious-newlink", test_nl_bugs_spuroius_newlink); g_test_add_func ("/link/nl-bugs/spurious-dellink", test_nl_bugs_spuroius_dellink); + + g_test_add_vtable ("/general/netns/general", 0, NULL, _test_netns_setup, test_netns_general, _test_netns_teardown); + g_test_add_vtable ("/general/netns/set-netns", 0, NULL, _test_netns_setup, test_netns_set_netns, _test_netns_teardown); + g_test_add_vtable ("/general/netns/push", 0, NULL, _test_netns_setup, test_netns_push, _test_netns_teardown); + g_test_add_vtable ("/general/netns/bind-to-path", 0, NULL, _test_netns_setup, test_netns_bind_to_path, _test_netns_teardown); } } diff --git a/src/platform/tests/test-nmp-object.c b/src/platform/tests/test-nmp-object.c index 3b44abb8..d77170b3 100644 --- a/src/platform/tests/test-nmp-object.c +++ b/src/platform/tests/test-nmp-object.c @@ -223,9 +223,7 @@ test_cache_link (void) GUdevDevice *udev_device_3 = g_list_nth_data (global.udev_devices, 0); NMPCacheOpsType ops_type; - cache = nmp_cache_new (); - - nmp_cache_use_udev_set (cache, g_rand_int_range (nmtst_get_rand (), 0, 2)); + cache = nmp_cache_new (nmtst_get_rand_int () % 2); /* if we have a link, and don't set is_in_netlink, adding it has no effect. */ obj1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2); diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c index f5fa024b..85851854 100644 --- a/src/platform/tests/test-route.c +++ b/src/platform/tests/test-route.c @@ -314,7 +314,7 @@ test_ip4_zero_gateway (void) nmtstp_run_command_check ("ip route add 1.2.3.2/32 dev %s", DEVICE_NAME); NMTST_WAIT_ASSERT (100, { - nmtstp_wait_for_signal (10); + nmtstp_wait_for_signal (NM_PLATFORM_GET, 10); if ( nm_platform_ip4_route_get (NM_PLATFORM_GET, ifindex, nmtst_inet4_from_string ("1.2.3.1"), 32, 0) && nm_platform_ip4_route_get (NM_PLATFORM_GET, ifindex, nmtst_inet4_from_string ("1.2.3.2"), 32, 0)) break; @@ -322,7 +322,7 @@ test_ip4_zero_gateway (void) nmtstp_run_command_check ("ip route flush dev %s", DEVICE_NAME); - nmtstp_wait_for_signal (50); + nmtstp_wait_for_signal (NM_PLATFORM_GET, 50); nm_platform_process_events (NM_PLATFORM_GET); } diff --git a/src/platform/wifi/wifi-utils-wext.c b/src/platform/wifi/wifi-utils-wext.c index 029601e4..af285b45 100644 --- a/src/platform/wifi/wifi-utils-wext.c +++ b/src/platform/wifi/wifi-utils-wext.c @@ -101,7 +101,7 @@ wifi_wext_get_mode (WifiData *data) struct iwreq wrq; memset (&wrq, 0, sizeof (struct iwreq)); - strncpy (wrq.ifr_name, wext->parent.iface, IFNAMSIZ); + nm_utils_ifname_cpy (wrq.ifr_name, wext->parent.iface); if (ioctl (wext->fd, SIOCGIWMODE, &wrq) < 0) { if (errno != ENODEV) { @@ -118,6 +118,7 @@ wifi_wext_get_mode (WifiData *data) case IW_MODE_MASTER: return NM_802_11_MODE_AP; case IW_MODE_INFRA: + case IW_MODE_AUTO: /* hack for WEXT devices reporting IW_MODE_AUTO */ return NM_802_11_MODE_INFRA; default: break; @@ -150,7 +151,7 @@ wifi_wext_set_mode (WifiData *data, const NM80211Mode mode) return FALSE; } - strncpy (wrq.ifr_name, wext->parent.iface, IFNAMSIZ); + nm_utils_ifname_cpy (wrq.ifr_name, wext->parent.iface); if (ioctl (wext->fd, SIOCSIWMODE, &wrq) < 0) { if (errno != ENODEV) { nm_log_err (LOGD_HW | LOGD_WIFI, "(%s): error setting mode %d", @@ -174,7 +175,7 @@ wifi_wext_set_powersave (WifiData *data, guint32 powersave) } else wrq.u.power.disabled = 1; - strncpy (wrq.ifr_name, wext->parent.iface, IFNAMSIZ); + nm_utils_ifname_cpy (wrq.ifr_name, wext->parent.iface); if (ioctl (wext->fd, SIOCSIWPOWER, &wrq) < 0) { if (errno != ENODEV) { nm_log_err (LOGD_HW | LOGD_WIFI, "(%s): error setting powersave %" G_GUINT32_FORMAT, @@ -193,7 +194,7 @@ wifi_wext_get_freq (WifiData *data) struct iwreq wrq; memset (&wrq, 0, sizeof (struct iwreq)); - strncpy (wrq.ifr_name, wext->parent.iface, IFNAMSIZ); + nm_utils_ifname_cpy (wrq.ifr_name, wext->parent.iface); if (ioctl (wext->fd, SIOCGIWFREQ, &wrq) < 0) { nm_log_warn (LOGD_HW | LOGD_WIFI, "(%s): error getting frequency: %s", @@ -227,7 +228,7 @@ wifi_wext_get_bssid (WifiData *data, guint8 *out_bssid) struct iwreq wrq; memset (&wrq, 0, sizeof (wrq)); - strncpy (wrq.ifr_name, wext->parent.iface, IFNAMSIZ); + nm_utils_ifname_cpy (wrq.ifr_name, wext->parent.iface); if (ioctl (wext->fd, SIOCGIWAP, &wrq) < 0) { nm_log_warn (LOGD_HW | LOGD_WIFI, "(%s): error getting associated BSSID: %s", @@ -246,7 +247,7 @@ wifi_wext_get_rate (WifiData *data) int err; memset (&wrq, 0, sizeof (wrq)); - strncpy (wrq.ifr_name, wext->parent.iface, IFNAMSIZ); + nm_utils_ifname_cpy (wrq.ifr_name, wext->parent.iface); err = ioctl (wext->fd, SIOCGIWRATE, &wrq); return ((err == 0) ? wrq.u.bitrate.value / 1000 : 0); } @@ -356,7 +357,7 @@ wifi_wext_get_qual (WifiData *data) wrq.u.data.pointer = &stats; wrq.u.data.length = sizeof (stats); wrq.u.data.flags = 1; /* Clear updated flag */ - strncpy (wrq.ifr_name, wext->parent.iface, IFNAMSIZ); + nm_utils_ifname_cpy (wrq.ifr_name, wext->parent.iface); if (ioctl (wext->fd, SIOCGIWSTATS, &wrq) < 0) { nm_log_warn (LOGD_HW | LOGD_WIFI, @@ -393,7 +394,7 @@ wifi_wext_set_mesh_channel (WifiData *data, guint32 channel) struct iwreq wrq; memset (&wrq, 0, sizeof (struct iwreq)); - strncpy (wrq.ifr_name, wext->parent.iface, IFNAMSIZ); + nm_utils_ifname_cpy (wrq.ifr_name, wext->parent.iface); if (channel > 0) { wrq.u.freq.flags = IW_FREQ_FIXED; @@ -425,7 +426,7 @@ wifi_wext_set_mesh_ssid (WifiData *data, const guint8 *ssid, gsize len) wrq.u.essid.length = len; wrq.u.essid.flags = (len > 0) ? 1 : 0; /* 1=enable SSID, 0=disable/any */ - strncpy (wrq.ifr_name, wext->parent.iface, IFNAMSIZ); + nm_utils_ifname_cpy (wrq.ifr_name, wext->parent.iface); if (ioctl (wext->fd, SIOCSIWESSID, &wrq) == 0) return TRUE; @@ -448,7 +449,7 @@ wext_can_scan (WifiDataWext *wext) struct iwreq wrq; memset (&wrq, 0, sizeof (struct iwreq)); - strncpy (wrq.ifr_name, wext->parent.iface, IFNAMSIZ); + nm_utils_ifname_cpy (wrq.ifr_name, wext->parent.iface); if (ioctl (wext->fd, SIOCSIWSCAN, &wrq) < 0) { if (errno == EOPNOTSUPP) return FALSE; @@ -466,7 +467,7 @@ wext_get_range (WifiDataWext *wext, struct iwreq wrq; memset (&wrq, 0, sizeof (struct iwreq)); - strncpy (wrq.ifr_name, wext->parent.iface, IFNAMSIZ); + nm_utils_ifname_cpy (wrq.ifr_name, wext->parent.iface); wrq.u.data.pointer = (caddr_t) range; wrq.u.data.length = sizeof (struct iw_range); @@ -666,7 +667,7 @@ wifi_wext_is_wifi (const char *iface) fd = socket (PF_INET, SOCK_DGRAM, 0); if (fd >= 0) { - strncpy (iwr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ); + nm_utils_ifname_cpy (iwr.ifr_ifrn.ifrn_name, iface); if (ioctl (fd, SIOCGIWNAME, &iwr) == 0) is_wifi = TRUE; close (fd); diff --git a/src/ppp-manager/nm-ppp-manager.c b/src/ppp-manager/nm-ppp-manager.c index 1578e595..16e34f11 100644 --- a/src/ppp-manager/nm-ppp-manager.c +++ b/src/ppp-manager/nm-ppp-manager.c @@ -49,6 +49,16 @@ #include "nmdbus-ppp-manager.h" +#define _NMLOG_DOMAIN LOGD_PPP +#define _NMLOG_PREFIX_NAME "ppp-manager" +#define _NMLOG(level, ...) \ + G_STMT_START { \ + nm_log ((level), _NMLOG_DOMAIN, \ + "%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME": " \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } G_STMT_END + static void _ppp_cleanup (NMPPPManager *manager); static void _ppp_kill (NMPPPManager *manager); @@ -185,7 +195,7 @@ monitor_cb (gpointer user_data) strncpy (req.ifr_name, priv->ip_iface, sizeof (req.ifr_name)); if (ioctl (priv->monitor_fd, SIOCGPPPSTATS, &req) < 0) { if (errno != ENODEV) - nm_log_warn (LOGD_PPP, "could not read ppp stats: %s", strerror (errno)); + _LOGW ("could not read ppp stats: %s", strerror (errno)); } else { g_signal_emit (manager, signals[STATS], 0, stats.p.ppp_ibytes, @@ -211,7 +221,7 @@ monitor_stats (NMPPPManager *manager) g_source_remove (priv->monitor_id); priv->monitor_id = g_timeout_add_seconds (5, monitor_cb, manager); } else - nm_log_warn (LOGD_PPP, "could not monitor PPP stats: %s", strerror (errno)); + _LOGW ("could not monitor PPP stats: %s", strerror (errno)); } /*******************************************/ @@ -316,7 +326,7 @@ ppp_secrets_cb (NMActRequest *req, goto out; if (error) { - nm_log_warn (LOGD_PPP, "%s", error->message); + _LOGW ("%s", error->message); g_dbus_method_invocation_return_gerror (priv->pending_secrets_context, error); goto out; } @@ -324,7 +334,7 @@ ppp_secrets_cb (NMActRequest *req, applied_connection = nm_act_request_get_applied_connection (req); if (!extract_details_from_connection (applied_connection, priv->secrets_setting_name, &username, &password, &local)) { - nm_log_warn (LOGD_PPP, "%s", local->message); + _LOGW ("%s", local->message); g_dbus_method_invocation_take_error (priv->pending_secrets_context, local); goto out; } @@ -370,7 +380,7 @@ impl_ppp_manager_need_secrets (NMPPPManager *manager, priv->pending_secrets_context = context; ppp_secrets_cb (priv->act_req, priv->secrets_id, NULL, NULL, manager); } else { - nm_log_warn (LOGD_PPP, "%s", error->message); + _LOGW ("%s", error->message); g_dbus_method_invocation_take_error (priv->pending_secrets_context, error); } return; @@ -419,7 +429,7 @@ set_ip_config_common (NMPPPManager *self, const char *iface; if (!g_variant_lookup (config_dict, iface_prop, "&s", &iface)) { - nm_log_err (LOGD_PPP, "no interface received!"); + _LOGE ("no interface received!"); return FALSE; } if (priv->ip_iface == NULL) @@ -450,7 +460,7 @@ impl_ppp_manager_set_ip4_config (NMPPPManager *manager, guint32 u32; GVariantIter *iter; - nm_log_info (LOGD_PPP, "PPP manager (IPv4 Config Get) reply received."); + _LOGI ("(IPv4 Config Get) reply received."); remove_timeout_handler (manager); @@ -475,7 +485,7 @@ impl_ppp_manager_set_ip4_config (NMPPPManager *manager, address.source = NM_IP_CONFIG_SOURCE_PPP; nm_ip4_config_add_address (config, &address); } else { - nm_log_err (LOGD_PPP, "invalid IPv4 address received!"); + _LOGE ("invalid IPv4 address received!"); goto out; } @@ -517,7 +527,7 @@ iid_value_to_ll6_addr (GVariant *dict, guint64 iid; if (!g_variant_lookup (dict, prop, "t", &iid)) { - nm_log_dbg (LOGD_PPP, "pppd plugin property '%s' missing or not a uint64", prop); + _LOGD ("pppd plugin property '%s' missing or not a uint64", prop); return FALSE; } g_return_val_if_fail (iid != 0, FALSE); @@ -545,7 +555,7 @@ impl_ppp_manager_set_ip6_config (NMPPPManager *manager, struct in6_addr a; NMUtilsIPv6IfaceId iid = NM_UTILS_IPV6_IFACE_ID_INIT; - nm_log_info (LOGD_PPP, "PPP manager (IPv6 Config Get) reply received."); + _LOGI ("(IPv6 Config Get) reply received."); remove_timeout_handler (manager); @@ -567,7 +577,7 @@ impl_ppp_manager_set_ip6_config (NMPPPManager *manager, g_signal_emit (manager, signals[IP6_CONFIG], 0, priv->ip_iface, &iid, config); } } else - nm_log_err (LOGD_PPP, "invalid IPv6 address received!"); + _LOGE ("invalid IPv6 address received!"); g_object_unref (config); g_dbus_method_invocation_return_value (context, NULL); @@ -771,7 +781,7 @@ ppp_exit_code (guint pppd_exit_status, GPid pid) msg = "Unknown error"; } - nm_log_warn (LOGD_PPP, "pppd pid %d exited with error: %s", pid, msg); + _LOGW ("pppd pid %d exited with error: %s", pid, msg); } static void @@ -788,13 +798,13 @@ ppp_watch_cb (GPid pid, gint status, gpointer user_data) if (err != 0) ppp_exit_code (err, priv->pid); } else if (WIFSTOPPED (status)) { - nm_log_info (LOGD_PPP, "pppd pid %d stopped unexpectedly with signal %d", priv->pid, WSTOPSIG (status)); + _LOGI ("pppd pid %d stopped unexpectedly with signal %d", priv->pid, WSTOPSIG (status)); } else if (WIFSIGNALED (status)) { - nm_log_info (LOGD_PPP, "pppd pid %d died with signal %d", priv->pid, WTERMSIG (status)); + _LOGI ("pppd pid %d died with signal %d", priv->pid, WTERMSIG (status)); } else - nm_log_info (LOGD_PPP, "pppd pid %d died from an unknown cause", priv->pid); + _LOGI ("pppd pid %d died from an unknown cause", priv->pid); - nm_log_dbg (LOGD_PPP, "pppd pid %d cleaned up", priv->pid); + _LOGD ("pppd pid %d cleaned up", priv->pid); priv->pid = 0; priv->ppp_watch_id = 0; g_signal_emit (manager, signals[STATE_CHANGED], 0, NM_PPP_STATUS_DEAD); @@ -805,7 +815,7 @@ pppd_timed_out (gpointer data) { NMPPPManager *manager = NM_PPP_MANAGER (data); - nm_log_warn (LOGD_PPP, "pppd timed out or didn't initialize our dbus module"); + _LOGW ("pppd timed out or didn't initialize our dbus module"); _ppp_cleanup (manager); _ppp_kill (manager); @@ -1065,10 +1075,10 @@ nm_ppp_manager_start (NMPPPManager *manager, g_ptr_array_add (ppp_cmd->array, NULL); - nm_log_info (LOGD_PPP, "starting PPP connection"); + _LOGI ("starting PPP connection"); cmd_str = nm_cmd_line_to_str (ppp_cmd); - nm_log_dbg (LOGD_PPP, "command line: %s", cmd_str); + _LOGD ("command line: %s", cmd_str); g_free (cmd_str); priv->pid = 0; @@ -1079,7 +1089,7 @@ nm_ppp_manager_start (NMPPPManager *manager, goto out; } - nm_log_info (LOGD_PPP, "pppd started with pid %d", priv->pid); + _LOGI ("pppd started with pid %d", priv->pid); priv->ppp_watch_id = g_child_watch_add (priv->pid, (GChildWatchFunc) ppp_watch_cb, manager); priv->ppp_timeout_handler = g_timeout_add_seconds (timeout_secs, pppd_timed_out, manager); diff --git a/src/ppp-manager/nm-pppd-plugin.c b/src/ppp-manager/nm-pppd-plugin.c index be4dd185..4c16f1f0 100644 --- a/src/ppp-manager/nm-pppd-plugin.c +++ b/src/ppp-manager/nm-pppd-plugin.c @@ -302,10 +302,9 @@ get_credentials (char *username, char *password) G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err); if (!ret) { - g_warning ("nm-ppp-plugin: (%s): could not get secrets: (%d) %s", + g_warning ("nm-ppp-plugin: (%s): could not get secrets: %s", __func__, - err ? err->code : -1, - err->message ? err->message : "(unknown)"); + err->message); g_error_free (err); return -1; } diff --git a/src/rdisc/nm-lndp-rdisc.c b/src/rdisc/nm-lndp-rdisc.c index 06863462..27fd2f83 100644 --- a/src/rdisc/nm-lndp-rdisc.c +++ b/src/rdisc/nm-lndp-rdisc.c @@ -31,6 +31,7 @@ #include "NetworkManagerUtils.h" #include "nm-platform.h" +#include "nmp-netns.h" #define _NMLOG_PREFIX_NAME "rdisc-lndp" @@ -273,9 +274,14 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data) static gboolean event_ready (GIOChannel *source, GIOCondition condition, NMRDisc *rdisc) { + nm_auto_pop_netns NMPNetns *netns = NULL; NMLNDPRDiscPrivate *priv = NM_LNDP_RDISC_GET_PRIVATE (rdisc); _LOGD ("processing libndp events"); + + if (!nm_rdisc_netns_push (rdisc, &netns)) + return G_SOURCE_CONTINUE; + ndp_callall_eventfd_handler (priv->ndp); return G_SOURCE_CONTINUE; } @@ -298,40 +304,50 @@ start (NMRDisc *rdisc) /******************************************************************/ static inline gint32 -ipv6_sysctl_get (const char *ifname, const char *property, gint32 defval) +ipv6_sysctl_get (NMPlatform *platform, const char *ifname, const char *property, gint32 defval) { - return nm_platform_sysctl_get_int32 (NM_PLATFORM_GET, nm_utils_ip6_property_path (ifname, property), defval); + return nm_platform_sysctl_get_int32 (platform, nm_utils_ip6_property_path (ifname, property), defval); } NMRDisc * -nm_lndp_rdisc_new (int ifindex, +nm_lndp_rdisc_new (NMPlatform *platform, + int ifindex, const char *ifname, const char *uuid, NMSettingIP6ConfigAddrGenMode addr_gen_mode, GError **error) { + nm_auto_pop_netns NMPNetns *netns = NULL; NMRDisc *rdisc; NMLNDPRDiscPrivate *priv; int errsv; + g_return_val_if_fail (NM_IS_PLATFORM (platform), NULL); g_return_val_if_fail (!error || !*error, NULL); - rdisc = g_object_new (NM_TYPE_LNDP_RDISC, NULL); + if (!nm_platform_netns_push (platform, &netns)) + return NULL; + + rdisc = g_object_new (NM_TYPE_LNDP_RDISC, + NM_RDISC_PLATFORM, platform, + NULL); rdisc->ifindex = ifindex; rdisc->ifname = g_strdup (ifname); rdisc->uuid = g_strdup (uuid); rdisc->addr_gen_mode = addr_gen_mode; - rdisc->max_addresses = ipv6_sysctl_get (ifname, "max_addresses", + rdisc->max_addresses = ipv6_sysctl_get (platform, ifname, "max_addresses", NM_RDISC_MAX_ADDRESSES_DEFAULT); - rdisc->rtr_solicitations = ipv6_sysctl_get (ifname, "router_solicitations", + rdisc->rtr_solicitations = ipv6_sysctl_get (platform, ifname, "router_solicitations", NM_RDISC_RTR_SOLICITATIONS_DEFAULT); - rdisc->rtr_solicitation_interval = ipv6_sysctl_get (ifname, "router_solicitation_interval", + rdisc->rtr_solicitation_interval = ipv6_sysctl_get (platform, ifname, "router_solicitation_interval", NM_RDISC_RTR_SOLICITATION_INTERVAL_DEFAULT); priv = NM_LNDP_RDISC_GET_PRIVATE (rdisc); + errsv = ndp_open (&priv->ndp); + if (errsv != 0) { errsv = errsv > 0 ? errsv : -errsv; g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, diff --git a/src/rdisc/nm-lndp-rdisc.h b/src/rdisc/nm-lndp-rdisc.h index e6706e3c..4c7c4743 100644 --- a/src/rdisc/nm-lndp-rdisc.h +++ b/src/rdisc/nm-lndp-rdisc.h @@ -44,7 +44,8 @@ typedef struct { GType nm_lndp_rdisc_get_type (void); -NMRDisc *nm_lndp_rdisc_new (int ifindex, +NMRDisc *nm_lndp_rdisc_new (NMPlatform *platform, + int ifindex, const char *ifname, const char *uuid, NMSettingIP6ConfigAddrGenMode addr_gen_mode, diff --git a/src/rdisc/nm-rdisc.c b/src/rdisc/nm-rdisc.c index 82aece30..689fe7f6 100644 --- a/src/rdisc/nm-rdisc.c +++ b/src/rdisc/nm-rdisc.c @@ -28,6 +28,8 @@ #include "nm-rdisc-private.h" #include "nm-utils.h" +#include "nm-platform.h" +#include "nmp-netns.h" #include <nm-setting-ip6-config.h> @@ -46,6 +48,10 @@ typedef struct { G_DEFINE_TYPE (NMRDisc, nm_rdisc, G_TYPE_OBJECT) +NM_GOBJECT_PROPERTIES_DEFINE_BASE ( + PROP_PLATFORM, +); + enum { CONFIG_CHANGED, RA_TIMEOUT, @@ -56,6 +62,31 @@ static guint signals[LAST_SIGNAL] = { 0 }; /******************************************************************/ +NMPNetns * +nm_rdisc_netns_get (NMRDisc *self) +{ + g_return_val_if_fail (NM_IS_RDISC (self), NULL); + + return self->_netns; +} + +gboolean +nm_rdisc_netns_push (NMRDisc *self, NMPNetns **netns) +{ + g_return_val_if_fail (NM_IS_RDISC (self), FALSE); + + if ( self->_netns + && !nmp_netns_push (self->_netns)) { + NM_SET_OUT (netns, NULL); + return FALSE; + } + + NM_SET_OUT (netns, self->_netns); + return TRUE; +} + +/******************************************************************/ + gboolean nm_rdisc_add_gateway (NMRDisc *rdisc, const NMRDiscGateway *new) { @@ -317,10 +348,14 @@ nm_rdisc_set_iid (NMRDisc *rdisc, const NMUtilsIPv6IfaceId iid) static gboolean send_rs (NMRDisc *rdisc) { + nm_auto_pop_netns NMPNetns *netns = NULL; NMRDiscClass *klass = NM_RDISC_GET_CLASS (rdisc); NMRDiscPrivate *priv = NM_RDISC_GET_PRIVATE (rdisc); GError *error = NULL; + if (!nm_rdisc_netns_push (rdisc, &netns)) + return G_SOURCE_REMOVE; + if (klass->send_rs (rdisc, &error)) { _LOGD ("router solicitation sent"); priv->solicitations_left--; @@ -383,6 +418,7 @@ rdisc_ra_timeout_cb (gpointer user_data) void nm_rdisc_start (NMRDisc *rdisc) { + nm_auto_pop_netns NMPNetns *netns = NULL; NMRDiscPrivate *priv = NM_RDISC_GET_PRIVATE (rdisc); NMRDiscClass *klass = NM_RDISC_GET_CLASS (rdisc); guint ra_wait_secs; @@ -391,6 +427,9 @@ nm_rdisc_start (NMRDisc *rdisc) _LOGD ("starting router discovery: %d", rdisc->ifindex); + if (!nm_rdisc_netns_push (rdisc, &netns)) + return; + nm_clear_g_source (&priv->ra_timeout_id); ra_wait_secs = CLAMP (rdisc->rtr_solicitations * rdisc->rtr_solicitation_interval, 30, 120); priv->ra_timeout_id = g_timeout_add_seconds (ra_wait_secs, rdisc_ra_timeout_cb, rdisc); @@ -669,6 +708,33 @@ dns_domain_free (gpointer data) } static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMRDisc *self = NM_RDISC (object); + + switch (prop_id) { + case PROP_PLATFORM: + /* construct-only */ + self->_platform = g_value_get_object (value) ? : NM_PLATFORM_GET; + if (!self->_platform) + g_return_if_reached (); + + g_object_ref (self->_platform); + + self->_netns = nm_platform_netns_get (self->_platform); + if (self->_netns) + g_object_ref (self->_netns); + + g_return_if_fail (!self->_netns || self->_netns == nmp_netns_get_current ()); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void nm_rdisc_init (NMRDisc *rdisc) { NMRDiscPrivate *priv = NM_RDISC_GET_PRIVATE (rdisc); @@ -715,6 +781,9 @@ finalize (GObject *object) g_array_unref (rdisc->dns_servers); g_array_unref (rdisc->dns_domains); + g_clear_object (&rdisc->_netns); + g_clear_object (&rdisc->_platform); + G_OBJECT_CLASS (nm_rdisc_parent_class)->finalize (object); } @@ -725,23 +794,31 @@ nm_rdisc_class_init (NMRDiscClass *klass) g_type_class_add_private (klass, sizeof (NMRDiscPrivate)); + object_class->set_property = set_property; object_class->dispose = dispose; object_class->finalize = finalize; klass->config_changed = config_changed; - signals[CONFIG_CHANGED] = g_signal_new ( - NM_RDISC_CONFIG_CHANGED, - G_OBJECT_CLASS_TYPE (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMRDiscClass, config_changed), - NULL, NULL, NULL, - G_TYPE_NONE, 1, G_TYPE_INT); - - signals[RA_TIMEOUT] = g_signal_new ( - NM_RDISC_RA_TIMEOUT, - G_OBJECT_CLASS_TYPE (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMRDiscClass, ra_timeout), - NULL, NULL, NULL, - G_TYPE_NONE, 0); + obj_properties[PROP_PLATFORM] = + g_param_spec_object (NM_RDISC_PLATFORM, "", "", + NM_TYPE_PLATFORM, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + signals[CONFIG_CHANGED] = + g_signal_new (NM_RDISC_CONFIG_CHANGED, + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMRDiscClass, config_changed), + NULL, NULL, NULL, + G_TYPE_NONE, 1, G_TYPE_INT); + signals[RA_TIMEOUT] = + g_signal_new (NM_RDISC_RA_TIMEOUT, + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMRDiscClass, ra_timeout), + NULL, NULL, NULL, + G_TYPE_NONE, 0); } diff --git a/src/rdisc/nm-rdisc.h b/src/rdisc/nm-rdisc.h index 51e2602f..5b97bec5 100644 --- a/src/rdisc/nm-rdisc.h +++ b/src/rdisc/nm-rdisc.h @@ -21,11 +21,9 @@ #ifndef __NETWORKMANAGER_RDISC_H__ #define __NETWORKMANAGER_RDISC_H__ - #include <stdlib.h> #include <netinet/in.h> -#include "nm-default.h" #include "nm-setting-ip6-config.h" #include "NetworkManagerUtils.h" @@ -36,6 +34,7 @@ #define NM_IS_RDISC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_RDISC)) #define NM_RDISC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_RDISC, NMRDiscClass)) +#define NM_RDISC_PLATFORM "platform" #define NM_RDISC_CONFIG_CHANGED "config-changed" #define NM_RDISC_RA_TIMEOUT "ra-timeout" @@ -114,6 +113,9 @@ typedef enum { typedef struct { GObject parent; + NMPlatform *_platform; + NMPNetns *_netns; + int ifindex; char *ifname; char *uuid; @@ -149,4 +151,8 @@ gboolean nm_rdisc_set_iid (NMRDisc *rdisc, const NMUtilsIPv6IfaceId iid); void nm_rdisc_start (NMRDisc *rdisc); void nm_rdisc_dad_failed (NMRDisc *rdisc, struct in6_addr *address); +NMPlatform *nm_rdisc_get_platform (NMRDisc *self); +NMPNetns *nm_rdisc_netns_get (NMRDisc *self); +gboolean nm_rdisc_netns_push (NMRDisc *self, NMPNetns **netns); + #endif /* __NETWORKMANAGER_RDISC_H__ */ diff --git a/src/rdisc/tests/test-rdisc-fake.c b/src/rdisc/tests/test-rdisc-fake.c index 00a98dca..1c514b90 100644 --- a/src/rdisc/tests/test-rdisc-fake.c +++ b/src/rdisc/tests/test-rdisc-fake.c @@ -431,7 +431,7 @@ main (int argc, char **argv) nmtst_init_with_logging (&argc, &argv, NULL, "DEFAULT"); if (nmtst_test_quick ()) { - g_print ("Skipping test: don't run long running test %s (NMTST_DEBUG=slow)\n", str_if_set (g_get_prgname (), "test-rdisc-fake")); + g_print ("Skipping test: don't run long running test %s (NMTST_DEBUG=slow)\n", g_get_prgname () ?: "test-rdisc-fake"); return g_test_run (); } diff --git a/src/rdisc/tests/test-rdisc-linux.c b/src/rdisc/tests/test-rdisc-linux.c index bbdb5fb8..e22eb1ad 100644 --- a/src/rdisc/tests/test-rdisc-linux.c +++ b/src/rdisc/tests/test-rdisc-linux.c @@ -61,7 +61,8 @@ main (int argc, char **argv) return EXIT_FAILURE; } - rdisc = nm_lndp_rdisc_new (ifindex, + rdisc = nm_lndp_rdisc_new (NM_PLATFORM_GET, + ifindex, ifname, "8ce666e8-d34d-4fb1-b858-f15a7al28086", NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64, diff --git a/src/settings/nm-agent-manager.c b/src/settings/nm-agent-manager.c index bc09e031..48a7da7b 100644 --- a/src/settings/nm-agent-manager.c +++ b/src/settings/nm-agent-manager.c @@ -263,8 +263,8 @@ agent_register_permissions_done (NMAuthChain *chain, if (error) { local = g_error_new (NM_AGENT_MANAGER_ERROR, NM_AGENT_MANAGER_ERROR_PERMISSION_DENIED, - "Failed to request agent permissions: (%d) %s", - error->code, error->message); + "Failed to request agent permissions: %s", + error->message); g_dbus_method_invocation_take_error (context, local); } else { agent = nm_auth_chain_steal_data (chain, "agent"); @@ -930,6 +930,7 @@ set_secrets_not_required (NMConnection *connection, GVariant *dict) g_variant_unref (val); } } + g_variant_unref (setting_dict); } } @@ -987,9 +988,9 @@ _con_get_request_start_validated (NMAuthChain *chain, req->con.chain = NULL; if (error) { - _LOGD (req->current, "agent "LOG_REQ_FMT" MODIFY check error: (%d) %s", + _LOGD (req->current, "agent "LOG_REQ_FMT" MODIFY check error: %s", LOG_REQ_ARG (req), - error->code, error->message ? error->message : "(unknown)"); + error->message); /* Try the next agent */ request_next_agent (req); } else { diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c index a1695b34..6bed3fe5 100644 --- a/src/settings/nm-settings-connection.c +++ b/src/settings/nm-settings-connection.c @@ -883,10 +883,8 @@ new_secrets_commit_cb (NMSettingsConnection *self, GError *error, gpointer user_data) { - if (error) { - _LOGW ("Error saving new secrets to backing storage: (%d) %s", - error->code, error->message ? error->message : "(unknown)"); - } + if (error) + _LOGW ("Error saving new secrets to backing storage: %s", error->message); } static void @@ -1086,19 +1084,17 @@ get_secrets_done_cb (NMAgentManager *manager, } } else { - _LOGD ("(%s:%p) failed to update with agent secrets: (%d) %s", + _LOGD ("(%s:%p) failed to update with agent secrets: %s", setting_name, info, - local ? local->code : -1, - (local && local->message) ? local->message : "(unknown)"); + local->message); } g_variant_unref (filtered_secrets); } else { - _LOGD ("(%s:%p) failed to update with existing secrets: (%d) %s", + _LOGD ("(%s:%p) failed to update with existing secrets: %s", setting_name, info, - local ? local->code : -1, - (local && local->message) ? local->message : "(unknown)"); + local->message); } applied_connection = info->applied_connection; @@ -1739,7 +1735,10 @@ settings_connection_update_helper (NMSettingsConnection *self, /* Check if the settings are valid first */ if (new_settings) { - tmp = nm_simple_connection_new_from_dbus (new_settings, &error); + tmp = _nm_simple_connection_new_from_dbus (new_settings, + NM_SETTING_PARSE_FLAGS_STRICT + | NM_SETTING_PARSE_FLAGS_NORMALIZE, + &error); if (!tmp) goto error; } @@ -2163,7 +2162,7 @@ nm_settings_connection_update_timestamp (NMSettingsConnection *self, /* Save timestamp to timestamps database file */ timestamps_file = g_key_file_new (); if (!g_key_file_load_from_file (timestamps_file, SETTINGS_TIMESTAMPS_FILE, G_KEY_FILE_KEEP_COMMENTS, &error)) { - if (!(error->domain == G_FILE_ERROR && error->code == G_FILE_ERROR_NOENT)) + if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) _LOGW ("error parsing timestamps file '%s': %s", SETTINGS_TIMESTAMPS_FILE, error->message); g_clear_error (&error); } @@ -2172,7 +2171,7 @@ nm_settings_connection_update_timestamp (NMSettingsConnection *self, tmp = g_strdup_printf ("%" G_GUINT64_FORMAT, timestamp); g_key_file_set_value (timestamps_file, "timestamps", connection_uuid, tmp); g_free (tmp); - + data = g_key_file_to_data (timestamps_file, &len, &error); if (data) { g_file_set_contents (SETTINGS_TIMESTAMPS_FILE, data, len, &error); @@ -2219,8 +2218,7 @@ nm_settings_connection_read_and_fill_timestamp (NMSettingsConnection *self) priv->timestamp = timestamp; priv->timestamp_set = TRUE; } else { - _LOGD ("failed to read connection timestamp: (%d) %s", - err->code, err->message); + _LOGD ("failed to read connection timestamp: %s", err->message); g_clear_error (&err); } g_key_file_free (timestamps_file); diff --git a/src/settings/nm-settings-plugin.c b/src/settings/nm-settings-plugin.c index 2023bc17..7de7e597 100644 --- a/src/settings/nm-settings-plugin.c +++ b/src/settings/nm-settings-plugin.c @@ -175,5 +175,7 @@ nm_settings_plugin_add_connection (NMSettingsPlugin *config, if (NM_SETTINGS_PLUGIN_GET_INTERFACE (config)->add_connection) return NM_SETTINGS_PLUGIN_GET_INTERFACE (config)->add_connection (config, connection, save_to_disk, error); + g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_NOT_SUPPORTED, + "Plugin does not support adding connections"); return NULL; } diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index ee48e711..77e45f49 100644 --- a/src/settings/nm-settings.c +++ b/src/settings/nm-settings.c @@ -76,12 +76,15 @@ #include "nmdbus-settings.h" -#define LOG(level, ...) \ - G_STMT_START { \ - nm_log ((level), LOGD_CORE, \ - "settings: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__) \ - _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ - } G_STMT_END +#define _NMLOG_DOMAIN LOGD_SETTINGS +#define _NMLOG_PREFIX_NAME "settings" +#define _NMLOG(level, ...) \ + G_STMT_START { \ + nm_log ((level), _NMLOG_DOMAIN, \ + "%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME": " \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } G_STMT_END /* LINKER CRACKROCK */ #define EXPORT(sym) void * __export_##sym = &sym; @@ -652,8 +655,8 @@ add_plugin (NMSettings *self, NMSettingsPlugin *plugin) path = g_object_get_data (G_OBJECT (plugin), PLUGIN_MODULE_PATH); - nm_log_info (LOGD_SETTINGS, "Loaded settings plugin %s: %s%s%s%s", pname, pinfo, - NM_PRINT_FMT_QUOTED (path, " (", path, ")", "")); + _LOGI ("loaded plugin %s: %s%s%s%s", pname, pinfo, + NM_PRINT_FMT_QUOTED (path, " (", path, ")", "")); g_free (pname); g_free (pinfo); @@ -719,12 +722,12 @@ load_plugins (NMSettings *self, const char **plugins, GError **error) GObject *obj; if (!*pname || strchr (pname, '/')) { - LOG (LOGL_WARN, "ignore invalid plugin \"%s\"", pname); + _LOGW ("ignore invalid plugin \"%s\"", pname); continue; } if (!strcmp (pname, "ifcfg-suse")) { - LOG (LOGL_WARN, "skipping deprecated plugin ifcfg-suse"); + _LOGW ("skipping deprecated plugin ifcfg-suse"); continue; } @@ -767,25 +770,25 @@ load_plugin: if (stat (path, &st) != 0) { errsv = errno; - LOG (LOGL_WARN, "Could not load plugin '%s' from file '%s': %s", pname, path, strerror (errsv)); + _LOGW ("could not load plugin '%s' from file '%s': %s", pname, path, strerror (errsv)); goto next; } if (!S_ISREG (st.st_mode)) { - LOG (LOGL_WARN, "Could not load plugin '%s' from file '%s': not a file", pname, path); + _LOGW ("could not load plugin '%s' from file '%s': not a file", pname, path); goto next; } if (st.st_uid != 0) { - LOG (LOGL_WARN, "Could not load plugin '%s' from file '%s': file must be owned by root", pname, path); + _LOGW ("could not load plugin '%s' from file '%s': file must be owned by root", pname, path); goto next; } if (st.st_mode & (S_IWGRP | S_IWOTH | S_ISUID)) { - LOG (LOGL_WARN, "Could not load plugin '%s' from file '%s': invalid file permissions", pname, path); + _LOGW ("could not load plugin '%s' from file '%s': invalid file permissions", pname, path); goto next; } plugin = g_module_open (path, G_MODULE_BIND_LOCAL); if (!plugin) { - LOG (LOGL_WARN, "Could not load plugin '%s' from file '%s': %s", + _LOGW ("could not load plugin '%s' from file '%s': %s", pname, path, g_module_error ()); goto next; } @@ -985,8 +988,7 @@ claim_connection (NMSettings *self, NMSettingsConnection *connection) } if (!nm_connection_normalize (NM_CONNECTION (connection), NULL, NULL, &error)) { - nm_log_warn (LOGD_SETTINGS, "plugin provided invalid connection: %s", - error->message); + _LOGW ("plugin provided invalid connection: %s", error->message); g_error_free (error); return; } @@ -1003,8 +1005,8 @@ claim_connection (NMSettings *self, NMSettingsConnection *connection) * without the individual plugins being aware. Don't handle that at all, just * error out. That should not happen unless the admin misconfigured the system * to create conflicting connections. */ - nm_log_warn (LOGD_SETTINGS, "plugin provided duplicate connection with UUID %s", - nm_settings_connection_get_uuid (connection)); + _LOGW ("plugin provided duplicate connection with UUID %s", + nm_settings_connection_get_uuid (connection)); return; } @@ -1117,10 +1119,10 @@ nm_settings_add_connection (NMSettings *self, claim_connection (self, added); return added; } - nm_log_dbg (LOGD_SETTINGS, "Failed to add %s/'%s': %s", - nm_connection_get_uuid (connection), - nm_connection_get_id (connection), - add_error ? add_error->message : "(unknown)"); + _LOGD ("Failed to add %s/'%s': %s", + nm_connection_get_uuid (connection), + nm_connection_get_id (connection), + add_error->message); g_clear_error (&add_error); } @@ -1211,7 +1213,7 @@ pk_add_cb (NMAuthChain *chain, error = g_error_new (NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, "Error checking authorization: %s", - chain_error->message ? chain_error->message : "(unknown)"); + chain_error->message); } else if (result != NM_AUTH_CALL_RESULT_YES) { error = g_error_new_literal (NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_PERMISSION_DENIED, @@ -1294,7 +1296,7 @@ nm_settings_add_connection_dbus (NMSettings *self, error = g_error_new (NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "The connection was invalid: %s", - tmp_error ? tmp_error->message : "(unknown)"); + tmp_error->message); g_error_free (tmp_error); goto done; } @@ -1405,7 +1407,10 @@ impl_settings_add_connection_helper (NMSettings *self, NMConnection *connection; GError *error = NULL; - connection = nm_simple_connection_new_from_dbus (settings, &error); + connection = _nm_simple_connection_new_from_dbus (settings, + NM_SETTING_PARSE_FLAGS_STRICT + | NM_SETTING_PARSE_FLAGS_NORMALIZE, + &error); if (connection) { if (!nm_connection_verify_secrets (connection, &error)) @@ -1492,7 +1497,7 @@ impl_settings_load_connections (NMSettings *self, if (!iter) { if (!g_path_is_absolute (filenames[i])) - nm_log_warn (LOGD_SETTINGS, "Connection filename '%s' is not an absolute path", filenames[i]); + _LOGW ("connection filename '%s' is not an absolute path", filenames[i]); g_ptr_array_add (failures, (char *) filenames[i]); } } @@ -1525,6 +1530,65 @@ impl_settings_reload_connections (NMSettings *self, g_dbus_method_invocation_return_value (context, g_variant_new ("(b)", TRUE)); } +typedef struct { + char *hostname; + NMSettingsSetHostnameCb cb; + gpointer user_data; +} SetHostnameInfo; + +static void +set_transient_hostname_done (GObject *object, + GAsyncResult *res, + gpointer user_data) +{ + GDBusProxy *proxy = G_DBUS_PROXY (object); + gs_free SetHostnameInfo *info = user_data; + gs_unref_variant GVariant *result = NULL; + gs_free_error GError *error = NULL; + + result = g_dbus_proxy_call_finish (proxy, res, &error); + + if (error) { + _LOGW ("couldn't set the system hostname to '%s' using hostnamed: %s", + info->hostname, error->message); + } + + info->cb (info->hostname, !error, info->user_data); + g_free (info->hostname); +} + +void +nm_settings_set_transient_hostname (NMSettings *self, + const char *hostname, + NMSettingsSetHostnameCb cb, + gpointer user_data) +{ + NMSettingsPrivate *priv; + SetHostnameInfo *info; + + g_return_if_fail (NM_IS_SETTINGS (self)); + priv = NM_SETTINGS_GET_PRIVATE (self); + + if (!priv->hostname.hostnamed_proxy) { + cb (hostname, FALSE, user_data); + return; + } + + info = g_new0 (SetHostnameInfo, 1); + info->hostname = g_strdup (hostname); + info->cb = cb; + info->user_data = user_data; + + g_dbus_proxy_call (priv->hostname.hostnamed_proxy, + "SetHostname", + g_variant_new ("(sb)", hostname, FALSE), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + set_transient_hostname_done, + info); +} + static gboolean write_hostname (NMSettingsPrivate *priv, const char *hostname) { @@ -1549,7 +1613,7 @@ write_hostname (NMSettingsPrivate *priv, const char *hostname) NULL, &error); if (error) - nm_log_warn (LOGD_SETTINGS, "Could not set hostname: %s", error->message); + _LOGW ("could not set hostname: %s", error->message); return !error; } @@ -1595,7 +1659,7 @@ write_hostname (NMSettingsPrivate *priv, const char *hostname) g_free (hostname_eol); if (!ret) { - nm_log_warn (LOGD_SETTINGS, "Could not save hostname to %s: %s", file, error->message); + _LOGW ("could not save hostname to %s: %s", file, error->message); return FALSE; } @@ -1625,7 +1689,7 @@ pk_hostname_cb (NMAuthChain *chain, error = g_error_new (NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, "Error checking authorization: %s", - chain_error->message ? chain_error->message : "(unknown)"); + chain_error->message); } else if (result != NM_AUTH_CALL_RESULT_YES) { error = g_error_new_literal (NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_PERMISSION_DENIED, @@ -1721,9 +1785,9 @@ hostname_maybe_changed (NMSettings *settings) || (!new_hostname && priv->hostname.value) || (priv->hostname.value && new_hostname && strcmp (priv->hostname.value, new_hostname))) { - nm_log_info (LOGD_SETTINGS, "hostname changed from %s%s%s to %s%s%s", - NM_PRINT_FMT_QUOTED (priv->hostname.value, "\"", priv->hostname.value, "\"", "(none)"), - NM_PRINT_FMT_QUOTED (new_hostname, "\"", new_hostname, "\"", "(none)")); + _LOGI ("hostname changed from %s%s%s to %s%s%s", + NM_PRINT_FMT_QUOTED (priv->hostname.value, "\"", priv->hostname.value, "\"", "(none)"), + NM_PRINT_FMT_QUOTED (new_hostname, "\"", new_hostname, "\"", "(none)")); g_free (priv->hostname.value); priv->hostname.value = new_hostname; g_object_notify (G_OBJECT (settings), NM_SETTINGS_HOSTNAME); @@ -1894,9 +1958,9 @@ device_realized (NMDevice *device, GParamSpec *pspec, NMSettings *self) g_object_unref (connection); if (!added) { - nm_log_warn (LOGD_SETTINGS, "(%s) couldn't create default wired connection: %s", - nm_device_get_iface (device), - (error && error->message) ? error->message : "(unknown)"); + _LOGW ("(%s) couldn't create default wired connection: %s", + nm_device_get_iface (device), + error->message); g_clear_error (&error); return; } @@ -1909,9 +1973,9 @@ device_realized (NMDevice *device, GParamSpec *pspec, NMSettings *self) g_signal_connect (added, NM_SETTINGS_CONNECTION_REMOVED, G_CALLBACK (default_wired_connection_removed_cb), self); - nm_log_info (LOGD_SETTINGS, "(%s): created default wired connection '%s'", - nm_device_get_iface (device), - nm_settings_connection_get_id (added)); + _LOGI ("(%s): created default wired connection '%s'", + nm_device_get_iface (device), + nm_settings_connection_get_id (added)); } void @@ -2080,9 +2144,9 @@ hostnamed_properties_changed (GDBusProxy *proxy, hostname = g_variant_get_string (v_hostname, NULL); if (g_strcmp0 (priv->hostname.value, hostname) != 0) { - nm_log_info (LOGD_SETTINGS, "hostname changed from %s%s%s to %s%s%s", - NM_PRINT_FMT_QUOTED (priv->hostname.value, "\"", priv->hostname.value, "\"", "(none)"), - NM_PRINT_FMT_QUOTED (hostname, "\"", hostname, "\"", "(none)")); + _LOGI ("hostname changed from %s%s%s to %s%s%s", + NM_PRINT_FMT_QUOTED (priv->hostname.value, "\"", priv->hostname.value, "\"", "(none)"), + NM_PRINT_FMT_QUOTED (hostname, "\"", hostname, "\"", "(none)")); g_free (priv->hostname.value); priv->hostname.value = g_strdup (hostname); g_object_notify (G_OBJECT (user_data), NM_SETTINGS_HOSTNAME); @@ -2170,19 +2234,19 @@ nm_settings_start (NMSettings *self, GError **error) if (proxy) { variant = g_dbus_proxy_get_cached_property (proxy, "StaticHostname"); if (variant) { - nm_log_info (LOGD_SETTINGS, "hostname: using hostnamed"); + _LOGI ("hostname: using hostnamed"); priv->hostname.hostnamed_proxy = proxy; g_signal_connect (proxy, "g-properties-changed", G_CALLBACK (hostnamed_properties_changed), self); hostnamed_properties_changed (proxy, NULL, NULL, self); g_variant_unref (variant); } else { - nm_log_info (LOGD_SETTINGS, "hostname: couldn't get property from hostnamed"); + _LOGI ("hostname: couldn't get property from hostnamed"); g_object_unref (proxy); } } else { - nm_log_info (LOGD_SETTINGS, "hostname: hostnamed not used as proxy creation failed with: %s", - local_error->message); + _LOGI ("hostname: hostnamed not used as proxy creation failed with: %s", + local_error->message); g_clear_error (&local_error); } diff --git a/src/settings/nm-settings.h b/src/settings/nm-settings.h index 923b164b..051c2094 100644 --- a/src/settings/nm-settings.h +++ b/src/settings/nm-settings.h @@ -71,6 +71,8 @@ typedef struct { void (*agent_registered) (NMSettings *self, NMSecretAgent *agent); } NMSettingsClass; +typedef void (*NMSettingsSetHostnameCb) (const char *name, gboolean result, gpointer user_data); + GType nm_settings_get_type (void); NMSettings *nm_settings_new (void); @@ -127,4 +129,9 @@ gint nm_settings_sort_connections (gconstpointer a, gconstpointer b); gboolean nm_settings_get_startup_complete (NMSettings *self); +void nm_settings_set_transient_hostname (NMSettings *self, + const char *hostname, + NMSettingsSetHostnameCb cb, + gpointer user_data); + #endif /* __NM_SETTINGS_H__ */ diff --git a/src/settings/plugins/ibft/tests/test-ibft.c b/src/settings/plugins/ibft/tests/test-ibft.c index a9085478..9c98d891 100644 --- a/src/settings/plugins/ibft/tests/test-ibft.c +++ b/src/settings/plugins/ibft/tests/test-ibft.c @@ -181,7 +181,7 @@ test_read_ibft_malformed (gconstpointer user_data) g_assert (g_file_test (iscsiadm_path, G_FILE_TEST_EXISTS)); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*malformed iscsiadm record*"); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*malformed iscsiadm record*"); success = read_ibft_blocks (iscsiadm_path, &blocks, &error); g_assert_no_error (error); diff --git a/src/settings/plugins/ifcfg-rh/nm-ifcfg-rh.xml b/src/settings/plugins/ifcfg-rh/nm-ifcfg-rh.xml index 1f308dd4..c2a6cb34 100644 --- a/src/settings/plugins/ifcfg-rh/nm-ifcfg-rh.xml +++ b/src/settings/plugins/ifcfg-rh/nm-ifcfg-rh.xml @@ -2,28 +2,28 @@ <node name="/" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> <interface name="com.redhat.ifcfgrh1"> - <tp:docstring> + <annotation name="org.gtk.GDBus.DocString" value=" Utility methods for handling NM integration with standard Red Hat ifcfg files. - </tp:docstring> + " /> <method name="GetIfcfgDetails"> - <tp:docstring> + <annotation name="org.gtk.GDBus.DocString" value=" Given an ifcfg file, return various internal information about it. - </tp:docstring> + " /> <arg name="ifcfg" type="s" direction="in"> - <tp:docstring> + <annotation name="org.gtk.GDBus.DocString" value=" The full path to an ifcfg file. - </tp:docstring> + " /> </arg> <arg name="uuid" type="s" direction="out"> - <tp:docstring> + <annotation name="org.gtk.GDBus.DocString" value=" The UUID of the NM connection backed by this ifcfg file. If the ifcfg file does not contain a UUID tag, this UUID is generated by NM, otherwise the UUID from the ifcfg file is used. - </tp:docstring> + " /> </arg> <arg name="path" type="o" direction="out"> - <tp:docstring> + <annotation name="org.gtk.GDBus.DocString" value=" The object path of the NM connected backed by this ifcfg file. - </tp:docstring> + " /> </arg> </method> </interface> diff --git a/src/settings/plugins/ifcfg-rh/plugin.c b/src/settings/plugins/ifcfg-rh/plugin.c index d28e3bf6..1fb6b789 100644 --- a/src/settings/plugins/ifcfg-rh/plugin.c +++ b/src/settings/plugins/ifcfg-rh/plugin.c @@ -207,8 +207,10 @@ update_connection (SettingsPluginIfcfg *self, && !protect_existing_connection && (!protected_connections || !g_hash_table_contains (protected_connections, connection))) remove_connection (self, connection); - if (!source && !ignore_error) - _LOGW ("loading \"%s\" fails: %s", full_path, local ? local->message : "(unknown reason)"); + if (!source) { + _NMLOG (ignore_error ? LOGL_DEBUG : LOGL_WARN, + "loading \"%s\" fails: %s", full_path, local ? local->message : "(unknown reason)"); + } g_propagate_error (error, local); return NULL; } diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c index ca512fc6..41ffa27d 100644 --- a/src/settings/plugins/ifcfg-rh/reader.c +++ b/src/settings/plugins/ifcfg-rh/reader.c @@ -3076,6 +3076,13 @@ fill_8021x (shvarFile *ifcfg, read_8021x_list_value (ifcfg, "IEEE_8021X_PHASE2_ALTSUBJECT_MATCHES", s_8021x, NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES); + value = svGetValue (ifcfg, "IEEE_8021X_DOMAIN_SUFFIX_MATCH", FALSE); + g_object_set (s_8021x, NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH, value, NULL); + g_free (value); + value = svGetValue (ifcfg, "IEEE_8021X_PHASE2_DOMAIN_SUFFIX_MATCH", FALSE); + g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH, value, NULL); + g_free (value); + if (list) g_strfreev (list); if (keys) @@ -4993,14 +5000,24 @@ connection_from_file_full (const char *filename, type = svGetValue (parsed, "TYPE", FALSE); if (!type) { + gs_free char *tmp = NULL; char *device; + if ((tmp = svGetValue (parsed, "IPV6TUNNELIPV4", FALSE))) { + if (out_ignore_error) + *out_ignore_error = TRUE; + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, + "Ignoring unsupported connection due to IPV6TUNNELIPV4"); + goto done; + } + device = svGetValue (parsed, "DEVICE", FALSE); if (!device) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "File '%s' had neither TYPE nor DEVICE keys.", filename); goto done; } + g_assert (device[0]); if (!strcmp (device, "lo")) { if (out_ignore_error) @@ -5018,8 +5035,51 @@ connection_from_file_full (const char *filename, type = g_strdup (TYPE_VLAN); else if (is_wifi_device (device, parsed)) type = g_strdup (TYPE_WIRELESS); - else - type = g_strdup (TYPE_ETHERNET); + else { + gs_free char *p_path = NULL; + char *p_device; + gsize i; + + /* network-functions detects DEVICETYPE based on the ifcfg-* name and the existence + * of a ifup script: + * [ -z "$DEVICETYPE" ] && DEVICETYPE=$(echo ${DEVICE} | sed "s/[0-9]*$//") + * later... + * OTHERSCRIPT="/etc/sysconfig/network-scripts/ifup-${DEVICETYPE}" + * */ +#define IFUP_PATH_PREFIX "/etc/sysconfig/network-scripts/ifup-" + i = strlen (device); + p_path = g_malloc (NM_STRLEN (IFUP_PATH_PREFIX) + i + 1); + p_device = &p_path[NM_STRLEN (IFUP_PATH_PREFIX)]; + memcpy (p_device, device, i + 1); + + /* strip trailing numbers */ + while (i >= 1) { + i--; + if (p_device[i] < '0' || p_device[i] > '9') + break; + p_device[i] = '\0'; + } + + if (nm_streq (p_device, "eth")) + type = g_strdup (TYPE_ETHERNET); + else if (nm_streq (p_device, "wireless")) + type = g_strdup (TYPE_WIRELESS); + else if (p_device[0]) { + memcpy (p_path, IFUP_PATH_PREFIX, NM_STRLEN (IFUP_PATH_PREFIX)); + if (access (p_path, X_OK) == 0) { + /* for all other types, this is not something we want to handle. */ + if (out_ignore_error) + *out_ignore_error = TRUE; + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, + "Ignore script for unknown device type which has a matching %s script", + p_path); + goto done; + } + } + + if (!type) + type = g_strdup (TYPE_ETHERNET); + } } else { /* For the unit tests, there won't necessarily be any * adapters of the connection's type in the system so the diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am index 36e52af4..fc759e6d 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am @@ -77,6 +77,7 @@ EXTRA_DIST = \ ifcfg-test-ibft \ ifcfg-test-static-routes-legacy \ route-test-static-routes-legacy \ + ifcfg-test-sit-ignore \ ifcfg-test-wired-static-routes \ route-test-wired-static-routes \ ifcfg-test-wired-static-routes-legacy \ diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in index 2152961c..e98ea93c 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in @@ -473,6 +473,7 @@ EXTRA_DIST = \ ifcfg-test-ibft \ ifcfg-test-static-routes-legacy \ route-test-static-routes-legacy \ + ifcfg-test-sit-ignore \ ifcfg-test-wired-static-routes \ route-test-wired-static-routes \ ifcfg-test-wired-static-routes-legacy \ diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sit-ignore b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sit-ignore new file mode 100644 index 00000000..a2581db6 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sit-ignore @@ -0,0 +1,12 @@ +# this ifcfg-file represents a "sit" type without explicit TYPE. +# Such connection types are not supported by NetworkManager and +# the connection should be ignored based on the presence of +# IPV6TUNNELIPV4. + +DEVICE=sit1 +BOOTPROTO=none +ONBOOT=yes +IPV6INIT=yes +IPV6TUNNELIPV4=5.4.3.6 +IPV6TUNNELIPV4LOCAL=172.17.1.9 +IPV6ADDR=2001:470:2:3:4::2/64 diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index 8ca5c8bb..5ed25fda 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -310,7 +310,7 @@ test_read_miscellaneous_variables (void) int mac_blacklist_num, i; guint64 expected_timestamp = 0; - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*invalid MAC in HWADDR_BLACKLIST 'XX:aa:invalid'*"); connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-misc-variables", NULL, TYPE_ETHERNET, NULL); @@ -563,7 +563,7 @@ test_read_wired_static_no_prefix (gconstpointer user_data) file = g_strdup_printf (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wired-static-no-prefix-%u", expected_prefix); expected_id = g_strdup_printf ("System test-wired-static-no-prefix-%u", expected_prefix); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*missing PREFIX, assuming*"); connection = _connection_from_file (file, NULL, TYPE_ETHERNET, NULL); g_test_assert_expected_messages (); @@ -785,7 +785,7 @@ test_read_wired_global_gateway_ignore (void) NMSettingIPConfig *s_ip4; char *unmanaged = NULL; - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*ignoring GATEWAY (/etc/sysconfig/network) for * because the connection has no static addresses"); connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-global-gateway-ignore", TEST_IFCFG_DIR"/network-scripts/network-test-wired-global-gateway-ignore", @@ -1120,7 +1120,7 @@ test_read_wired_ipv6_manual (void) NMIPAddress *ip6_addr; NMIPRoute *ip6_route; - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*ignoring manual default route*"); connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-ipv6-manual", NULL, TYPE_ETHERNET, &unmanaged); @@ -1492,7 +1492,7 @@ test_read_write_802_1X_subj_matches (void) NMSetting8021x *s_8021x; char *written = NULL; - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*missing IEEE_8021X_CA_CERT*peap*"); connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-802-1X-subj-matches", NULL, TYPE_ETHERNET, NULL); @@ -1518,7 +1518,7 @@ test_read_write_802_1X_subj_matches (void) TEST_SCRATCH_DIR "/network-scripts/", &written); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*missing IEEE_8021X_CA_CERT*peap*"); reread = _connection_from_file (written, NULL, TYPE_ETHERNET, NULL); g_test_assert_expected_messages (); @@ -1683,7 +1683,7 @@ test_read_wired_aliases_bad (const char *base, const char *expected_id) static void test_read_wired_aliases_bad_1 (void) { - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*aliasem1:1*has no DEVICE*"); test_read_wired_aliases_bad (TEST_IFCFG_DIR "/network-scripts/ifcfg-aliasem1", "System aliasem1"); } @@ -1691,7 +1691,7 @@ test_read_wired_aliases_bad_1 (void) static void test_read_wired_aliases_bad_2 (void) { - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*aliasem2:1*has invalid DEVICE*"); test_read_wired_aliases_bad (TEST_IFCFG_DIR "/network-scripts/ifcfg-aliasem2", "System aliasem2"); } @@ -3560,9 +3560,6 @@ test_write_wired_static (void) TEST_SCRATCH_DIR "/network-scripts/", &testfile); - /* reread will be normalized, so we must normalize connection too. */ - nm_connection_normalize (connection, NULL, NULL, NULL); - reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL); unlink (testfile); @@ -7329,7 +7326,7 @@ test_read_vlan_reorder_hdr_1 (void) NMConnection *connection; NMSettingVlan *s_vlan; - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*REORDER_HDR key is deprecated, use VLAN_FLAGS*"); connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-vlan-reorder-hdr-1", NULL, TYPE_ETHERNET, NULL); @@ -8167,7 +8164,7 @@ test_read_dcb_bad_booleans (void) { gs_free_error GError *error = NULL; - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*invalid DCB_PG_STRICT value*not all 0s and 1s*"); _connection_from_file_fail (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-bad-booleans", NULL, TYPE_ETHERNET, &error); @@ -8182,7 +8179,7 @@ test_read_dcb_short_booleans (void) { gs_free_error GError *error = NULL; - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*DCB_PG_STRICT value*8 characters*"); _connection_from_file_fail (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-short-booleans", NULL, TYPE_ETHERNET, &error); @@ -8197,7 +8194,7 @@ test_read_dcb_bad_uints (void) { gs_free_error GError *error = NULL; - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*invalid DCB_PG_UP2TC value*not 0 - 7*"); _connection_from_file_fail (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-bad-uints", NULL, TYPE_ETHERNET, &error); @@ -8212,7 +8209,7 @@ test_read_dcb_short_uints (void) { gs_free_error GError *error = NULL; - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*DCB_PG_UP2TC value*8 characters*"); _connection_from_file_fail (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-short-uints", NULL, TYPE_ETHERNET, &error); @@ -8227,7 +8224,7 @@ test_read_dcb_bad_percent (void) { gs_free_error GError *error = NULL; - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*invalid DCB_PG_PCT percentage value*"); _connection_from_file_fail (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-bad-percent", NULL, TYPE_ETHERNET, &error); @@ -8242,7 +8239,7 @@ test_read_dcb_short_percent (void) { gs_free_error GError *error = NULL; - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*invalid DCB_PG_PCT percentage list value*"); _connection_from_file_fail (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-short-percent", NULL, TYPE_ETHERNET, &error); @@ -8257,7 +8254,7 @@ test_read_dcb_pgpct_not_100 (void) { gs_free_error GError *error = NULL; - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*DCB_PG_PCT percentages do not equal 100*"); _connection_from_file_fail (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-pgpct-not-100", NULL, TYPE_ETHERNET, &error); @@ -8738,6 +8735,20 @@ test_read_vlan_trailing_spaces (void) g_object_unref (connection); } +/*****************************************************************************/ + +static void +test_sit_read_ignore (void) +{ + gs_free_error GError *error = NULL; + + _connection_from_file_fail (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-sit-ignore", + NULL, TYPE_ETHERNET, &error); + nmtst_assert_error (error, 0, 0, "*Ignoring unsupported connection due to IPV6TUNNELIPV4*"); +} + +/*****************************************************************************/ + #define TPATH "/settings/plugins/ifcfg-rh/" @@ -8937,10 +8948,8 @@ int main (int argc, char **argv) g_test_add_func (TPATH "wired/write-missing-ipv6", test_write_ethernet_missing_ipv6); g_test_add_func (TPATH "write-dns-options", test_write_dns_options); - /* iSCSI / ibft */ g_test_add_func (TPATH "ibft/ignored", test_read_ibft_ignored); - /* Data Center Bridging (DCB) */ g_test_add_func (TPATH "dcb/read-basic", test_read_dcb_basic); g_test_add_func (TPATH "dcb/write-basic", test_write_dcb_basic); g_test_add_func (TPATH "dcb/default-app-priorities", test_read_dcb_default_app_priorities); @@ -8956,7 +8965,6 @@ int main (int argc, char **argv) g_test_add_data_func (TPATH "fcoe/write-fabric", (gpointer) NM_SETTING_DCB_FCOE_MODE_FABRIC, test_write_fcoe_mode); g_test_add_data_func (TPATH "fcoe/write-vn2vn", (gpointer) NM_SETTING_DCB_FCOE_MODE_VN2VN, test_write_fcoe_mode); - /* bonding */ g_test_add_func (TPATH "bond/read-master", test_read_bond_main); g_test_add_func (TPATH "bond/read-slave", test_read_bond_slave); g_test_add_func (TPATH "bond/read-slave-ib", test_read_bond_slave_ib); @@ -8965,20 +8973,20 @@ int main (int argc, char **argv) g_test_add_func (TPATH "bond/write-slave-ib", test_write_bond_slave_ib); g_test_add_func (TPATH "bond/bonding-opts-numeric-mode", test_read_bond_opts_mode_numeric); - /* bridging */ g_test_add_func (TPATH "bridge/read-master", test_read_bridge_main); g_test_add_func (TPATH "bridge/write-master", test_write_bridge_main); g_test_add_func (TPATH "bridge/read-component", test_read_bridge_component); g_test_add_func (TPATH "bridge/write-component", test_write_bridge_component); g_test_add_func (TPATH "bridge/read-missing-stp", test_read_bridge_missing_stp); - /* Team */ g_test_add_func (TPATH "team/read-master", test_read_team_master); g_test_add_func (TPATH "team/write-master", test_write_team_master); g_test_add_func (TPATH "team/read-port", test_read_team_port); g_test_add_func (TPATH "team/write-port", test_write_team_port); g_test_add_func (TPATH "team/read-port-empty-config", test_read_team_port_empty_config); + g_test_add_func (TPATH "sit/read/ignore", test_sit_read_ignore); + /* Stuff we expect to fail for now */ g_test_add_func (TPATH "pppoe/write-wired", test_write_wired_pppoe); g_test_add_func (TPATH "vpn/write", test_write_vpn); diff --git a/src/settings/plugins/ifcfg-rh/utils.h b/src/settings/plugins/ifcfg-rh/utils.h index 329f4547..752d08a6 100644 --- a/src/settings/plugins/ifcfg-rh/utils.h +++ b/src/settings/plugins/ifcfg-rh/utils.h @@ -26,7 +26,7 @@ #include "shvar.h" #include "common.h" -#define NM_IFCFG_CONNECTION_LOG_PATH(path) str_if_set (path,"in-memory") +#define NM_IFCFG_CONNECTION_LOG_PATH(path) ((path) ?: "in-memory") #define NM_IFCFG_CONNECTION_LOG_FMT "%s (%s,\"%s\")" #define NM_IFCFG_CONNECTION_LOG_ARG(con) NM_IFCFG_CONNECTION_LOG_PATH (nm_settings_connection_get_filename ((NMSettingsConnection *) (con))), nm_connection_get_uuid ((NMConnection *) (con)), nm_connection_get_id ((NMConnection *) (con)) #define NM_IFCFG_CONNECTION_LOG_FMTD "%s (%s,\"%s\",%p)" diff --git a/src/settings/plugins/ifcfg-rh/writer.c b/src/settings/plugins/ifcfg-rh/writer.c index e7d64379..c17824d6 100644 --- a/src/settings/plugins/ifcfg-rh/writer.c +++ b/src/settings/plugins/ifcfg-rh/writer.c @@ -582,6 +582,13 @@ write_8021x_setting (NMConnection *connection, svSetValue (ifcfg, "IEEE_8021X_PHASE2_ALTSUBJECT_MATCHES", str->str, FALSE); g_string_free (str, TRUE); + svSetValue (ifcfg, "IEEE_8021X_DOMAIN_SUFFIX_MATCH", + nm_setting_802_1x_get_domain_suffix_match (s_8021x), + FALSE); + svSetValue (ifcfg, "IEEE_8021X_PHASE2_DOMAIN_SUFFIX_MATCH", + nm_setting_802_1x_get_phase2_domain_suffix_match (s_8021x), + FALSE); + success = write_8021x_certs (s_8021x, FALSE, ifcfg, error); if (success) { /* phase2/inner certs */ diff --git a/src/settings/plugins/ifnet/connection_parser.c b/src/settings/plugins/ifnet/connection_parser.c index bf8b9a42..d9ff97dc 100644 --- a/src/settings/plugins/ifnet/connection_parser.c +++ b/src/settings/plugins/ifnet/connection_parser.c @@ -362,11 +362,17 @@ eap_peap_reader (const char *eap_method, } pos = strchr (*iter, '='); - pos++; - lower = g_ascii_strdown (pos, -1); - g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, lower, - NULL); - g_free (lower); + if (pos && *pos) { + pos++; + lower = g_ascii_strdown (pos, -1); + g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, lower, + NULL); + g_free (lower); + } else { + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, + "No IEEE_8021X_INNER_AUTH_METHOD."); + goto done; + } break; } @@ -513,7 +519,7 @@ read_mac_address (const char *conn_name, const char **mac, GError **error) return TRUE; } -static void +static gboolean make_wired_connection_setting (NMConnection *connection, const char *conn_name, GError **error) @@ -538,22 +544,21 @@ make_wired_connection_setting (NMConnection *connection, (guint32) mtu, NULL); } - if (read_mac_address (conn_name, &mac, error)) { - if (mac) { - g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, - mac, NULL); - } - } else { + if (!read_mac_address (conn_name, &mac, error)) { g_object_unref (s_wired); - s_wired = NULL; + return FALSE; } - if (s_wired) - nm_connection_add_setting (connection, NM_SETTING (s_wired)); + + if (mac) + g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, mac, NULL); + nm_connection_add_setting (connection, NM_SETTING (s_wired)); + + return TRUE; } /* add NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, * NM_SETTING_IP_CONFIG_DHCP_CLIENT_ID in future*/ -static void +static gboolean make_ip4_setting (NMConnection *connection, const char *conn_name, GError **error) @@ -578,7 +583,7 @@ make_ip4_setting (NMConnection *connection, g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Unknown config for %s", conn_name); g_object_unref (ip4_setting); - return; + return FALSE; } if (strstr (method, "dhcp")) g_object_set (ip4_setting, @@ -591,19 +596,19 @@ make_ip4_setting (NMConnection *connection, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL, NM_SETTING_IP_CONFIG_NEVER_DEFAULT, FALSE, NULL); nm_connection_add_setting (connection, NM_SETTING (ip4_setting)); - return; + return TRUE; } else if (strstr (method, "shared")) { g_object_set (ip4_setting, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_SHARED, NM_SETTING_IP_CONFIG_NEVER_DEFAULT, FALSE, NULL); nm_connection_add_setting (connection, NM_SETTING (ip4_setting)); - return; + return TRUE; } else { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Unknown config for %s", conn_name); g_object_unref (ip4_setting); - return; + return FALSE; } nm_log_info (LOGD_SETTINGS, "Using %s method for %s", method, conn_name); }else { @@ -613,7 +618,7 @@ make_ip4_setting (NMConnection *connection, "Ifnet plugin: can't aquire ip configuration for %s", conn_name); g_object_unref (ip4_setting); - return; + return FALSE; } /************** add all ip settings to the connection**********/ while (iblock) { @@ -735,9 +740,11 @@ make_ip4_setting (NMConnection *connection, /* Finally add setting to connection */ nm_connection_add_setting (connection, NM_SETTING (ip4_setting)); + + return TRUE; } -static void +static gboolean make_ip6_setting (NMConnection *connection, const char *conn_name, GError **error) @@ -875,12 +882,12 @@ make_ip6_setting (NMConnection *connection, done: nm_connection_add_setting (connection, NM_SETTING (s_ip6)); - return; + return TRUE; error: g_object_unref (s_ip6); nm_log_warn (LOGD_SETTINGS, " Ignore IPv6 for %s", conn_name); - return; + return FALSE; } static NMSetting * @@ -1018,14 +1025,6 @@ make_leap_setting (const char *ssid, GError **error) wsec = NM_SETTING_WIRELESS_SECURITY (nm_setting_wireless_security_new ()); - value = wpa_get_value (ssid, "key_mgmt"); - if (!value || strcmp (value, "IEEE8021X")) - goto error; /* Not LEAP */ - - value = wpa_get_value (ssid, "eap"); - if (!value || strcasecmp (value, "LEAP")) - goto error; /* Not LEAP */ - value = wpa_get_value (ssid, "password"); if (value && strlen (value)) g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD, @@ -1444,12 +1443,6 @@ make_wpa_setting (const char *ssid, if (value) adhoc = strcmp (value, "1") == 0 ? TRUE : FALSE; - value = wpa_get_value (ssid, "key_mgmt"); - /* Not WPA or Dynamic WEP */ - if (!value) - goto error; - if (strcmp (value, "WPA-PSK") && strcmp (value, "WPA-EAP")) - goto error; /* Pairwise and Group ciphers */ fill_wpa_ciphers (ssid, wsec, FALSE, adhoc); fill_wpa_ciphers (ssid, wsec, TRUE, adhoc); @@ -1464,6 +1457,7 @@ make_wpa_setting (const char *ssid, } + value = wpa_get_value (ssid, "key_mgmt"); if (!strcmp (value, "WPA-PSK")) { char *psk = parse_wpa_psk (wpa_get_value (ssid, "psk"), error); @@ -1522,8 +1516,6 @@ make_wireless_security_setting (const char *conn_name, g_return_val_if_fail (conn_name != NULL && strcmp (ifnet_get_data (conn_name, "type"), "ppp") != 0, NULL); - if (!wpa_get_value (conn_name, "ssid")) - return NULL; nm_log_info (LOGD_SETTINGS, "updating wireless security settings (%s).", conn_name); ssid = conn_name; @@ -1531,19 +1523,22 @@ make_wireless_security_setting (const char *conn_name, if (value) adhoc = strcmp (value, "1") == 0 ? TRUE : FALSE; - if (!adhoc) { - wsec = make_leap_setting (ssid, error); - if (error && *error) - goto error; - } - if (!wsec) { + value = wpa_get_value (ssid, "key_mgmt"); + if (!adhoc && g_strcmp0 (value, "IEEE8021X") == 0) { + value = wpa_get_value (ssid, "eap"); + if (value && strcasecmp (value, "LEAP") == 0) { + wsec = make_leap_setting (ssid, error); + if (wsec == NULL) + goto error; + } + } else if (g_strcmp0 (value, "WPA-PSK") == 0 || g_strcmp0 (value, "WPA-EAP") == 0) { wsec = make_wpa_setting (ssid, basepath, s_8021x, error); - if (error && *error) + if (wsec == NULL) goto error; } if (!wsec) { wsec = make_wep_setting (ssid, error); - if (error && *error) + if (wsec == NULL) goto error; } @@ -1559,7 +1554,7 @@ error: } /* Currently only support username and password */ -static void +static gboolean make_pppoe_connection_setting (NMConnection *connection, const char *conn_name, GError **error) @@ -1575,7 +1570,7 @@ make_pppoe_connection_setting (NMConnection *connection, if (!value) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "ppp requires at lease a username"); - return; + return FALSE; } g_object_set (s_pppoe, NM_SETTING_PPPOE_USERNAME, value, NULL); @@ -1591,6 +1586,8 @@ make_pppoe_connection_setting (NMConnection *connection, /* PPP setting */ s_ppp = (NMSettingPpp *) nm_setting_ppp_new (); nm_connection_add_setting (connection, NM_SETTING (s_ppp)); + + return TRUE; } NMConnection * @@ -1644,18 +1641,13 @@ ifnet_update_connection_from_config_block (const char *conn_name, if (!strcmp (NM_SETTING_WIRED_SETTING_NAME, type) || !strcmp (NM_SETTING_PPPOE_SETTING_NAME, type)) { /* wired setting */ - make_wired_connection_setting (connection, conn_name, error); - if (error && *error) { - nm_log_warn (LOGD_SETTINGS, "Found error: %s", (*error)->message); + if (!make_wired_connection_setting (connection, conn_name, error)) goto error; - } + /* pppoe setting */ - if (!strcmp (NM_SETTING_PPPOE_SETTING_NAME, type)) - make_pppoe_connection_setting (connection, conn_name, - error); - if (error && *error) { - nm_log_warn (LOGD_SETTINGS, "Found error: %s", (*error)->message); - goto error; + if (!strcmp (NM_SETTING_PPPOE_SETTING_NAME, type)) { + if (!make_pppoe_connection_setting (connection, conn_name, error)) + goto error; } } else if (!strcmp (NM_SETTING_WIRELESS_SETTING_NAME, type)) { /* wireless setting */ @@ -1666,50 +1658,33 @@ ifnet_update_connection_from_config_block (const char *conn_name, goto error; nm_connection_add_setting (connection, wireless_setting); - if (error && *error) { - nm_log_warn (LOGD_SETTINGS, "Found error: %s", (*error)->message); - goto error; - } - /* wireless security setting */ - wsec = make_wireless_security_setting (conn_name, basepath, &s_8021x, error); - if (wsec) { + if (wpa_get_value (conn_name, "ssid")) { + wsec = make_wireless_security_setting (conn_name, basepath, &s_8021x, error); + if (!wsec) + goto error; nm_connection_add_setting (connection, NM_SETTING (wsec)); if (s_8021x) nm_connection_add_setting (connection, NM_SETTING (s_8021x)); } - - if (error && *error) { - nm_log_warn (LOGD_SETTINGS, "Found error: %s", (*error)->message); - goto error; - } - } else goto error; /* IPv4 setting */ - make_ip4_setting (connection, conn_name, error); - if (error && *error) { - nm_log_warn (LOGD_SETTINGS, "Found error: %s", (*error)->message); + if (!make_ip4_setting (connection, conn_name, error)) goto error; - } /* IPv6 setting */ - make_ip6_setting (connection, conn_name, error); - if (error && *error) { - nm_log_warn (LOGD_SETTINGS, "Found error: %s", (*error)->message); + if (!make_ip6_setting (connection, conn_name, error)) goto error; - } - success = nm_connection_verify (connection, error); - if (error && *error) - nm_log_warn (LOGD_SETTINGS, "Found error: %s", (*error)->message); - else + if (nm_connection_verify (connection, error)) { nm_log_info (LOGD_SETTINGS, "Connection verified %s:%d", conn_name, success); - if (!success) + } else { goto error; - return connection; + } + return connection; error: g_object_unref (connection); return NULL; @@ -2493,8 +2468,8 @@ write_ip4_setting (NMConnection *connection, const char *conn_name, GError **err return success; } -static gboolean -write_route6_file (NMSettingIPConfig *s_ip6, const char *conn_name, GError **error) +static void +write_route6_file (NMSettingIPConfig *s_ip6, const char *conn_name) { NMIPRoute *route; const char *next_hop; @@ -2502,11 +2477,10 @@ write_route6_file (NMSettingIPConfig *s_ip6, const char *conn_name, GError **err GString *routes_string; const char *old_routes; - g_return_val_if_fail (s_ip6 != NULL, FALSE); + g_return_if_fail (s_ip6 != NULL); num = nm_setting_ip_config_get_num_routes (s_ip6); - if (num == 0) { - return TRUE; - } + if (num == 0) + return; old_routes = ifnet_get_data (conn_name, "routes"); routes_string = g_string_new (old_routes); @@ -2527,8 +2501,6 @@ write_route6_file (NMSettingIPConfig *s_ip6, const char *conn_name, GError **err if (num > 0) ifnet_set_data (conn_name, "routes", routes_string->str); g_string_free (routes_string, TRUE); - - return TRUE; } static gboolean @@ -2645,9 +2617,7 @@ write_ip6_setting (NMConnection *connection, const char *conn_name, GError **err g_string_free (searches, TRUE); } - write_route6_file (s_ip6, conn_name, error); - if (error && *error) - return FALSE; + write_route6_file (s_ip6, conn_name); return TRUE; } diff --git a/src/settings/plugins/ifnet/net_parser.c b/src/settings/plugins/ifnet/net_parser.c index cad34f06..6e1061c6 100644 --- a/src/settings/plugins/ifnet/net_parser.c +++ b/src/settings/plugins/ifnet/net_parser.c @@ -552,7 +552,7 @@ gboolean ifnet_flush_to_file (const char *config_file, gchar **out_backup) { GIOChannel *channel; - GError **error = NULL; + GError *error = NULL; gpointer key, value, name, network; GHashTableIter iter, iter_network; GList *list_iter; @@ -579,32 +579,36 @@ ifnet_flush_to_file (const char *config_file, gchar **out_backup) g_io_channel_write_chars (channel, "#Generated by NetworkManager\n" "###### Global Configuration ######\n", - -1, &bytes_written, error); + -1, &bytes_written, &error); + if (error) + goto done; + /* Writing global data */ while (g_hash_table_iter_next (&iter, &key, &value)) { out_line = g_strdup_printf ("%s=\"%s\"\n", (gchar *) key, (gchar *) value); g_io_channel_write_chars (channel, out_line, -1, - &bytes_written, error); - if (bytes_written == 0 || (error && *error)) - break; + &bytes_written, &error); + if (bytes_written == 0 || error) + goto done; g_free (out_line); } - if (error && *error) { - nm_log_warn (LOGD_SETTINGS, "Found error: %s", (*error)->message); - goto done; - } /* Writing connection data */ g_io_channel_write_chars (channel, "\n###### Connection Configuration ######\n", - -1, &bytes_written, error); + -1, &bytes_written, &error); + if (error) + goto done; + g_hash_table_iter_init (&iter, conn_table); while (g_hash_table_iter_next (&iter, &name, &network)) { g_hash_table_iter_init (&iter_network, (GHashTable *) network); g_io_channel_write_chars (channel, "#----------------------------------\n", - -1, &bytes_written, error); + -1, &bytes_written, &error); + if (error) + goto done; while (g_hash_table_iter_next (&iter_network, &key, &value)) { if (!g_str_has_prefix ((gchar *) key, "name") @@ -627,51 +631,47 @@ ifnet_flush_to_file (const char *config_file, gchar **out_backup) ("%s_%s=\"%s\"\n", (gchar *) key, (gchar *) name, (gchar *) value); - g_io_channel_write_chars - (channel, out_line, -1, - &bytes_written, error); - if (bytes_written == 0 || (error && *error)) - break; + g_io_channel_write_chars (channel, out_line, -1, &bytes_written, &error); + if (bytes_written == 0 || error) + goto done; g_free (out_line); } } } - if (error && *error) { - nm_log_warn (LOGD_SETTINGS, "Found error: %s", (*error)->message); - goto done; - } /* Writing reserved functions */ if (functions_list) { g_io_channel_write_chars (channel, "\n###### Reserved Functions ######\n", - -1, &bytes_written, error); + -1, &bytes_written, &error); + if (error) + goto done; + /* Writing functions */ for (list_iter = functions_list; list_iter; list_iter = g_list_next (list_iter)) { out_line = g_strdup_printf ("%s\n", (gchar *) list_iter->data); g_io_channel_write_chars (channel, out_line, -1, - &bytes_written, error); - if (bytes_written == 0 || (error && *error)) - break; + &bytes_written, &error); + if (bytes_written == 0 || error) + goto done; g_free (out_line); } - if (error && *error) { - nm_log_warn (LOGD_SETTINGS, "Found error: %s", (*error)->message); - goto done; - } } - g_io_channel_flush (channel, error); - if (error && *error) { - nm_log_warn (LOGD_SETTINGS, "Found error: %s", (*error)->message); + g_io_channel_flush (channel, &error); + if (error) goto done; - } result = TRUE; net_parser_data_changed = FALSE; done: + if (error) { + nm_log_warn (LOGD_SETTINGS, "Error writing the configuration file: %s", error->message); + g_error_free (error); + } + if (result && out_backup) *out_backup = backup; else diff --git a/src/settings/plugins/ifnet/net_utils.c b/src/settings/plugins/ifnet/net_utils.c index 1944e478..bd5d65d5 100644 --- a/src/settings/plugins/ifnet/net_utils.c +++ b/src/settings/plugins/ifnet/net_utils.c @@ -800,18 +800,27 @@ gchar *backup_file (const gchar* target) { GFile *source, *backup; gchar* backup_path; - GError **error = NULL; + GError *error = NULL; source = g_file_new_for_path (target); + + if (!g_file_query_exists (source, NULL)) { + g_object_unref (source); + return NULL; + } + backup_path = g_strdup_printf ("%s.bak", target); backup = g_file_new_for_path (backup_path); - g_file_copy (source, backup, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, error); - if (error && *error) { - nm_log_warn (LOGD_SETTINGS, "Backup failed: %s", (*error)->message); + if (!g_file_copy (source, backup, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, &error)) { + nm_log_warn (LOGD_SETTINGS, "Backup failed: %s", error->message); g_free (backup_path); backup_path = NULL; + g_error_free (error); } + g_object_unref (source); + g_object_unref (backup); + return backup_path; } diff --git a/src/settings/plugins/ifnet/nm-ifnet-connection.c b/src/settings/plugins/ifnet/nm-ifnet-connection.c index 84515519..b661b03e 100644 --- a/src/settings/plugins/ifnet/nm-ifnet-connection.c +++ b/src/settings/plugins/ifnet/nm-ifnet-connection.c @@ -68,6 +68,8 @@ nm_ifnet_connection_new (NMConnection *source, const char *conn_name) else { tmp = ifnet_update_connection_from_config_block (conn_name, NULL, &error); if (!tmp) { + nm_log_warn (LOGD_SETTINGS, "Could not read connection '%s': %s", + conn_name, error->message); g_error_free (error); return NULL; } @@ -79,11 +81,14 @@ nm_ifnet_connection_new (NMConnection *source, const char *conn_name) object = (GObject *) g_object_new (NM_TYPE_IFNET_CONNECTION, NULL); g_assert (object); NM_IFNET_CONNECTION_GET_PRIVATE (object)->conn_name = g_strdup (conn_name); - nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (object), - tmp, - update_unsaved, - NULL, - NULL); + if (!nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (object), + tmp, + update_unsaved, + NULL, + NULL)) { + g_object_unref (object); + return NULL; + } g_object_unref (tmp); return NM_IFNET_CONNECTION (object); diff --git a/src/settings/plugins/ifnet/tests/test-ifnet.c b/src/settings/plugins/ifnet/tests/test-ifnet.c index c870152b..3035fdb1 100644 --- a/src/settings/plugins/ifnet/tests/test-ifnet.c +++ b/src/settings/plugins/ifnet/tests/test-ifnet.c @@ -134,7 +134,7 @@ test_convert_ipv4_config_block (void) check_ip_block (iblock, "192.168.4.121", 24, "202.117.16.1"); destroy_ip_block (iblock); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*Can't handle IPv4 address*202.117.16.1211*"); iblock = convert_ip4_config_block ("eth2"); g_test_assert_expected_messages (); @@ -142,7 +142,7 @@ test_convert_ipv4_config_block (void) check_ip_block (iblock, "192.168.4.121", 24, NULL); destroy_ip_block (iblock); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*missing netmask or prefix*"); iblock = convert_ip4_config_block ("eth3"); g_assert (iblock == NULL); @@ -216,9 +216,9 @@ test_new_connection (void) GError *error = NULL; NMConnection *connection; - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*Can't handle IPv4 address*202.117.16.1211*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*Can't handle IPv6 address*202.117.16.1211*"); connection = ifnet_update_connection_from_config_block ("eth2", NULL, &error); g_test_assert_expected_messages (); @@ -245,7 +245,7 @@ test_new_connection (void) static void kill_backup (char **path) { - if (path) { + if (*path) { unlink (*path); g_free (*path); *path = NULL; @@ -306,9 +306,9 @@ test_add_connection (void) kill_backup (&backup); g_object_unref (connection); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*Can't handle ipv4 address: brd, missing netmask or prefix*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*Can't handle ipv4 address: 202.117.16.255, missing netmask or prefix*"); connection = ifnet_update_connection_from_config_block ("myxjtu2", basepath, NULL); g_test_assert_expected_messages (); @@ -349,10 +349,8 @@ test_missing_config (void) GError *error = NULL; NMConnection *connection; - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, - "*Unknown config for eth8*"); connection = ifnet_update_connection_from_config_block ("eth8", NULL, &error); - g_test_assert_expected_messages (); + g_assert_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION); g_assert (connection == NULL && error != NULL); } diff --git a/src/settings/plugins/ifnet/wpa_parser.c b/src/settings/plugins/ifnet/wpa_parser.c index 501bca7a..8e2559b3 100644 --- a/src/settings/plugins/ifnet/wpa_parser.c +++ b/src/settings/plugins/ifnet/wpa_parser.c @@ -365,7 +365,7 @@ gboolean wpa_flush_to_file (const char *config_file) { GIOChannel *channel; - GError **error = NULL; + GError *error = NULL; gpointer key, value, ssid, security; GHashTableIter iter, iter_security; gchar *out_line; @@ -389,25 +389,27 @@ wpa_flush_to_file (const char *config_file) g_io_channel_write_chars (channel, "#Generated by NetworkManager\n" "###### Global Configuration ######\n", - -1, &bytes_written, error); + -1, &bytes_written, &error); + if (error) + goto done; /* Writing global information */ while (g_hash_table_iter_next (&iter, &key, &value)) { out_line = g_strdup_printf ("%s=%s\n", (gchar *) key, (gchar *) value); g_io_channel_write_chars (channel, out_line, -1, &bytes_written, - error); - if (bytes_written == 0 || (error && *error)) + &error); + if (bytes_written == 0 || error) break; g_free (out_line); } - if (error && *error) { - nm_log_warn (LOGD_SETTINGS, "Found error: %s", (*error)->message); + if (error) goto done; - } g_io_channel_write_chars (channel, "\n###### Security Configuration ######\n", - -1, &bytes_written, error); + -1, &bytes_written, &error); + if (error) + goto done; g_hash_table_iter_init (&iter, wsec_table); /* Writing security */ @@ -415,35 +417,34 @@ wpa_flush_to_file (const char *config_file) g_hash_table_iter_init (&iter_security, (GHashTable *) security); g_io_channel_write_chars (channel, "network={\n", -1, - &bytes_written, error); + &bytes_written, &error); + if (error) + goto done; while (g_hash_table_iter_next (&iter_security, &key, &value)) { out_line = g_strdup_printf (need_quote ((gchar *) key) ? "\t%s=\"%s\"\n" : "\t%s=%s\n", (gchar *) key, (gchar *) value); g_io_channel_write_chars (channel, out_line, -1, - &bytes_written, error); - if (bytes_written == 0 || (error && *error)) - break; + &bytes_written, &error); + if (bytes_written == 0 || error) + goto done; g_free (out_line); } - g_io_channel_write_chars (channel, - "}\n\n", -1, &bytes_written, error); + g_io_channel_write_chars (channel, "}\n\n", -1, &bytes_written, &error); } - if (error && *error) { - nm_log_warn (LOGD_SETTINGS, "Found error: %s", (*error)->message); + g_io_channel_flush (channel, &error); + if (error) goto done; - } - g_io_channel_flush (channel, error); - if (error && *error) { - nm_log_warn (LOGD_SETTINGS, "Found error: %s", (*error)->message); - goto done; - } wpa_parser_data_changed = FALSE; result = TRUE; done: + if (error) { + nm_log_warn (LOGD_SETTINGS, "Error writing WPA configuration: %s", error->message); + g_error_free (error); + } g_io_channel_shutdown (channel, FALSE, NULL); g_io_channel_unref (channel); return result; diff --git a/src/settings/plugins/ifupdown/interface_parser.c b/src/settings/plugins/ifupdown/interface_parser.c index be7d387d..d342501b 100644 --- a/src/settings/plugins/ifupdown/interface_parser.c +++ b/src/settings/plugins/ifupdown/interface_parser.c @@ -1,4 +1,4 @@ -/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ /* NetworkManager -- Network link manager * * Tom Parker <palfrey@tevp.net> @@ -50,7 +50,6 @@ void add_block(const char *type, const char* name) last = ret; } last_data = NULL; - //printf("added block '%s' with type '%s'\n",name,type); } void add_data(const char *key,const char *data) @@ -58,14 +57,15 @@ void add_data(const char *key,const char *data) if_data *ret; char *idx; - // Check if there is a block where we can attach our data + /* Check if there is a block where we can attach our data */ if (first == NULL) return; ret = (if_data*) calloc(1,sizeof(struct _if_data)); ret->key = g_strdup(key); - // Normalize keys. Convert '_' to '-', as ifupdown accepts both variants. - // When querying keys via ifparser_getkey(), use '-'. + + /* Normalize keys. Convert '_' to '-', as ifupdown accepts both variants. + * When querying keys via ifparser_getkey(), use '-'. */ while ((idx = strrchr(ret->key, '_'))) { *idx = '-'; } @@ -81,10 +81,9 @@ void add_data(const char *key,const char *data) last_data->next = ret; last_data = last_data->next; } - //printf("added data '%s' with key '%s'\n",data,key); } -// join values in src with spaces into dst; dst needs to be large enough +/* join values in src with spaces into dst; dst needs to be large enough */ static char *join_values_with_spaces(char *dst, char **src) { if (dst != NULL) { @@ -112,7 +111,7 @@ _recursive_ifparser (const char *eni_file, int quiet) int skip_long_line = 0; int offs = 0; - // Check if interfaces file exists and open it + /* Check if interfaces file exists and open it */ if (!g_file_test (eni_file, G_FILE_TEST_EXISTS)) { if (!quiet) nm_log_warn (LOGD_SETTINGS, "interfaces file %s doesn't exist\n", eni_file); @@ -130,8 +129,8 @@ _recursive_ifparser (const char *eni_file, int quiet) while (!feof(inp)) { - char *token[128]; // 255 chars can only be split into 127 tokens - char value[255]; // large enough to join previously split tokens + char *token[128]; /* 255 chars can only be split into 127 tokens */ + char value[255]; /* large enough to join previously split tokens */ char *safeptr; int toknum; int len = 0; @@ -141,7 +140,7 @@ _recursive_ifparser (const char *eni_file, int quiet) break; len = strlen(line); - // skip over-long lines + /* skip over-long lines */ if (!feof(inp) && len > 0 && line[len-1] != '\n') { if (!skip_long_line) { if (!quiet) @@ -151,35 +150,33 @@ _recursive_ifparser (const char *eni_file, int quiet) continue; } - // trailing '\n' found: remove it & reset offset to 0 + /* trailing '\n' found: remove it & reset offset to 0 */ if (len > 0 && line[len-1] == '\n') { line[--len] = '\0'; offs = 0; } - // if we're in long_line_skip mode, terminate it for real next line + /* if we're in long_line_skip mode, terminate it for real next line */ if (skip_long_line) { if (len == 0 || line[len-1] != '\\') skip_long_line = 0; continue; } - // unwrap wrapped lines + /* unwrap wrapped lines */ if (len > 0 && line[len-1] == '\\') { offs = len - 1; continue; } - //printf(">>%s<<\n", line); - #define SPACES " \t" - // tokenize input; + /* tokenize input; */ for (toknum = 0, token[toknum] = strtok_r(line, SPACES, &safeptr); token[toknum] != NULL; toknum++, token[toknum] = strtok_r(NULL, SPACES, &safeptr)) ; - // ignore comments and empty lines + /* ignore comments and empty lines */ if (toknum == 0 || *token[0]=='#') continue; @@ -192,11 +189,11 @@ _recursive_ifparser (const char *eni_file, int quiet) continue; } - // There are five different stanzas: - // iface, mapping, auto, allow-* and source. - // Create a block for each of them except source. + /* There are five different stanzas: + * iface, mapping, auto, allow-* and source. + * Create a block for each of them except source. */ - // iface stanza takes at least 3 parameters + /* iface stanza takes at least 3 parameters */ if (strcmp(token[0], "iface") == 0) { if (toknum < 4) { if (!quiet) { @@ -209,8 +206,8 @@ _recursive_ifparser (const char *eni_file, int quiet) skip_to_block = 0; add_data(token[2], join_values_with_spaces(value, token + 3)); } - // auto and allow-auto stanzas are equivalent, - // both can take multiple interfaces as parameters: add one block for each + /* auto and allow-auto stanzas are equivalent, + * both can take multiple interfaces as parameters: add one block for each */ else if (strcmp(token[0], "auto") == 0 || strcmp(token[0], "allow-auto") == 0) { int i; @@ -222,14 +219,14 @@ _recursive_ifparser (const char *eni_file, int quiet) add_block(token[0], join_values_with_spaces(value, token + 1)); skip_to_block = 0; } - // allow-* can take multiple interfaces as parameters: add one block for each + /* allow-* can take multiple interfaces as parameters: add one block for each */ else if (strncmp(token[0],"allow-",6) == 0) { int i; for (i = 1; i < toknum; i++) add_block(token[0], token[i]); skip_to_block = 0; } - // source stanza takes one or more filepaths as parameters + /* source stanza takes one or more filepaths as parameters */ else if (strcmp(token[0], "source") == 0) { int i; char *en_dir; diff --git a/src/settings/plugins/ifupdown/interface_parser.h b/src/settings/plugins/ifupdown/interface_parser.h index 4034d44c..d4bb8515 100644 --- a/src/settings/plugins/ifupdown/interface_parser.h +++ b/src/settings/plugins/ifupdown/interface_parser.h @@ -1,4 +1,4 @@ -/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ /* NetworkManager -- Network link manager * * Tom Parker <palfrey@tevp.net> diff --git a/src/settings/plugins/ifupdown/nm-ifupdown-connection.c b/src/settings/plugins/ifupdown/nm-ifupdown-connection.c index 19de1db6..34ecf8b9 100644 --- a/src/settings/plugins/ifupdown/nm-ifupdown-connection.c +++ b/src/settings/plugins/ifupdown/nm-ifupdown-connection.c @@ -1,5 +1,4 @@ -/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ - +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ /* NetworkManager system settings service (ifupdown) * * Alexander Sack <asac@ubuntu.com> @@ -36,134 +35,46 @@ G_DEFINE_TYPE (NMIfupdownConnection, nm_ifupdown_connection, NM_TYPE_SETTINGS_CONNECTION) -#define NM_IFUPDOWN_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_IFUPDOWN_CONNECTION, NMIfupdownConnectionPrivate)) - -typedef struct { - if_block *ifblock; -} NMIfupdownConnectionPrivate; - -enum { - PROP_ZERO, - PROP_IFBLOCK, - _PROP_END, -}; - - NMIfupdownConnection* nm_ifupdown_connection_new (if_block *block) { - g_return_val_if_fail (block != NULL, NULL); - - return (NMIfupdownConnection *) g_object_new (NM_TYPE_IFUPDOWN_CONNECTION, - NM_IFUPDOWN_CONNECTION_IFBLOCK, block, - NULL); -} - -static gboolean -supports_secrets (NMSettingsConnection *connection, const char *setting_name) -{ - nm_log_info (LOGD_SETTINGS, "supports_secrets() for setting_name: '%s'", setting_name); - - return (strcmp (setting_name, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME) == 0); -} - -static void -nm_ifupdown_connection_init (NMIfupdownConnection *connection) -{ -} - -static GObject * -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) -{ GObject *object; - NMIfupdownConnectionPrivate *priv; GError *error = NULL; - object = G_OBJECT_CLASS (nm_ifupdown_connection_parent_class)->constructor (type, n_construct_params, construct_params); - g_return_val_if_fail (object, NULL); + g_return_val_if_fail (block != NULL, NULL); - priv = NM_IFUPDOWN_CONNECTION_GET_PRIVATE (object); - if (!priv) { - nm_log_warn (LOGD_SETTINGS, "%s.%d - no private instance.", __FILE__, __LINE__); - goto err; - } - if (!priv->ifblock) { - nm_log_warn (LOGD_SETTINGS, "(ifupdown) ifblock not provided to constructor."); - goto err; - } + object = g_object_new (NM_TYPE_IFUPDOWN_CONNECTION, NULL); - if (!ifupdown_update_connection_from_if_block (NM_CONNECTION (object), priv->ifblock, &error)) { - nm_log_warn (LOGD_SETTINGS, "%s.%d - invalid connection read from /etc/network/interfaces: (%d) %s", + if (!ifupdown_update_connection_from_if_block (NM_CONNECTION (object), block, &error)) { + nm_log_warn (LOGD_SETTINGS, "%s.%d - invalid connection read from /etc/network/interfaces: %s", __FILE__, __LINE__, - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); - goto err; + error->message); + g_object_unref (object); + return NULL; } - return object; - - err: - g_object_unref (object); - return NULL; + return (NMIfupdownConnection *) object; } -static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) +static gboolean +supports_secrets (NMSettingsConnection *connection, const char *setting_name) { - NMIfupdownConnectionPrivate *priv = NM_IFUPDOWN_CONNECTION_GET_PRIVATE (object); - g_return_if_fail (priv); + nm_log_info (LOGD_SETTINGS, "supports_secrets() for setting_name: '%s'", setting_name); - switch (prop_id) { - case PROP_IFBLOCK: - priv->ifblock = g_value_get_pointer (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } + return (strcmp (setting_name, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME) == 0); } static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) +nm_ifupdown_connection_init (NMIfupdownConnection *connection) { - NMIfupdownConnectionPrivate *priv = NM_IFUPDOWN_CONNECTION_GET_PRIVATE (object); - g_return_if_fail (priv); - - switch (prop_id) { - case PROP_IFBLOCK: - g_value_set_pointer (value, priv->ifblock); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } } static void nm_ifupdown_connection_class_init (NMIfupdownConnectionClass *ifupdown_connection_class) { - GObjectClass *object_class = G_OBJECT_CLASS (ifupdown_connection_class); NMSettingsConnectionClass *connection_class = NM_SETTINGS_CONNECTION_CLASS (ifupdown_connection_class); - g_type_class_add_private (ifupdown_connection_class, sizeof (NMIfupdownConnectionPrivate)); - - /* Virtual methods */ - object_class->constructor = constructor; - object_class->set_property = set_property; - object_class->get_property = get_property; - connection_class->supports_secrets = supports_secrets; - - /* Properties */ - g_object_class_install_property - (object_class, PROP_IFBLOCK, - g_param_spec_pointer (NM_IFUPDOWN_CONNECTION_IFBLOCK, "", "", - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); } diff --git a/src/settings/plugins/ifupdown/nm-ifupdown-connection.h b/src/settings/plugins/ifupdown/nm-ifupdown-connection.h index 54c219f4..8085b831 100644 --- a/src/settings/plugins/ifupdown/nm-ifupdown-connection.h +++ b/src/settings/plugins/ifupdown/nm-ifupdown-connection.h @@ -1,4 +1,4 @@ -/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ /* NetworkManager system settings service (ifupdown) * @@ -37,8 +37,6 @@ G_BEGIN_DECLS #define NM_IS_IFUPDOWN_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_IFUPDOWN_CONNECTION)) #define NM_IFUPDOWN_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_IFUPDOWN_CONNECTION, NMIfupdownConnectionClass)) -#define NM_IFUPDOWN_CONNECTION_IFBLOCK "ifblock" - typedef struct { NMSettingsConnection parent; } NMIfupdownConnection; diff --git a/src/settings/plugins/ifupdown/parser.c b/src/settings/plugins/ifupdown/parser.c index bd200cd5..109018dd 100644 --- a/src/settings/plugins/ifupdown/parser.c +++ b/src/settings/plugins/ifupdown/parser.c @@ -1,4 +1,4 @@ -/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ /* NetworkManager system settings service (ifupdown) * @@ -94,6 +94,8 @@ update_wireless_setting_from_if_block(NMConnection *connection, const gchar* value = ifparser_getkey (block, "inet"); struct _Mapping mapping[] = { {"ssid", "ssid"}, + {"essid", "ssid"}, + {"mode", "mode"}, { NULL, NULL} }; @@ -112,14 +114,22 @@ update_wireless_setting_from_if_block(NMConnection *connection, const gchar* newkey = map_by_mapping(mapping, curr->key+wireless_l); nm_log_info (LOGD_SETTINGS, "wireless setting key: %s='%s'", newkey, curr->data); if(newkey && !strcmp("ssid", newkey)) { - GByteArray *ssid; + GBytes *ssid; gint len = strlen(curr->data); - ssid = g_byte_array_sized_new (len); - g_byte_array_append (ssid, (const guint8 *) curr->data, len); + ssid = g_bytes_new (curr->data, len); g_object_set (wireless_setting, NM_SETTING_WIRELESS_SSID, ssid, NULL); - g_byte_array_free (ssid, TRUE); + g_bytes_unref (ssid); nm_log_info (LOGD_SETTINGS, "setting wireless ssid = %d", len); + } else if(newkey && !strcmp("mode", newkey)) { + if (!g_ascii_strcasecmp (curr->data, "Managed") || !g_ascii_strcasecmp (curr->data, "Auto")) + g_object_set (wireless_setting, NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_INFRA, NULL); + else if (!g_ascii_strcasecmp (curr->data, "Ad-Hoc")) + g_object_set (wireless_setting, NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_ADHOC, NULL); + else if (!g_ascii_strcasecmp (curr->data, "Master")) + g_object_set (wireless_setting, NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_AP, NULL); + else + nm_log_warn (LOGD_SETTINGS, "Invalid mode '%s' (not 'Ad-Hoc', 'Ap', 'Managed', or 'Auto')", curr->data); } else { g_object_set(wireless_setting, newkey, curr->data, @@ -130,13 +140,12 @@ update_wireless_setting_from_if_block(NMConnection *connection, const gchar* newkey = map_by_mapping(mapping, curr->key+wpa_l); if(newkey && !strcmp("ssid", newkey)) { - GByteArray *ssid; + GBytes *ssid; gint len = strlen(curr->data); - ssid = g_byte_array_sized_new (len); - g_byte_array_append (ssid, (const guint8 *) curr->data, len); + ssid = g_bytes_new (curr->data, len); g_object_set (wireless_setting, NM_SETTING_WIRELESS_SSID, ssid, NULL); - g_byte_array_free (ssid, TRUE); + g_bytes_unref (ssid); nm_log_info (LOGD_SETTINGS, "setting wpa ssid = %d", len); } else if(newkey) { @@ -318,11 +327,9 @@ update_wireless_security_setting_from_if_block(NMConnection *connection, IfupdownStrDupeFunc dupe_func = map_by_mapping (dupe_mapping, curr->key+wireless_l); IfupdownStrToTypeFunc type_map_func = map_by_mapping (type_mapping, curr->key+wireless_l); GFreeFunc free_func = map_by_mapping (free_type_mapping, curr->key+wireless_l); - if(!newkey || !dupe_func) { - nm_log_warn (LOGD_SETTINGS, "no (wireless) mapping found for key: %s", - curr->key); + if(!newkey || !dupe_func) goto next; - } + property_value = (*dupe_func) (curr->data, connection); nm_log_info (LOGD_SETTINGS, "setting wireless security key: %s=%s", newkey, property_value); @@ -353,15 +360,15 @@ update_wireless_security_setting_from_if_block(NMConnection *connection, IfupdownStrDupeFunc dupe_func = map_by_mapping (dupe_mapping, curr->key+wpa_l); IfupdownStrToTypeFunc type_map_func = map_by_mapping (type_mapping, curr->key+wpa_l); GFreeFunc free_func = map_by_mapping (free_type_mapping, curr->key+wpa_l); - if(!newkey || !dupe_func) { + if(!newkey || !dupe_func) goto next; - } + property_value = (*dupe_func) (curr->data, connection); nm_log_info (LOGD_SETTINGS, "setting wpa security key: %s=%s", newkey, #ifdef DEBUG_SECRETS property_value -#else // DEBUG_SECRETS +#else /* DEBUG_SECRETS */ !strcmp("key", newkey) || !strcmp("leap-password", newkey) || !strcmp("pin", newkey) || @@ -372,7 +379,7 @@ update_wireless_security_setting_from_if_block(NMConnection *connection, !strcmp("wep-key3", newkey) || NULL ? "<omitted>" : property_value -#endif // DEBUG_SECRETS +#endif /* DEBUG_SECRETS */ ); if (type_map_func) { diff --git a/src/settings/plugins/ifupdown/parser.h b/src/settings/plugins/ifupdown/parser.h index 6aebb8c7..ee88c500 100644 --- a/src/settings/plugins/ifupdown/parser.h +++ b/src/settings/plugins/ifupdown/parser.h @@ -1,4 +1,4 @@ -/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ /* NetworkManager system settings service (ifupdown) * diff --git a/src/settings/plugins/ifupdown/plugin.c b/src/settings/plugins/ifupdown/plugin.c index dbc96eac..b506b2d6 100644 --- a/src/settings/plugins/ifupdown/plugin.c +++ b/src/settings/plugins/ifupdown/plugin.c @@ -93,13 +93,13 @@ static void settings_plugin_ifupdown_class_init (SettingsPluginIfupdownClass *req_class); static void -SettingsPluginIfupdown_init (NMSettingsPlugin *config); +init (NMSettingsPlugin *config); /* Returns the plugins currently known list of connections. The returned * list is freed by the system settings service. */ static GSList* -SettingsPluginIfupdown_get_connections (NMSettingsPlugin *config); +get_connections (NMSettingsPlugin *config); /* * Return a list of device specifications which NetworkManager should not @@ -107,27 +107,27 @@ SettingsPluginIfupdown_get_connections (NMSettingsPlugin *config); * each element must be allocated using g_malloc() or its variants. */ static GSList* -SettingsPluginIfupdown_get_unmanaged_specs (NMSettingsPlugin *config); +get_unmanaged_specs (NMSettingsPlugin *config); /* GObject */ static void -GObject__get_property (GObject *object, guint prop_id, +get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); static void -GObject__set_property (GObject *object, guint prop_id, +set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static void -GObject__dispose (GObject *object); +dispose (GObject *object); static void settings_plugin_interface_init (NMSettingsPluginInterface *plugin_iface) { - plugin_iface->init = SettingsPluginIfupdown_init; - plugin_iface->get_connections = SettingsPluginIfupdown_get_connections; - plugin_iface->get_unmanaged_specs = SettingsPluginIfupdown_get_unmanaged_specs; + plugin_iface->init = init; + plugin_iface->get_connections = get_connections; + plugin_iface->get_unmanaged_specs = get_unmanaged_specs; } static void @@ -137,9 +137,9 @@ settings_plugin_ifupdown_class_init (SettingsPluginIfupdownClass *req_class) g_type_class_add_private (req_class, sizeof (SettingsPluginIfupdownPrivate)); - object_class->dispose = GObject__dispose; - object_class->get_property = GObject__get_property; - object_class->set_property = GObject__set_property; + object_class->dispose = dispose; + object_class->get_property = get_property; + object_class->set_property = set_property; g_object_class_override_property (object_class, NM_SETTINGS_PLUGIN_PROP_NAME, @@ -292,7 +292,7 @@ handle_uevent (GUdevClient *client, } static void -SettingsPluginIfupdown_init (NMSettingsPlugin *config) +init (NMSettingsPlugin *config) { SettingsPluginIfupdown *self = SETTINGS_PLUGIN_IFUPDOWN (config); SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (self); @@ -447,7 +447,7 @@ SettingsPluginIfupdown_init (NMSettingsPlugin *config) * list is freed by the system settings service. */ static GSList* -SettingsPluginIfupdown_get_connections (NMSettingsPlugin *config) +get_connections (NMSettingsPlugin *config) { SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (config); GSList *connections; @@ -471,7 +471,7 @@ SettingsPluginIfupdown_get_connections (NMSettingsPlugin *config) * each element must be allocated using g_malloc() or its variants. */ static GSList* -SettingsPluginIfupdown_get_unmanaged_specs (NMSettingsPlugin *config) +get_unmanaged_specs (NMSettingsPlugin *config) { SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (config); GSList *specs = NULL; @@ -504,7 +504,7 @@ settings_plugin_ifupdown_init (SettingsPluginIfupdown *plugin) } static void -GObject__get_property (GObject *object, guint prop_id, +get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { switch (prop_id) { @@ -524,7 +524,7 @@ GObject__get_property (GObject *object, guint prop_id, } static void -GObject__set_property (GObject *object, guint prop_id, +set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { switch (prop_id) { @@ -535,7 +535,7 @@ GObject__set_property (GObject *object, guint prop_id, } static void -GObject__dispose (GObject *object) +dispose (GObject *object) { SettingsPluginIfupdown *plugin = SETTINGS_PLUGIN_IFUPDOWN (object); SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (plugin); diff --git a/src/settings/plugins/ifupdown/plugin.h b/src/settings/plugins/ifupdown/plugin.h index 090178f2..10ba2287 100644 --- a/src/settings/plugins/ifupdown/plugin.h +++ b/src/settings/plugins/ifupdown/plugin.h @@ -1,4 +1,4 @@ -/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ /* NetworkManager system settings service (ifupdown) * diff --git a/src/settings/plugins/keyfile/plugin.c b/src/settings/plugins/keyfile/plugin.c index 29a1141b..6003c745 100644 --- a/src/settings/plugins/keyfile/plugin.c +++ b/src/settings/plugins/keyfile/plugin.c @@ -404,10 +404,9 @@ read_connections (NMSettingsPlugin *config) dir = g_dir_open (nm_keyfile_plugin_get_path (), 0, &error); if (!dir) { - nm_log_warn (LOGD_SETTINGS, "keyfile: cannot read directory '%s': (%d) %s", + nm_log_warn (LOGD_SETTINGS, "keyfile: cannot read directory '%s': %s", nm_keyfile_plugin_get_path (), - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); + error->message); g_clear_error (&error); return; } diff --git a/src/settings/plugins/keyfile/tests/test-keyfile.c b/src/settings/plugins/keyfile/tests/test-keyfile.c index c1b79ef7..7b66e198 100644 --- a/src/settings/plugins/keyfile/tests/test-keyfile.c +++ b/src/settings/plugins/keyfile/tests/test-keyfile.c @@ -88,33 +88,33 @@ test_read_valid_wired_connection (void) char expected_mac_address[ETH_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }; gboolean success; - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*ipv4.addresses:*semicolon at the end*addresses1*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*ipv4.addresses:*semicolon at the end*addresses2*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*missing prefix length*address4*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, - "*missing prefix length*address5*"); g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + "*missing prefix length*address5*"); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*ipv4.routes*semicolon at the end*routes2*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*ipv4.routes*semicolon at the end*routes3*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*ipv4.routes*semicolon at the end*routes5*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*ipv4.routes*semicolon at the end*routes8*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, - "*missing prefix length*address4*"); g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + "*missing prefix length*address4*"); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*ipv6.address*semicolon at the end*address5*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, - "*missing prefix length*address5*"); g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + "*missing prefix length*address5*"); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*ipv6.address*semicolon at the end*address7*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*ipv6.routes*semicolon at the end*routes1*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*ipv6.route*semicolon at the end*route6*"); connection = nm_keyfile_plugin_connection_from_file (TEST_KEYFILES_DIR "/Test_Wired_Connection", NULL); g_test_assert_expected_messages (); @@ -537,11 +537,11 @@ test_read_wired_mac_case (void) char expected_mac_address[ETH_ALEN] = { 0x00, 0x11, 0xaa, 0xbb, 0xcc, 0x55 }; gboolean success; - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*ipv4.addresses*semicolon at the end*addresses1*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*ipv4.addresses*semicolon at the end*addresses2*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*ipv6.routes*semicolon at the end*routes1*"); connection = nm_keyfile_plugin_connection_from_file (TEST_KEYFILES_DIR "/Test_Wired_Connection_MAC_Case", NULL); g_test_assert_expected_messages (); @@ -1513,10 +1513,10 @@ test_read_wired_8021x_tls_blob_connection (void) gboolean success; GBytes *blob; - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, - "*<warn> keyfile: 802-1x.client-cert: certificate or key file '/CASA/dcbw/Desktop/certinfra/client.pem' does not exist*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, - "*<warn> keyfile: 802-1x.private-key: certificate or key file '/CASA/dcbw/Desktop/certinfra/client.pem' does not exist*"); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + "*<warn> * keyfile: 802-1x.client-cert: certificate or key file '/CASA/dcbw/Desktop/certinfra/client.pem' does not exist*"); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + "*<warn> * keyfile: 802-1x.private-key: certificate or key file '/CASA/dcbw/Desktop/certinfra/client.pem' does not exist*"); connection = nm_keyfile_plugin_connection_from_file (TEST_KEYFILES_DIR "/Test_Wired_TLS_Blob", &error); g_assert_no_error (error); g_assert (connection); @@ -1576,7 +1576,7 @@ test_read_wired_8021x_tls_bad_path_connection (void) char *tmp2; gboolean success; - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*does not exist*"); connection = nm_keyfile_plugin_connection_from_file (TEST_KEYFILES_DIR "/Test_Wired_TLS_Path_Missing", &error); g_test_assert_expected_messages (); @@ -1631,12 +1631,12 @@ test_read_wired_8021x_tls_old_connection (void) const char *tmp; gboolean success; - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, - "*<warn> keyfile: 802-1x.ca-cert: certificate or key file '/CASA/dcbw/Desktop/certinfra/CA/eaptest_ca_cert.pem' does not exist*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, - "*<warn> keyfile: 802-1x.client-cert: certificate or key file '/CASA/dcbw/Desktop/certinfra/client.pem' does not exist*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, - "*<warn> keyfile: 802-1x.private-key: certificate or key file '/CASA/dcbw/Desktop/certinfra/client.pem' does not exist*"); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + "*<warn> * keyfile: 802-1x.ca-cert: certificate or key file '/CASA/dcbw/Desktop/certinfra/CA/eaptest_ca_cert.pem' does not exist*"); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + "*<warn> * keyfile: 802-1x.client-cert: certificate or key file '/CASA/dcbw/Desktop/certinfra/client.pem' does not exist*"); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + "*<warn> * keyfile: 802-1x.private-key: certificate or key file '/CASA/dcbw/Desktop/certinfra/client.pem' does not exist*"); connection = nm_keyfile_plugin_connection_from_file (TEST_KEYFILES_DIR "/Test_Wired_TLS_Old", &error); g_assert_no_error (error); g_assert (connection); @@ -3000,71 +3000,71 @@ int main (int argc, char **argv) nmtst_init_assert_logging (&argc, &argv, "INFO", "DEFAULT"); /* The tests */ - g_test_add_func ("/keyfile/test_read_valid_wired_connection ", test_read_valid_wired_connection); - g_test_add_func ("/keyfile/test_write_wired_connection ", test_write_wired_connection); + g_test_add_func ("/keyfile/test_read_valid_wired_connection", test_read_valid_wired_connection); + g_test_add_func ("/keyfile/test_write_wired_connection", test_write_wired_connection); - g_test_add_func ("/keyfile/test_read_ip6_wired_connection ", test_read_ip6_wired_connection); - g_test_add_func ("/keyfile/test_write_ip6_wired_connection ", test_write_ip6_wired_connection); + g_test_add_func ("/keyfile/test_read_ip6_wired_connection", test_read_ip6_wired_connection); + g_test_add_func ("/keyfile/test_write_ip6_wired_connection", test_write_ip6_wired_connection); - g_test_add_func ("/keyfile/test_read_wired_mac_case ", test_read_wired_mac_case); - g_test_add_func ("/keyfile/test_read_mac_old_format ", test_read_mac_old_format); - g_test_add_func ("/keyfile/test_read_mac_ib_old_format ", test_read_mac_ib_old_format); + g_test_add_func ("/keyfile/test_read_wired_mac_case", test_read_wired_mac_case); + g_test_add_func ("/keyfile/test_read_mac_old_format", test_read_mac_old_format); + g_test_add_func ("/keyfile/test_read_mac_ib_old_format", test_read_mac_ib_old_format); - g_test_add_func ("/keyfile/test_read_valid_wireless_connection ", test_read_valid_wireless_connection); - g_test_add_func ("/keyfile/test_write_wireless_connection ", test_write_wireless_connection); + g_test_add_func ("/keyfile/test_read_valid_wireless_connection", test_read_valid_wireless_connection); + g_test_add_func ("/keyfile/test_write_wireless_connection", test_write_wireless_connection); - g_test_add_func ("/keyfile/test_read_string_ssid ", test_read_string_ssid); - g_test_add_func ("/keyfile/test_write_string_ssid ", test_write_string_ssid); + g_test_add_func ("/keyfile/test_read_string_ssid", test_read_string_ssid); + g_test_add_func ("/keyfile/test_write_string_ssid", test_write_string_ssid); - g_test_add_func ("/keyfile/test_read_intlist_ssid ", test_read_intlist_ssid); - g_test_add_func ("/keyfile/test_write_intlist_ssid ", test_write_intlist_ssid); + g_test_add_func ("/keyfile/test_read_intlist_ssid", test_read_intlist_ssid); + g_test_add_func ("/keyfile/test_write_intlist_ssid", test_write_intlist_ssid); - g_test_add_func ("/keyfile/test_read_intlike_ssid ", test_read_intlike_ssid); - g_test_add_func ("/keyfile/test_write_intlike_ssid ", test_write_intlike_ssid); + g_test_add_func ("/keyfile/test_read_intlike_ssid", test_read_intlike_ssid); + g_test_add_func ("/keyfile/test_write_intlike_ssid", test_write_intlike_ssid); - g_test_add_func ("/keyfile/test_read_intlike_ssid_2 ", test_read_intlike_ssid_2); - g_test_add_func ("/keyfile/test_write_intlike_ssid_2 ", test_write_intlike_ssid_2); + g_test_add_func ("/keyfile/test_read_intlike_ssid_2", test_read_intlike_ssid_2); + g_test_add_func ("/keyfile/test_write_intlike_ssid_2", test_write_intlike_ssid_2); - g_test_add_func ("/keyfile/test_read_bt_dun_connection ", test_read_bt_dun_connection); - g_test_add_func ("/keyfile/test_write_bt_dun_connection ", test_write_bt_dun_connection); + g_test_add_func ("/keyfile/test_read_bt_dun_connection", test_read_bt_dun_connection); + g_test_add_func ("/keyfile/test_write_bt_dun_connection", test_write_bt_dun_connection); - g_test_add_func ("/keyfile/test_read_gsm_connection ", test_read_gsm_connection); - g_test_add_func ("/keyfile/test_write_gsm_connection ", test_write_gsm_connection); + g_test_add_func ("/keyfile/test_read_gsm_connection", test_read_gsm_connection); + g_test_add_func ("/keyfile/test_write_gsm_connection", test_write_gsm_connection); - g_test_add_func ("/keyfile/test_read_wired_8021x_tls_blob_connection ", test_read_wired_8021x_tls_blob_connection); - g_test_add_func ("/keyfile/test_read_wired_8021x_tls_bad_path_connection ", test_read_wired_8021x_tls_bad_path_connection); + g_test_add_func ("/keyfile/test_read_wired_8021x_tls_blob_connection", test_read_wired_8021x_tls_blob_connection); + g_test_add_func ("/keyfile/test_read_wired_8021x_tls_bad_path_connection", test_read_wired_8021x_tls_bad_path_connection); - g_test_add_func ("/keyfile/test_read_wired_8021x_tls_old_connection ", test_read_wired_8021x_tls_old_connection); - g_test_add_func ("/keyfile/test_read_wired_8021x_tls_new_connection ", test_read_wired_8021x_tls_new_connection); - g_test_add_func ("/keyfile/test_write_wired_8021x_tls_connection_path ", test_write_wired_8021x_tls_connection_path); - g_test_add_func ("/keyfile/test_write_wired_8021x_tls_connection_blob ", test_write_wired_8021x_tls_connection_blob); + g_test_add_func ("/keyfile/test_read_wired_8021x_tls_old_connection", test_read_wired_8021x_tls_old_connection); + g_test_add_func ("/keyfile/test_read_wired_8021x_tls_new_connection", test_read_wired_8021x_tls_new_connection); + g_test_add_func ("/keyfile/test_write_wired_8021x_tls_connection_path", test_write_wired_8021x_tls_connection_path); + g_test_add_func ("/keyfile/test_write_wired_8021x_tls_connection_blob", test_write_wired_8021x_tls_connection_blob); - g_test_add_func ("/keyfile/test_read_infiniband_connection ", test_read_infiniband_connection); - g_test_add_func ("/keyfile/test_write_infiniband_connection ", test_write_infiniband_connection); + g_test_add_func ("/keyfile/test_read_infiniband_connection", test_read_infiniband_connection); + g_test_add_func ("/keyfile/test_write_infiniband_connection", test_write_infiniband_connection); - g_test_add_func ("/keyfile/test_read_bridge_main ", test_read_bridge_main); - g_test_add_func ("/keyfile/test_write_bridge_main ", test_write_bridge_main); - g_test_add_func ("/keyfile/test_read_bridge_component ", test_read_bridge_component); - g_test_add_func ("/keyfile/test_write_bridge_component ", test_write_bridge_component); + g_test_add_func ("/keyfile/test_read_bridge_main", test_read_bridge_main); + g_test_add_func ("/keyfile/test_write_bridge_main", test_write_bridge_main); + g_test_add_func ("/keyfile/test_read_bridge_component", test_read_bridge_component); + g_test_add_func ("/keyfile/test_write_bridge_component", test_write_bridge_component); - g_test_add_func ("/keyfile/test_read_new_wired_group_name ", test_read_new_wired_group_name); - g_test_add_func ("/keyfile/test_write_new_wired_group_name ", test_write_new_wired_group_name); - g_test_add_func ("/keyfile/test_read_new_wireless_group_names ", test_read_new_wireless_group_names); - g_test_add_func ("/keyfile/test_write_new_wireless_group_names ", test_write_new_wireless_group_names); + g_test_add_func ("/keyfile/test_read_new_wired_group_name", test_read_new_wired_group_name); + g_test_add_func ("/keyfile/test_write_new_wired_group_name", test_write_new_wired_group_name); + g_test_add_func ("/keyfile/test_read_new_wireless_group_names", test_read_new_wireless_group_names); + g_test_add_func ("/keyfile/test_write_new_wireless_group_names", test_write_new_wireless_group_names); - g_test_add_func ("/keyfile/test_read_missing_vlan_setting ", test_read_missing_vlan_setting); - g_test_add_func ("/keyfile/test_read_missing_vlan_flags ", test_read_missing_vlan_flags); - g_test_add_func ("/keyfile/test_read_missing_id_uuid ", test_read_missing_id_uuid); + g_test_add_func ("/keyfile/test_read_missing_vlan_setting", test_read_missing_vlan_setting); + g_test_add_func ("/keyfile/test_read_missing_vlan_flags", test_read_missing_vlan_flags); + g_test_add_func ("/keyfile/test_read_missing_id_uuid", test_read_missing_id_uuid); g_test_add_func ("/keyfile/test_read_minimal", test_read_minimal); g_test_add_func ("/keyfile/test_read_minimal_slave", test_read_minimal_slave); - g_test_add_func ("/keyfile/test_read_enum_property ", test_read_enum_property); - g_test_add_func ("/keyfile/test_write_enum_property ", test_write_enum_property); - g_test_add_func ("/keyfile/test_read_flags_property ", test_read_flags_property); - g_test_add_func ("/keyfile/test_write_flags_property ", test_write_flags_property); + g_test_add_func ("/keyfile/test_read_enum_property", test_read_enum_property); + g_test_add_func ("/keyfile/test_write_enum_property", test_write_enum_property); + g_test_add_func ("/keyfile/test_read_flags_property", test_read_flags_property); + g_test_add_func ("/keyfile/test_write_flags_property", test_write_flags_property); - g_test_add_func ("/keyfile/test_nm_keyfile_plugin_utils_escape_filename ", test_nm_keyfile_plugin_utils_escape_filename); + g_test_add_func ("/keyfile/test_nm_keyfile_plugin_utils_escape_filename", test_nm_keyfile_plugin_utils_escape_filename); return g_test_run (); } diff --git a/src/settings/plugins/keyfile/utils.h b/src/settings/plugins/keyfile/utils.h index 0b2b6f4e..c18fb2bc 100644 --- a/src/settings/plugins/keyfile/utils.h +++ b/src/settings/plugins/keyfile/utils.h @@ -27,7 +27,7 @@ #define KEYFILE_PLUGIN_NAME "keyfile" #define KEYFILE_PLUGIN_INFO "(c) 2007 - 2015 Red Hat, Inc. To report bugs please use the NetworkManager mailing list." -#define NM_KEYFILE_CONNECTION_LOG_PATH(path) str_if_set (path,"in-memory") +#define NM_KEYFILE_CONNECTION_LOG_PATH(path) ((path) ?: "in-memory") #define NM_KEYFILE_CONNECTION_LOG_FMT "%s (%s,\"%s\")" #define NM_KEYFILE_CONNECTION_LOG_ARG(con) NM_KEYFILE_CONNECTION_LOG_PATH (nm_settings_connection_get_filename ((NMSettingsConnection *) (con))), nm_connection_get_uuid ((NMConnection *) (con)), nm_connection_get_id ((NMConnection *) (con)) #define NM_KEYFILE_CONNECTION_LOG_FMTD "%s (%s,\"%s\",%p)" diff --git a/src/supplicant-manager/nm-supplicant-config.c b/src/supplicant-manager/nm-supplicant-config.c index 091742e5..5ce8bb31 100644 --- a/src/supplicant-manager/nm-supplicant-config.c +++ b/src/supplicant-manager/nm-supplicant-config.c @@ -761,7 +761,7 @@ nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig *self, } else { /* 802.1x for Dynamic WEP and WPA-Enterprise */ if (!strcmp (key_mgmt, "ieee8021x") || !strcmp (key_mgmt, "wpa-eap")) { - if (!setting_8021x) { + if (!setting_8021x) { g_set_error (error, NM_SUPPLICANT_ERROR, NM_SUPPLICANT_ERROR_CONFIG, "Cannot set key-mgmt %s with missing 8021x setting", key_mgmt); return FALSE; @@ -1033,6 +1033,14 @@ nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self, if (!ADD_STRING_LIST_VAL (self, setting, 802_1x, phase2_altsubject_match, phase2_altsubject_matches, "altsubject_match2", ';', FALSE, FALSE, error)) return FALSE; + /* Domain suffix match */ + value = nm_setting_802_1x_get_domain_suffix_match (setting); + if (!add_string_val (self, value, "domain_suffix_match", FALSE, FALSE, error)) + return FALSE; + value = nm_setting_802_1x_get_phase2_domain_suffix_match (setting); + if (!add_string_val (self, value, "domain_suffix_match2", FALSE, FALSE, error)) + return FALSE; + /* Private key */ added = FALSE; switch (nm_setting_802_1x_get_private_key_scheme (setting)) { diff --git a/src/supplicant-manager/nm-supplicant-manager.c b/src/supplicant-manager/nm-supplicant-manager.c index 1b352527..f2c63364 100644 --- a/src/supplicant-manager/nm-supplicant-manager.c +++ b/src/supplicant-manager/nm-supplicant-manager.c @@ -34,6 +34,16 @@ G_DEFINE_TYPE (NMSupplicantManager, nm_supplicant_manager, G_TYPE_OBJECT) +#define _NMLOG_DOMAIN LOGD_SUPPLICANT +#define _NMLOG_PREFIX_NAME "supplicant" +#define _NMLOG(level, ...) \ + G_STMT_START { \ + nm_log ((level), _NMLOG_DOMAIN, \ + "%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME": " \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } G_STMT_END + typedef struct { GDBusProxy * proxy; GCancellable * cancellable; @@ -133,7 +143,7 @@ nm_supplicant_manager_create_interface (NMSupplicantManager *self, priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self); - nm_log_dbg (LOGD_SUPPLICANT, "(%s): creating new supplicant interface", ifname); + _LOGD ("(%s): creating new supplicant interface", ifname); /* assert against not requesting duplicate interfaces. */ for (ifaces = priv->ifaces; ifaces; ifaces = ifaces->next) { @@ -195,9 +205,9 @@ update_capabilities (NMSupplicantManager *self) for (ifaces = priv->ifaces; ifaces; ifaces = ifaces->next) nm_supplicant_interface_set_ap_support (ifaces->data, priv->ap_support); - nm_log_dbg (LOGD_SUPPLICANT, "AP mode is %ssupported", - (priv->ap_support == NM_SUPPLICANT_FEATURE_YES) ? "" : - (priv->ap_support == NM_SUPPLICANT_FEATURE_NO) ? "not " : "possibly "); + _LOGD ("AP mode is %ssupported", + (priv->ap_support == NM_SUPPLICANT_FEATURE_YES) ? "" : + (priv->ap_support == NM_SUPPLICANT_FEATURE_NO) ? "not " : "possibly "); /* EAP-FAST */ priv->fast_supported = FALSE; @@ -212,7 +222,7 @@ update_capabilities (NMSupplicantManager *self) g_variant_unref (value); } - nm_log_dbg (LOGD_SUPPLICANT, "EAP-FAST is %ssupported", priv->fast_supported ? "" : "not "); + _LOGD ("EAP-FAST is %ssupported", priv->fast_supported ? "" : "not "); } static void @@ -270,7 +280,7 @@ wpas_die_count_reset_cb (gpointer user_data) /* Reset the die count back to zero, which allows use of the supplicant again */ priv->die_count_reset_id = 0; set_die_count (self, 0); - nm_log_info (LOGD_SUPPLICANT, "wpa_supplicant die count reset"); + _LOGI ("wpa_supplicant die count reset"); return FALSE; } @@ -284,7 +294,7 @@ name_owner_cb (GDBusProxy *proxy, GParamSpec *pspec, gpointer user_data) g_return_if_fail (proxy == priv->proxy); owner = g_dbus_proxy_get_name_owner (proxy); - nm_log_info (LOGD_SUPPLICANT, "wpa_supplicant %s", owner ? "running" : "stopped"); + _LOGI ("wpa_supplicant %s", owner ? "running" : "stopped"); if (owner) { set_running (self, TRUE); @@ -301,9 +311,8 @@ name_owner_cb (GDBusProxy *proxy, GParamSpec *pspec, gpointer user_data) set_die_count (self, priv->die_count + 1); if (die_count_exceeded (priv->die_count)) { - nm_log_info (LOGD_SUPPLICANT, - "wpa_supplicant die count %d; ignoring for 10 seconds", - priv->die_count); + _LOGI ("wpa_supplicant die count %d; ignoring for 10 seconds", + priv->die_count); } set_running (self, FALSE); @@ -324,9 +333,8 @@ on_proxy_acquired (GObject *object, GAsyncResult *result, gpointer user_data) proxy = g_dbus_proxy_new_for_bus_finish (result, &error); if (!proxy) { - nm_log_warn (LOGD_SUPPLICANT, - "Failed to acquire wpa_supplicant proxy: Wi-Fi and 802.1x will not be available (%s)", - error->message); + _LOGW ("failed to acquire wpa_supplicant proxy: Wi-Fi and 802.1x will not be available (%s)", + error->message); g_clear_error (&error); return; } diff --git a/src/supplicant-manager/nm-supplicant-settings-verify.c b/src/supplicant-manager/nm-supplicant-settings-verify.c index ec660d18..bb046f93 100644 --- a/src/supplicant-manager/nm-supplicant-settings-verify.c +++ b/src/supplicant-manager/nm-supplicant-settings-verify.c @@ -112,6 +112,7 @@ static const struct Opt opt_table[] = { { "ca_path", TYPE_BYTES, 0, 0, FALSE, NULL }, { "subject_match", TYPE_BYTES, 0, 0, FALSE, NULL }, { "altsubject_match", TYPE_BYTES, 0, 0, FALSE, NULL }, + { "domain_suffix_match",TYPE_BYTES, 0, 0, FALSE, NULL }, { "ca_cert", TYPE_BYTES, 0, 65536, FALSE, NULL }, { "client_cert", TYPE_BYTES, 0, 65536, FALSE, NULL }, { "private_key", TYPE_BYTES, 0, 65536, FALSE, NULL }, @@ -122,6 +123,7 @@ static const struct Opt opt_table[] = { { "ca_path2", TYPE_BYTES, 0, 0, FALSE, NULL }, { "subject_match2", TYPE_BYTES, 0, 0, FALSE, NULL }, { "altsubject_match2", TYPE_BYTES, 0, 0, FALSE, NULL }, + { "domain_suffix_match2", TYPE_BYTES, 0, 0, FALSE, NULL }, { "ca_cert2", TYPE_BYTES, 0, 65536, FALSE, NULL }, { "client_cert2", TYPE_BYTES, 0, 65536, FALSE, NULL }, { "private_key2", TYPE_BYTES, 0, 65536, FALSE, NULL }, diff --git a/src/supplicant-manager/tests/test-supplicant-config.c b/src/supplicant-manager/tests/test-supplicant-config.c index 0c3e9a47..881f44f6 100644 --- a/src/supplicant-manager/tests/test-supplicant-config.c +++ b/src/supplicant-manager/tests/test-supplicant-config.c @@ -149,13 +149,13 @@ test_wifi_open (void) config = nm_supplicant_config_new (); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*added 'ssid' value 'Test SSID'*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*added 'scan_ssid' value '1'*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*added 'bssid' value '11:22:33:44:55:66'*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*added 'freq_list' value *"); g_assert (nm_supplicant_config_add_setting_wireless (config, s_wifi, @@ -166,7 +166,7 @@ test_wifi_open (void) g_assert_no_error (error); g_test_assert_expected_messages (); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*added 'key_mgmt' value 'NONE'"); g_assert (nm_supplicant_config_add_no_security (config, &error)); g_assert_no_error (error); @@ -254,13 +254,13 @@ test_wifi_wep_key (const char *detail, config = nm_supplicant_config_new (); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*added 'ssid' value 'Test SSID'*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*added 'scan_ssid' value '1'*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*added 'bssid' value '11:22:33:44:55:66'*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*added 'freq_list' value *"); g_assert (nm_supplicant_config_add_setting_wireless (config, s_wifi, @@ -271,11 +271,11 @@ test_wifi_wep_key (const char *detail, g_assert_no_error (error); g_test_assert_expected_messages (); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*added 'key_mgmt' value 'NONE'"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*added 'wep_key0' value *"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*added 'wep_tx_keyidx' value '0'"); g_assert (nm_supplicant_config_add_setting_wireless_security (config, s_wsec, @@ -399,13 +399,13 @@ test_wifi_wpa_psk (const char *detail, config = nm_supplicant_config_new (); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*added 'ssid' value 'Test SSID'*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*added 'scan_ssid' value '1'*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*added 'bssid' value '11:22:33:44:55:66'*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*added 'freq_list' value *"); g_assert (nm_supplicant_config_add_setting_wireless (config, s_wifi, @@ -416,15 +416,15 @@ test_wifi_wpa_psk (const char *detail, g_assert_no_error (error); g_test_assert_expected_messages (); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*added 'key_mgmt' value 'WPA-PSK'"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*added 'psk' value *"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*added 'proto' value 'WPA RSN'"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*added 'pairwise' value 'TKIP CCMP'"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*added 'group' value 'TKIP CCMP'"); g_assert (nm_supplicant_config_add_setting_wireless_security (config, s_wsec, @@ -546,13 +546,13 @@ test_wifi_eap (void) config = nm_supplicant_config_new (); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*added 'ssid' value 'Test SSID'*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*added 'scan_ssid' value '1'*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*added 'bssid' value '11:22:33:44:55:66'*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*added 'freq_list' value *"); g_assert (nm_supplicant_config_add_setting_wireless (config, s_wifi, @@ -563,25 +563,25 @@ test_wifi_eap (void) g_assert_no_error (error); g_test_assert_expected_messages (); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*added 'key_mgmt' value 'WPA-EAP'"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*added 'proto' value 'WPA RSN'"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*added 'pairwise' value 'TKIP CCMP'"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*added 'group' value 'TKIP CCMP'"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*Config: added 'eap' value 'TLS'"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*Config: added 'fragment_size' value '1086'"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "* Config: added 'ca_cert' value '*/test-ca-cert.pem'"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "* Config: added 'private_key' value '*/test-cert.p12'"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*Config: added 'bgscan' value 'simple:30:-65:300'"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*Config: added 'proactive_key_caching' value '1'"); g_assert (nm_supplicant_config_add_setting_wireless_security (config, s_wsec, diff --git a/src/systemd/nm-sd-adapt.c b/src/systemd/nm-sd-adapt.c index fa7cd938..4e308276 100644 --- a/src/systemd/nm-sd-adapt.c +++ b/src/systemd/nm-sd-adapt.c @@ -13,226 +13,22 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2014 Red Hat, Inc. + * Copyright (C) 2014 - 2016 Red Hat, Inc. */ #include "nm-default.h" #include "nm-sd-adapt.h" -#include <unistd.h> -#include <errno.h> - -#include "sd-event.h" #include "fd-util.h" -#include "time-util.h" - -struct sd_event_source { - guint refcount; - guint id; - gpointer user_data; - - GIOChannel *channel; - - union { - struct { - sd_event_io_handler_t cb; - } io; - struct { - sd_event_time_handler_t cb; - uint64_t usec; - } time; - }; -}; - -static struct sd_event_source * -source_new (void) -{ - struct sd_event_source *source; - - source = g_slice_new0 (struct sd_event_source); - source->refcount = 1; - return source; -} - -int -sd_event_source_set_priority (sd_event_source *s, int64_t priority) -{ - return 0; -} - -sd_event_source* -sd_event_source_unref (sd_event_source *s) -{ - - if (!s) - return NULL; - - g_return_val_if_fail (s->refcount, NULL); - - s->refcount--; - if (s->refcount == 0) { - if (s->id) - g_source_remove (s->id); - if (s->channel) { - /* Don't shut down the channel since systemd will soon close - * the file descriptor itself, which would cause -EBADF. - */ - g_io_channel_unref (s->channel); - } - g_slice_free (struct sd_event_source, s); - } - return NULL; -} - -int -sd_event_source_set_description(sd_event_source *s, const char *description) -{ - if (!s) - return -EINVAL; - - g_source_set_name_by_id (s->id, description); - return 0; -} - -static gboolean -io_ready (GIOChannel *channel, GIOCondition condition, struct sd_event_source *source) -{ - int r, revents = 0; - gboolean result; - - if (condition & G_IO_IN) - revents |= EPOLLIN; - if (condition & G_IO_OUT) - revents |= EPOLLOUT; - if (condition & G_IO_PRI) - revents |= EPOLLPRI; - if (condition & G_IO_ERR) - revents |= EPOLLERR; - if (condition & G_IO_HUP) - revents |= EPOLLHUP; - - source->refcount++; - - r = source->io.cb (source, g_io_channel_unix_get_fd (channel), revents, source->user_data); - if (r < 0 || source->refcount <= 1) { - source->id = 0; - result = G_SOURCE_REMOVE; - } else - result = G_SOURCE_CONTINUE; - - sd_event_source_unref (source); - - return result; -} - -int -sd_event_add_io (sd_event *e, sd_event_source **s, int fd, uint32_t events, sd_event_io_handler_t callback, void *userdata) -{ - struct sd_event_source *source; - GIOChannel *channel; - GIOCondition condition = 0; - - /* systemd supports floating sd_event_source by omitting the @s argument. - * We don't have such users and don't implement floating references. */ - g_return_val_if_fail (s, -EINVAL); - channel = g_io_channel_unix_new (fd); - if (!channel) - return -EINVAL; - - source = source_new (); - source->io.cb = callback; - source->user_data = userdata; - source->channel = channel; - - if (events & EPOLLIN) - condition |= G_IO_IN; - if (events & EPOLLOUT) - condition |= G_IO_OUT; - if (events & EPOLLPRI) - condition |= G_IO_PRI; - if (events & EPOLLERR) - condition |= G_IO_ERR; - if (events & EPOLLHUP) - condition |= G_IO_HUP; - - g_io_channel_set_encoding (source->channel, NULL, NULL); - g_io_channel_set_buffered (source->channel, FALSE); - source->id = g_io_add_watch (source->channel, condition, (GIOFunc) io_ready, source); - - *s = source; - return 0; -} - -static gboolean -time_ready (struct sd_event_source *source) -{ - source->refcount++; - - source->time.cb (source, source->time.usec, source->user_data); - source->id = 0; - - sd_event_source_unref (source); - - return G_SOURCE_REMOVE; -} +/*****************************************************************************/ int -sd_event_add_time(sd_event *e, sd_event_source **s, clockid_t clock, uint64_t usec, uint64_t accuracy, sd_event_time_handler_t callback, void *userdata) -{ - struct sd_event_source *source; - uint64_t n = now (clock); - - /* systemd supports floating sd_event_source by omitting the @s argument. - * We don't have such users and don't implement floating references. */ - g_return_val_if_fail (s, -EINVAL); - - source = source_new (); - source->time.cb = callback; - source->user_data = userdata; - source->time.usec = usec; - - if (usec > 1000) - usec = n < usec - 1000 ? usec - n : 1000; - source->id = g_timeout_add (usec / 1000, (GSourceFunc) time_ready, source); - - *s = source; - return 0; -} - -/* sd_event is basically a GMainContext; but since we only - * ever use the default context, nothing to do here. - */ - -int -sd_event_default (sd_event **e) -{ - *e = GUINT_TO_POINTER (1); - return 0; -} - -sd_event* -sd_event_ref (sd_event *e) -{ - return e; -} - -sd_event* -sd_event_unref (sd_event *e) -{ - return NULL; -} - -int -sd_event_now (sd_event *e, clockid_t clock, uint64_t *usec) -{ - *usec = now (clock); - return 0; -} - -int asynchronous_close(int fd) { - safe_close(fd); +asynchronous_close (int fd) { + safe_close (fd); return -1; } +/*****************************************************************************/ + diff --git a/src/systemd/nm-sd-adapt.h b/src/systemd/nm-sd-adapt.h index f48c86f1..010c8a80 100644 --- a/src/systemd/nm-sd-adapt.h +++ b/src/systemd/nm-sd-adapt.h @@ -53,7 +53,7 @@ _slog_level_to_nm (int slevel) const int _nm_e = (error); \ const NMLogLevel _nm_l = _slog_level_to_nm ((level)); \ \ - if (nm_logging_enabled (_nm_l, LOGD_DHCP)) { \ + if (nm_logging_enabled (_nm_l, LOGD_SYSTEMD)) { \ const char *_nm_location = strrchr ((""file), '/'); \ \ _nm_log_impl (_nm_location ? _nm_location + 1 : (""file), (line), (func), _nm_l, LOGD_DHCP, _nm_e, ("%s"format), "libsystemd: ", ## __VA_ARGS__); \ @@ -102,6 +102,7 @@ G_STMT_START { \ #endif #include <unistd.h> #include <sys/syscall.h> +#include <sys/ioctl.h> #include <net/if_arp.h> @@ -110,6 +111,18 @@ G_STMT_START { \ #define BPF_XOR 0xa0 #endif +#ifndef ETHERTYPE_LLDP +#define ETHERTYPE_LLDP 0x88cc +#endif + +#ifndef HAVE_SECURE_GETENV +# ifdef HAVE___SECURE_GETENV +# define secure_getenv __secure_getenv +# else +# error neither secure_getenv nor __secure_getenv is available +# endif +#endif + /*****************************************************************************/ /* work around missing uchar.h */ @@ -118,6 +131,14 @@ typedef guint32 char32_t; /*****************************************************************************/ +#define PID_TO_PTR(p) ((void*) ((uintptr_t) p)) + +static inline int +sd_notify (int unset_environment, const char *state) +{ + return 0; +} + /* Can't include both net/if.h and linux/if.h; so have to define this here */ #ifndef IFNAMSIZ #define IFNAMSIZ 16 diff --git a/src/systemd/nm-sd.c b/src/systemd/nm-sd.c new file mode 100644 index 00000000..4d596020 --- /dev/null +++ b/src/systemd/nm-sd.c @@ -0,0 +1,136 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2014 - 2016 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-sd.h" + +#include "sd-event.h" + +/***************************************************************************** + * Integrating sd_event into glib. Taken and adjusted from + * https://www.freedesktop.org/software/systemd/man/sd_event_get_fd.html + *****************************************************************************/ + +typedef struct SDEventSource { + GSource source; + GPollFD pollfd; + sd_event *event; + guint *default_source_id; +} SDEventSource; + +static gboolean +event_prepare (GSource *source, gint *timeout_) +{ + return sd_event_prepare (((SDEventSource *) source)->event) > 0; +} + +static gboolean +event_check (GSource *source) +{ + return sd_event_wait (((SDEventSource *) source)->event, 0) > 0; +} + +static gboolean +event_dispatch (GSource *source, GSourceFunc callback, gpointer user_data) +{ + return sd_event_dispatch (((SDEventSource *)source)->event) > 0; +} + +static void +event_finalize (GSource *source) +{ + SDEventSource *s; + + s = (SDEventSource *) source; + sd_event_unref (s->event); + if (s->default_source_id) + *s->default_source_id = 0; +} + +static SDEventSource * +event_create_source (sd_event *event, guint *default_source_id) +{ + static GSourceFuncs event_funcs = { + .prepare = event_prepare, + .check = event_check, + .dispatch = event_dispatch, + .finalize = event_finalize, + }; + SDEventSource *source; + + g_return_val_if_fail (event, NULL); + + source = (SDEventSource *) g_source_new (&event_funcs, sizeof (SDEventSource)); + + source->event = sd_event_ref (event); + source->pollfd.fd = sd_event_get_fd (event); + source->pollfd.events = G_IO_IN | G_IO_HUP | G_IO_ERR; + source->default_source_id = default_source_id; + + g_source_add_poll ((GSource *) source, &source->pollfd); + + return source; +} + +static guint +event_attach (sd_event *event, GMainContext *context) +{ + SDEventSource *source; + guint id; + int r; + sd_event *e = event; + guint *p_default_source_id = NULL; + + if (!e) { + static guint default_source_id = 0; + + if (default_source_id) { + /* The default event cannot be registered multiple times. */ + g_return_val_if_reached (0); + } + + r = sd_event_default (&e); + if (r < 0) + g_return_val_if_reached (0); + + p_default_source_id = &default_source_id; + } + + source = event_create_source (e, p_default_source_id); + id = g_source_attach ((GSource *) source, context); + g_source_unref ((GSource *) source); + + + if (!event) { + *p_default_source_id = id; + sd_event_unref (e); + } + + g_return_val_if_fail (id, 0); + return id; +} + +guint +nm_sd_event_attach_default (void) +{ + return event_attach (NULL, NULL); +} + +/*****************************************************************************/ + diff --git a/src/systemd/nm-sd.h b/src/systemd/nm-sd.h new file mode 100644 index 00000000..888d44ab --- /dev/null +++ b/src/systemd/nm-sd.h @@ -0,0 +1,25 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2014 - 2016 Red Hat, Inc. + */ + +#ifndef __NM_SD_H__ +#define __NM_SD_H__ + +guint nm_sd_event_attach_default (void); + +#endif /* __NM_SD_H__ */ + diff --git a/src/systemd/src/basic/alloc-util.h b/src/systemd/src/basic/alloc-util.h index 679ba7f3..ceeee519 100644 --- a/src/systemd/src/basic/alloc-util.h +++ b/src/systemd/src/basic/alloc-util.h @@ -51,25 +51,29 @@ static inline void freep(void *p) { #define _cleanup_free_ _cleanup_(freep) -_malloc_ _alloc_(1, 2) static inline void *malloc_multiply(size_t a, size_t b) { - if (_unlikely_(b != 0 && a > ((size_t) -1) / b)) +static inline bool size_multiply_overflow(size_t size, size_t need) { + return _unlikely_(need != 0 && size > (SIZE_MAX / need)); +} + +_malloc_ _alloc_(1, 2) static inline void *malloc_multiply(size_t size, size_t need) { + if (size_multiply_overflow(size, need)) return NULL; - return malloc(a * b); + return malloc(size * need); } -_alloc_(2, 3) static inline void *realloc_multiply(void *p, size_t a, size_t b) { - if (_unlikely_(b != 0 && a > ((size_t) -1) / b)) +_alloc_(2, 3) static inline void *realloc_multiply(void *p, size_t size, size_t need) { + if (size_multiply_overflow(size, need)) return NULL; - return realloc(p, a * b); + return realloc(p, size * need); } -_alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t a, size_t b) { - if (_unlikely_(b != 0 && a > ((size_t) -1) / b)) +_alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t size, size_t need) { + if (size_multiply_overflow(size, need)) return NULL; - return memdup(p, a * b); + return memdup(p, size * need); } void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size); diff --git a/src/systemd/src/basic/escape.c b/src/systemd/src/basic/escape.c index 34fb0ced..406b791f 100644 --- a/src/systemd/src/basic/escape.c +++ b/src/systemd/src/basic/escape.c @@ -415,6 +415,34 @@ char *xescape(const char *s, const char *bad) { return r; } +char *octescape(const char *s, size_t len) { + char *r, *t; + const char *f; + + /* Escapes all chars in bad, in addition to \ and " chars, + * in \nnn style escaping. */ + + r = new(char, len * 4 + 1); + if (!r) + return NULL; + + for (f = s, t = r; f < s + len; f++) { + + if (*f < ' ' || *f >= 127 || *f == '\\' || *f == '"') { + *(t++) = '\\'; + *(t++) = '0' + (*f >> 6); + *(t++) = '0' + ((*f >> 3) & 8); + *(t++) = '0' + (*f & 8); + } else + *(t++) = *f; + } + + *t = 0; + + return r; + +} + static char *strcpy_backslash_escaped(char *t, const char *s, const char *bad) { assert(bad); diff --git a/src/systemd/src/basic/escape.h b/src/systemd/src/basic/escape.h index ce518111..b8ec96ad 100644 --- a/src/systemd/src/basic/escape.h +++ b/src/systemd/src/basic/escape.h @@ -52,6 +52,7 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit); char *xescape(const char *s, const char *bad); +char *octescape(const char *s, size_t len); char *shell_escape(const char *s, const char *bad); char *shell_maybe_quote(const char *s); diff --git a/src/systemd/src/basic/ether-addr-util.c b/src/systemd/src/basic/ether-addr-util.c new file mode 100644 index 00000000..0219300d --- /dev/null +++ b/src/systemd/src/basic/ether-addr-util.c @@ -0,0 +1,58 @@ +/*** + This file is part of systemd. + + Copyright 2014 Tom Gundersen + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include "nm-sd-adapt.h" + +#include <net/ethernet.h> +#include <stdio.h> +#include <sys/types.h> + +#include "ether-addr-util.h" +#include "macro.h" + +char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]) { + assert(addr); + assert(buffer); + + /* Like ether_ntoa() but uses %02x instead of %x to print + * ethernet addresses, which makes them look less funny. Also, + * doesn't use a static buffer. */ + + sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x", + addr->ether_addr_octet[0], + addr->ether_addr_octet[1], + addr->ether_addr_octet[2], + addr->ether_addr_octet[3], + addr->ether_addr_octet[4], + addr->ether_addr_octet[5]); + + return buffer; +} + +bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b) { + assert(a); + assert(b); + + return a->ether_addr_octet[0] == b->ether_addr_octet[0] && + a->ether_addr_octet[1] == b->ether_addr_octet[1] && + a->ether_addr_octet[2] == b->ether_addr_octet[2] && + a->ether_addr_octet[3] == b->ether_addr_octet[3] && + a->ether_addr_octet[4] == b->ether_addr_octet[4] && + a->ether_addr_octet[5] == b->ether_addr_octet[5]; +} diff --git a/src/systemd/src/basic/ether-addr-util.h b/src/systemd/src/basic/ether-addr-util.h new file mode 100644 index 00000000..07436379 --- /dev/null +++ b/src/systemd/src/basic/ether-addr-util.h @@ -0,0 +1,37 @@ +#pragma once + +/*** + This file is part of systemd. + + Copyright 2014 Tom Gundersen + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <net/ethernet.h> +#include <stdbool.h> + +#define ETHER_ADDR_FORMAT_STR "%02X%02X%02X%02X%02X%02X" +#define ETHER_ADDR_FORMAT_VAL(x) (x).ether_addr_octet[0], (x).ether_addr_octet[1], (x).ether_addr_octet[2], (x).ether_addr_octet[3], (x).ether_addr_octet[4], (x).ether_addr_octet[5] + +#define ETHER_ADDR_TO_STRING_MAX (3*6) +char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]); + +bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b); + +#define ETHER_ADDR_NULL ((const struct ether_addr){}) + +static inline bool ether_addr_is_null(const struct ether_addr *addr) { + return ether_addr_equal(addr, ÐER_ADDR_NULL); +} diff --git a/src/systemd/src/basic/fileio.c b/src/systemd/src/basic/fileio.c index 9b091213..e940e10e 100644 --- a/src/systemd/src/basic/fileio.c +++ b/src/systemd/src/basic/fileio.c @@ -42,9 +42,7 @@ #include "parse-util.h" #include "path-util.h" #include "random-util.h" -#if 0 /* NM_IGNORED */ #include "stdio-util.h" -#endif /* NM_IGNORED */ #include "string-util.h" #include "strv.h" #include "time-util.h" @@ -356,7 +354,7 @@ static int parse_env_file_internal( case KEY: if (strchr(newline, c)) { state = PRE_KEY; - line ++; + line++; n_key = 0; } else if (c == '=') { state = PRE_VALUE; @@ -380,7 +378,7 @@ static int parse_env_file_internal( case PRE_VALUE: if (strchr(newline, c)) { state = PRE_KEY; - line ++; + line++; key[n_key] = 0; if (value) @@ -420,7 +418,7 @@ static int parse_env_file_internal( case VALUE: if (strchr(newline, c)) { state = PRE_KEY; - line ++; + line++; key[n_key] = 0; @@ -539,7 +537,7 @@ static int parse_env_file_internal( state = COMMENT_ESCAPE; else if (strchr(newline, c)) { state = PRE_KEY; - line ++; + line++; } break; @@ -912,7 +910,7 @@ int get_proc_field(const char *filename, const char *pattern, const char *termin /* Back off one char if there's nothing but whitespace and zeros */ if (!*t || isspace(*t)) - t --; + t--; } len = strcspn(t, terminator); diff --git a/src/systemd/src/basic/fs-util.c b/src/systemd/src/basic/fs-util.c index a3306e3d..9a843644 100644 --- a/src/systemd/src/basic/fs-util.c +++ b/src/systemd/src/basic/fs-util.c @@ -291,24 +291,6 @@ int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) { return 0; } - -int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) { - assert(fd >= 0); - - /* Under the assumption that we are running privileged we - * first change the access mode and only then hand out - * ownership to avoid a window where access is too open. */ - - if (mode != MODE_INVALID) - if (fchmod(fd, mode) < 0) - return -errno; - - if (uid != UID_INVALID || gid != GID_INVALID) - if (fchown(fd, uid, gid) < 0) - return -errno; - - return 0; -} #endif /* NM_IGNORED */ int fchmod_umask(int fd, mode_t m) { diff --git a/src/systemd/src/basic/fs-util.h b/src/systemd/src/basic/fs-util.h index 0e2fcb21..0d23f863 100644 --- a/src/systemd/src/basic/fs-util.h +++ b/src/systemd/src/basic/fs-util.h @@ -43,7 +43,6 @@ int readlink_and_canonicalize(const char *p, char **r); int readlink_and_make_absolute_root(const char *root, const char *path, char **ret); int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid); -int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid); int fchmod_umask(int fd, mode_t mode); diff --git a/src/systemd/src/basic/hashmap.c b/src/systemd/src/basic/hashmap.c index 85071d3e..4df3ae73 100644 --- a/src/systemd/src/basic/hashmap.c +++ b/src/systemd/src/basic/hashmap.c @@ -180,7 +180,7 @@ enum HashmapType { }; struct _packed_ indirect_storage { - char *storage; /* where buckets and DIBs are stored */ + void *storage; /* where buckets and DIBs are stored */ uint8_t hash_key[HASH_KEY_SIZE]; /* hash key; changes during resize */ unsigned n_entries; /* number of stored entries */ @@ -197,7 +197,7 @@ struct direct_storage { /* This gives us 39 bytes on 64bit, or 35 bytes on 32bit. * That's room for 4 set_entries + 4 DIB bytes + 3 unused bytes on 64bit, * or 7 set_entries + 7 DIB bytes + 0 unused bytes on 32bit. */ - char storage[sizeof(struct indirect_storage)]; + uint8_t storage[sizeof(struct indirect_storage)]; }; #define DIRECT_BUCKETS(entry_t) \ @@ -306,7 +306,7 @@ static void n_entries_dec(HashmapBase *h) { h->n_direct_entries--; } -static char *storage_ptr(HashmapBase *h) { +static void *storage_ptr(HashmapBase *h) { return h->has_indirect ? h->indirect.storage : h->direct.storage; } @@ -351,7 +351,7 @@ static void get_hash_key(uint8_t hash_key[HASH_KEY_SIZE], bool reuse_is_ok) { static struct hashmap_base_entry *bucket_at(HashmapBase *h, unsigned idx) { return (struct hashmap_base_entry*) - (storage_ptr(h) + idx * hashmap_type_info[h->type].entry_size); + ((uint8_t*) storage_ptr(h) + idx * hashmap_type_info[h->type].entry_size); } static struct plain_hashmap_entry *plain_bucket_at(Hashmap *h, unsigned idx) { @@ -385,7 +385,7 @@ static struct hashmap_base_entry *bucket_at_virtual(HashmapBase *h, struct swap_ static dib_raw_t *dib_raw_ptr(HashmapBase *h) { return (dib_raw_t*) - (storage_ptr(h) + hashmap_type_info[h->type].entry_size * n_buckets(h)); + ((uint8_t*) storage_ptr(h) + hashmap_type_info[h->type].entry_size * n_buckets(h)); } static unsigned bucket_distance(HashmapBase *h, unsigned idx, unsigned from) { @@ -1032,7 +1032,7 @@ static int hashmap_base_put_boldly(HashmapBase *h, unsigned idx, */ static int resize_buckets(HashmapBase *h, unsigned entries_add) { struct swap_entries swap; - char *new_storage; + void *new_storage; dib_raw_t *old_dibs, *new_dibs; const struct hashmap_type_info *hi; unsigned idx, optimal_idx; @@ -1099,7 +1099,7 @@ static int resize_buckets(HashmapBase *h, unsigned entries_add) { h->indirect.n_buckets = (1U << new_shift) / (hi->entry_size + sizeof(dib_raw_t)); - old_dibs = (dib_raw_t*)(new_storage + hi->entry_size * old_n_buckets); + old_dibs = (dib_raw_t*)((uint8_t*) new_storage + hi->entry_size * old_n_buckets); new_dibs = dib_raw_ptr(h); /* diff --git a/src/systemd/src/basic/hexdecoct.c b/src/systemd/src/basic/hexdecoct.c index 99eaa7a2..950e3230 100644 --- a/src/systemd/src/basic/hexdecoct.c +++ b/src/systemd/src/basic/hexdecoct.c @@ -27,6 +27,7 @@ #include "alloc-util.h" #include "hexdecoct.h" #include "macro.h" +#include "util.h" char octchar(int x) { return '0' + (x & 7); @@ -277,8 +278,8 @@ int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_l if (padding) { /* strip the padding */ while (l > 0 && p[l - 1] == '=' && pad < 7) { - pad ++; - l --; + pad++; + l--; } } @@ -506,7 +507,7 @@ int unbase64char(char c) { if (c == '+') return offset; - offset ++; + offset++; if (c == '/') return offset; @@ -574,7 +575,7 @@ static int base64_append_width(char **prefix, int plen, if (!t) return -ENOMEM; - memcpy(t + plen, sep, slen); + memcpy_safe(t + plen, sep, slen); for (line = 0, s = t + plen + slen, avail = len; line < lines; line++) { int act = MIN(width, avail); @@ -622,9 +623,9 @@ int unbase64mem(const char *p, size_t l, void **mem, size_t *_len) { /* strip the padding */ if (l > 0 && p[l - 1] == '=') - l --; + l--; if (l > 0 && p[l - 1] == '=') - l --; + l--; /* a group of four input bytes needs three output bytes, in case of padding we need to add two or three extra bytes */ diff --git a/src/systemd/src/basic/hostname-util.c b/src/systemd/src/basic/hostname-util.c index 5875f4b4..ee48b86d 100644 --- a/src/systemd/src/basic/hostname-util.c +++ b/src/systemd/src/basic/hostname-util.c @@ -19,7 +19,6 @@ #include "nm-sd-adapt.h" -#include <bits/local_lim.h> #include <errno.h> #include <limits.h> #include <stdio.h> @@ -51,6 +50,10 @@ bool hostname_is_set(void) { char* gethostname_malloc(void) { struct utsname u; + /* This call tries to return something useful, either the actual hostname + * or it makes something up. The only reason it might fail is OOM. + * It might even return "localhost" if that's set. */ + assert_se(uname(&u) >= 0); if (isempty(u.nodename) || streq(u.nodename, "(none)")) @@ -59,6 +62,31 @@ char* gethostname_malloc(void) { return strdup(u.nodename); } +int gethostname_strict(char **ret) { + struct utsname u; + char *k; + + /* This call will rather fail than make up a name. It will not return "localhost" either. */ + + assert_se(uname(&u) >= 0); + + if (isempty(u.nodename)) + return -ENXIO; + + if (streq(u.nodename, "(none)")) + return -ENXIO; + + if (is_localhost(u.nodename)) + return -ENXIO; + + k = strdup(u.nodename); + if (!k) + return -ENOMEM; + + *ret = k; + return 0; +} + static bool hostname_valid_char(char c) { return (c >= 'a' && c <= 'z') || @@ -98,7 +126,7 @@ bool hostname_is_valid(const char *s, bool allow_trailing_dot) { return false; dot = true; - n_dots ++; + n_dots++; } else { if (!hostname_valid_char(*p)) return false; @@ -124,6 +152,8 @@ char* hostname_cleanup(char *s) { assert(s); + strshorten(s, HOST_NAME_MAX); + for (p = s, d = s, dot = true; *p; p++) { if (*p == '.') { if (dot) @@ -143,8 +173,6 @@ char* hostname_cleanup(char *s) { else *d = 0; - strshorten(s, HOST_NAME_MAX); - return s; } diff --git a/src/systemd/src/basic/hostname-util.h b/src/systemd/src/basic/hostname-util.h index d062edde..7af4e6c7 100644 --- a/src/systemd/src/basic/hostname-util.h +++ b/src/systemd/src/basic/hostname-util.h @@ -26,6 +26,7 @@ bool hostname_is_set(void); char* gethostname_malloc(void); +int gethostname_strict(char **ret); bool hostname_is_valid(const char *s, bool allow_trailing_dot) _pure_; char* hostname_cleanup(char *s); diff --git a/src/systemd/src/basic/io-util.c b/src/systemd/src/basic/io-util.c index 1b2fc99f..aaf414f4 100644 --- a/src/systemd/src/basic/io-util.c +++ b/src/systemd/src/basic/io-util.c @@ -251,7 +251,7 @@ ssize_t sparse_write(int fd, const void *p, size_t sz, size_t run_length) { } else if (n > 0) q += n; else - q ++; + q++; } if (q > w) { diff --git a/src/systemd/src/basic/io-util.h b/src/systemd/src/basic/io-util.h index 142c940d..4684ed3b 100644 --- a/src/systemd/src/basic/io-util.h +++ b/src/systemd/src/basic/io-util.h @@ -46,7 +46,7 @@ ssize_t sparse_write(int fd, const void *p, size_t sz, size_t run_length); char *_s = (char *)(s); \ _i->iov_base = _s; \ _i->iov_len = strlen(_s); \ - } while(false) + } while (false) static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, unsigned n) { unsigned j; diff --git a/src/systemd/src/basic/list.h b/src/systemd/src/basic/list.h index c68185f5..5962aa42 100644 --- a/src/systemd/src/basic/list.h +++ b/src/systemd/src/basic/list.h @@ -32,7 +32,7 @@ #define LIST_HEAD_INIT(head) \ do { \ (head) = NULL; } \ - while(false) + while (false) /* Initialize a list item */ #define LIST_INIT(name,item) \ @@ -40,7 +40,7 @@ typeof(*(item)) *_item = (item); \ assert(_item); \ _item->name##_prev = _item->name##_next = NULL; \ - } while(false) + } while (false) /* Prepend an item to the list */ #define LIST_PREPEND(name,head,item) \ @@ -51,7 +51,7 @@ _item->name##_next->name##_prev = _item; \ _item->name##_prev = NULL; \ *_head = _item; \ - } while(false) + } while (false) /* Append an item to the list */ #define LIST_APPEND(name,head,item) \ @@ -59,7 +59,7 @@ typeof(*(head)) *_tail; \ LIST_FIND_TAIL(name,head,_tail); \ LIST_INSERT_AFTER(name,head,_tail,item); \ - } while(false) + } while (false) /* Remove an item from the list */ #define LIST_REMOVE(name,head,item) \ @@ -75,7 +75,7 @@ *_head = _item->name##_next; \ } \ _item->name##_next = _item->name##_prev = NULL; \ - } while(false) + } while (false) /* Find the head of the list */ #define LIST_FIND_HEAD(name,item,head) \ @@ -119,7 +119,7 @@ _b->name##_prev = _a; \ _a->name##_next = _b; \ } \ - } while(false) + } while (false) /* Insert an item before another one (a = where, b = what) */ #define LIST_INSERT_BEFORE(name,head,a,b) \ @@ -145,7 +145,7 @@ _b->name##_next = _a; \ _a->name##_prev = _b; \ } \ - } while(false) + } while (false) #define LIST_JUST_US(name,item) \ (!(item)->name##_prev && !(item)->name##_next) \ diff --git a/src/systemd/src/basic/log.h b/src/systemd/src/basic/log.h index d0ec4dfa..322ad6ca 100644 --- a/src/systemd/src/basic/log.h +++ b/src/systemd/src/basic/log.h @@ -195,7 +195,7 @@ void log_assert_failed_return( #ifdef LOG_TRACE # define log_trace(...) log_debug(__VA_ARGS__) #else -# define log_trace(...) do {} while(0) +# define log_trace(...) do {} while (0) #endif /* Structured logging */ @@ -248,5 +248,4 @@ int log_syntax_internal( log_syntax_internal(unit, _level, config_file, config_line, 0, __FILE__, __LINE__, __func__, \ "String is not UTF-8 clean, ignoring assignment: %s", strna(_p)); \ } \ - -EINVAL; \ }) diff --git a/src/systemd/src/basic/macro.h b/src/systemd/src/basic/macro.h index d12e09a7..d6a877ea 100644 --- a/src/systemd/src/basic/macro.h +++ b/src/systemd/src/basic/macro.h @@ -23,10 +23,15 @@ #include <inttypes.h> #include <stdbool.h> #include <sys/param.h> +#include <sys/sysmacros.h> #include <sys/types.h> #define _printf_(a,b) __attribute__ ((format (printf, a, b))) -#define _alloc_(...) __attribute__ ((alloc_size(__VA_ARGS__))) +#ifdef __clang__ +# define _alloc_(...) +#else +# define _alloc_(...) __attribute__ ((alloc_size(__VA_ARGS__))) +#endif #define _sentinel_ __attribute__ ((sentinel)) #define _unused_ __attribute__ ((unused)) #define _destructor_ __attribute__ ((destructor)) @@ -233,7 +238,7 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) { /* We override the glibc assert() here. */ #undef assert #ifdef NDEBUG -#define assert(expr) do {} while(false) +#define assert(expr) do {} while (false) #else #define assert(expr) assert_message_se(expr, #expr) #endif @@ -370,6 +375,12 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) { _found; \ }) +#define SWAP_TWO(x, y) do { \ + typeof(x) _t = (x); \ + (x) = (y); \ + (y) = (_t); \ + } while (false) + /* Define C11 thread_local attribute even on older gcc compiler * version */ #ifndef thread_local diff --git a/src/systemd/src/basic/mempool.h b/src/systemd/src/basic/mempool.h index fea7841b..0618b8dd 100644 --- a/src/systemd/src/basic/mempool.h +++ b/src/systemd/src/basic/mempool.h @@ -36,7 +36,7 @@ void* mempool_alloc0_tile(struct mempool *mp); void mempool_free_tile(struct mempool *mp, void *p); #define DEFINE_MEMPOOL(pool_name, tile_type, alloc_at_least) \ -struct mempool pool_name = { \ +static struct mempool pool_name = { \ .tile_size = sizeof(tile_type), \ .at_least = alloc_at_least, \ } diff --git a/src/systemd/src/basic/parse-util.c b/src/systemd/src/basic/parse-util.c index beb90fa6..eb53c42d 100644 --- a/src/systemd/src/basic/parse-util.c +++ b/src/systemd/src/basic/parse-util.c @@ -511,7 +511,7 @@ int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) { s = *p; /* accept any number of digits, strtoull is limted to 19 */ - for(i=0; i < digits; i++,s++) { + for (i=0; i < digits; i++,s++) { if (*s < '0' || *s > '9') { if (i == 0) return -EINVAL; diff --git a/src/systemd/src/basic/set.h b/src/systemd/src/basic/set.h index 2bff5062..e0d9dd00 100644 --- a/src/systemd/src/basic/set.h +++ b/src/systemd/src/basic/set.h @@ -126,6 +126,9 @@ int set_put_strdupv(Set *s, char **l); #define SET_FOREACH(e, s, i) \ for ((i) = ITERATOR_FIRST; set_iterate((s), &(i), (void**)&(e)); ) +#define SET_FOREACH_MOVE(e, d, s) \ + for (; ({ e = set_first(s); assert_se(!e || set_move_one(d, s, e) >= 0); e; }); ) + DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free); DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free_free); diff --git a/src/systemd/src/basic/socket-util.c b/src/systemd/src/basic/socket-util.c new file mode 100644 index 00000000..c68db7c3 --- /dev/null +++ b/src/systemd/src/basic/socket-util.c @@ -0,0 +1,982 @@ +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include "nm-sd-adapt.h" + +#include <arpa/inet.h> +#include <errno.h> +#include <limits.h> +#include <net/if.h> +#include <netdb.h> +#include <netinet/ip.h> +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "alloc-util.h" +#include "fd-util.h" +#include "fileio.h" +#if 0 /* NM_IGNORED */ +#include "formats-util.h" +#endif /* NM_IGNORED */ +#include "log.h" +#include "macro.h" +#if 0 /* NM_IGNORED */ +#include "missing.h" +#endif /* NM_IGNORED */ +#include "parse-util.h" +#include "path-util.h" +#include "socket-util.h" +#include "string-table.h" +#include "string-util.h" +#if 0 /* NM_IGNORED */ +#include "user-util.h" +#endif /* NM_IGNORED */ +#include "util.h" + +#if 0 /* NM_IGNORED */ +int socket_address_parse(SocketAddress *a, const char *s) { + char *e, *n; + unsigned u; + int r; + + assert(a); + assert(s); + + zero(*a); + a->type = SOCK_STREAM; + + if (*s == '[') { + /* IPv6 in [x:.....:z]:p notation */ + + e = strchr(s+1, ']'); + if (!e) + return -EINVAL; + + n = strndupa(s+1, e-s-1); + + errno = 0; + if (inet_pton(AF_INET6, n, &a->sockaddr.in6.sin6_addr) <= 0) + return errno > 0 ? -errno : -EINVAL; + + e++; + if (*e != ':') + return -EINVAL; + + e++; + r = safe_atou(e, &u); + if (r < 0) + return r; + + if (u <= 0 || u > 0xFFFF) + return -EINVAL; + + a->sockaddr.in6.sin6_family = AF_INET6; + a->sockaddr.in6.sin6_port = htons((uint16_t) u); + a->size = sizeof(struct sockaddr_in6); + + } else if (*s == '/') { + /* AF_UNIX socket */ + + size_t l; + + l = strlen(s); + if (l >= sizeof(a->sockaddr.un.sun_path)) + return -EINVAL; + + a->sockaddr.un.sun_family = AF_UNIX; + memcpy(a->sockaddr.un.sun_path, s, l); + a->size = offsetof(struct sockaddr_un, sun_path) + l + 1; + + } else if (*s == '@') { + /* Abstract AF_UNIX socket */ + size_t l; + + l = strlen(s+1); + if (l >= sizeof(a->sockaddr.un.sun_path) - 1) + return -EINVAL; + + a->sockaddr.un.sun_family = AF_UNIX; + memcpy(a->sockaddr.un.sun_path+1, s+1, l); + a->size = offsetof(struct sockaddr_un, sun_path) + 1 + l; + + } else { + e = strchr(s, ':'); + if (e) { + r = safe_atou(e+1, &u); + if (r < 0) + return r; + + if (u <= 0 || u > 0xFFFF) + return -EINVAL; + + n = strndupa(s, e-s); + + /* IPv4 in w.x.y.z:p notation? */ + r = inet_pton(AF_INET, n, &a->sockaddr.in.sin_addr); + if (r < 0) + return -errno; + + if (r > 0) { + /* Gotcha, it's a traditional IPv4 address */ + a->sockaddr.in.sin_family = AF_INET; + a->sockaddr.in.sin_port = htons((uint16_t) u); + a->size = sizeof(struct sockaddr_in); + } else { + unsigned idx; + + if (strlen(n) > IF_NAMESIZE-1) + return -EINVAL; + + /* Uh, our last resort, an interface name */ + idx = if_nametoindex(n); + if (idx == 0) + return -EINVAL; + + a->sockaddr.in6.sin6_family = AF_INET6; + a->sockaddr.in6.sin6_port = htons((uint16_t) u); + a->sockaddr.in6.sin6_scope_id = idx; + a->sockaddr.in6.sin6_addr = in6addr_any; + a->size = sizeof(struct sockaddr_in6); + } + } else { + + /* Just a port */ + r = safe_atou(s, &u); + if (r < 0) + return r; + + if (u <= 0 || u > 0xFFFF) + return -EINVAL; + + if (socket_ipv6_is_supported()) { + a->sockaddr.in6.sin6_family = AF_INET6; + a->sockaddr.in6.sin6_port = htons((uint16_t) u); + a->sockaddr.in6.sin6_addr = in6addr_any; + a->size = sizeof(struct sockaddr_in6); + } else { + a->sockaddr.in.sin_family = AF_INET; + a->sockaddr.in.sin_port = htons((uint16_t) u); + a->sockaddr.in.sin_addr.s_addr = INADDR_ANY; + a->size = sizeof(struct sockaddr_in); + } + } + } + + return 0; +} + +int socket_address_parse_and_warn(SocketAddress *a, const char *s) { + SocketAddress b; + int r; + + /* Similar to socket_address_parse() but warns for IPv6 sockets when we don't support them. */ + + r = socket_address_parse(&b, s); + if (r < 0) + return r; + + if (!socket_ipv6_is_supported() && b.sockaddr.sa.sa_family == AF_INET6) { + log_warning("Binding to IPv6 address not available since kernel does not support IPv6."); + return -EAFNOSUPPORT; + } + + *a = b; + return 0; +} + +int socket_address_parse_netlink(SocketAddress *a, const char *s) { + int family; + unsigned group = 0; + _cleanup_free_ char *sfamily = NULL; + assert(a); + assert(s); + + zero(*a); + a->type = SOCK_RAW; + + errno = 0; + if (sscanf(s, "%ms %u", &sfamily, &group) < 1) + return errno > 0 ? -errno : -EINVAL; + + family = netlink_family_from_string(sfamily); + if (family < 0) + return -EINVAL; + + a->sockaddr.nl.nl_family = AF_NETLINK; + a->sockaddr.nl.nl_groups = group; + + a->type = SOCK_RAW; + a->size = sizeof(struct sockaddr_nl); + a->protocol = family; + + return 0; +} + +int socket_address_verify(const SocketAddress *a) { + assert(a); + + switch (socket_address_family(a)) { + + case AF_INET: + if (a->size != sizeof(struct sockaddr_in)) + return -EINVAL; + + if (a->sockaddr.in.sin_port == 0) + return -EINVAL; + + if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM) + return -EINVAL; + + return 0; + + case AF_INET6: + if (a->size != sizeof(struct sockaddr_in6)) + return -EINVAL; + + if (a->sockaddr.in6.sin6_port == 0) + return -EINVAL; + + if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM) + return -EINVAL; + + return 0; + + case AF_UNIX: + if (a->size < offsetof(struct sockaddr_un, sun_path)) + return -EINVAL; + + if (a->size > offsetof(struct sockaddr_un, sun_path)) { + + if (a->sockaddr.un.sun_path[0] != 0) { + char *e; + + /* path */ + e = memchr(a->sockaddr.un.sun_path, 0, sizeof(a->sockaddr.un.sun_path)); + if (!e) + return -EINVAL; + + if (a->size != offsetof(struct sockaddr_un, sun_path) + (e - a->sockaddr.un.sun_path) + 1) + return -EINVAL; + } + } + + if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM && a->type != SOCK_SEQPACKET) + return -EINVAL; + + return 0; + + case AF_NETLINK: + + if (a->size != sizeof(struct sockaddr_nl)) + return -EINVAL; + + if (a->type != SOCK_RAW && a->type != SOCK_DGRAM) + return -EINVAL; + + return 0; + + default: + return -EAFNOSUPPORT; + } +} + +int socket_address_print(const SocketAddress *a, char **ret) { + int r; + + assert(a); + assert(ret); + + r = socket_address_verify(a); + if (r < 0) + return r; + + if (socket_address_family(a) == AF_NETLINK) { + _cleanup_free_ char *sfamily = NULL; + + r = netlink_family_to_string_alloc(a->protocol, &sfamily); + if (r < 0) + return r; + + r = asprintf(ret, "%s %u", sfamily, a->sockaddr.nl.nl_groups); + if (r < 0) + return -ENOMEM; + + return 0; + } + + return sockaddr_pretty(&a->sockaddr.sa, a->size, false, true, ret); +} + +bool socket_address_can_accept(const SocketAddress *a) { + assert(a); + + return + a->type == SOCK_STREAM || + a->type == SOCK_SEQPACKET; +} + +bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) { + assert(a); + assert(b); + + /* Invalid addresses are unequal to all */ + if (socket_address_verify(a) < 0 || + socket_address_verify(b) < 0) + return false; + + if (a->type != b->type) + return false; + + if (socket_address_family(a) != socket_address_family(b)) + return false; + + switch (socket_address_family(a)) { + + case AF_INET: + if (a->sockaddr.in.sin_addr.s_addr != b->sockaddr.in.sin_addr.s_addr) + return false; + + if (a->sockaddr.in.sin_port != b->sockaddr.in.sin_port) + return false; + + break; + + case AF_INET6: + if (memcmp(&a->sockaddr.in6.sin6_addr, &b->sockaddr.in6.sin6_addr, sizeof(a->sockaddr.in6.sin6_addr)) != 0) + return false; + + if (a->sockaddr.in6.sin6_port != b->sockaddr.in6.sin6_port) + return false; + + break; + + case AF_UNIX: + if (a->size <= offsetof(struct sockaddr_un, sun_path) || + b->size <= offsetof(struct sockaddr_un, sun_path)) + return false; + + if ((a->sockaddr.un.sun_path[0] == 0) != (b->sockaddr.un.sun_path[0] == 0)) + return false; + + if (a->sockaddr.un.sun_path[0]) { + if (!path_equal_or_files_same(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path)) + return false; + } else { + if (a->size != b->size) + return false; + + if (memcmp(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path, a->size) != 0) + return false; + } + + break; + + case AF_NETLINK: + if (a->protocol != b->protocol) + return false; + + if (a->sockaddr.nl.nl_groups != b->sockaddr.nl.nl_groups) + return false; + + break; + + default: + /* Cannot compare, so we assume the addresses are different */ + return false; + } + + return true; +} + +bool socket_address_is(const SocketAddress *a, const char *s, int type) { + struct SocketAddress b; + + assert(a); + assert(s); + + if (socket_address_parse(&b, s) < 0) + return false; + + b.type = type; + + return socket_address_equal(a, &b); +} + +bool socket_address_is_netlink(const SocketAddress *a, const char *s) { + struct SocketAddress b; + + assert(a); + assert(s); + + if (socket_address_parse_netlink(&b, s) < 0) + return false; + + return socket_address_equal(a, &b); +} + +const char* socket_address_get_path(const SocketAddress *a) { + assert(a); + + if (socket_address_family(a) != AF_UNIX) + return NULL; + + if (a->sockaddr.un.sun_path[0] == 0) + return NULL; + + return a->sockaddr.un.sun_path; +} + +bool socket_ipv6_is_supported(void) { + if (access("/proc/net/sockstat6", F_OK) != 0) + return false; + + return true; +} + +bool socket_address_matches_fd(const SocketAddress *a, int fd) { + SocketAddress b; + socklen_t solen; + + assert(a); + assert(fd >= 0); + + b.size = sizeof(b.sockaddr); + if (getsockname(fd, &b.sockaddr.sa, &b.size) < 0) + return false; + + if (b.sockaddr.sa.sa_family != a->sockaddr.sa.sa_family) + return false; + + solen = sizeof(b.type); + if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &b.type, &solen) < 0) + return false; + + if (b.type != a->type) + return false; + + if (a->protocol != 0) { + solen = sizeof(b.protocol); + if (getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &b.protocol, &solen) < 0) + return false; + + if (b.protocol != a->protocol) + return false; + } + + return socket_address_equal(a, &b); +} + +int sockaddr_port(const struct sockaddr *_sa) { + union sockaddr_union *sa = (union sockaddr_union*) _sa; + + assert(sa); + + if (!IN_SET(sa->sa.sa_family, AF_INET, AF_INET6)) + return -EAFNOSUPPORT; + + return ntohs(sa->sa.sa_family == AF_INET6 ? + sa->in6.sin6_port : + sa->in.sin_port); +} + +int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret) { + union sockaddr_union *sa = (union sockaddr_union*) _sa; + char *p; + int r; + + assert(sa); + assert(salen >= sizeof(sa->sa.sa_family)); + + switch (sa->sa.sa_family) { + + case AF_INET: { + uint32_t a; + + a = ntohl(sa->in.sin_addr.s_addr); + + if (include_port) + r = asprintf(&p, + "%u.%u.%u.%u:%u", + a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF, + ntohs(sa->in.sin_port)); + else + r = asprintf(&p, + "%u.%u.%u.%u", + a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF); + if (r < 0) + return -ENOMEM; + break; + } + + case AF_INET6: { + static const unsigned char ipv4_prefix[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF + }; + + if (translate_ipv6 && + memcmp(&sa->in6.sin6_addr, ipv4_prefix, sizeof(ipv4_prefix)) == 0) { + const uint8_t *a = sa->in6.sin6_addr.s6_addr+12; + if (include_port) + r = asprintf(&p, + "%u.%u.%u.%u:%u", + a[0], a[1], a[2], a[3], + ntohs(sa->in6.sin6_port)); + else + r = asprintf(&p, + "%u.%u.%u.%u", + a[0], a[1], a[2], a[3]); + if (r < 0) + return -ENOMEM; + } else { + char a[INET6_ADDRSTRLEN]; + + inet_ntop(AF_INET6, &sa->in6.sin6_addr, a, sizeof(a)); + + if (include_port) { + r = asprintf(&p, + "[%s]:%u", + a, + ntohs(sa->in6.sin6_port)); + if (r < 0) + return -ENOMEM; + } else { + p = strdup(a); + if (!p) + return -ENOMEM; + } + } + + break; + } + + case AF_UNIX: + if (salen <= offsetof(struct sockaddr_un, sun_path)) { + p = strdup("<unnamed>"); + if (!p) + return -ENOMEM; + + } else if (sa->un.sun_path[0] == 0) { + /* abstract */ + + /* FIXME: We assume we can print the + * socket path here and that it hasn't + * more than one NUL byte. That is + * actually an invalid assumption */ + + p = new(char, sizeof(sa->un.sun_path)+1); + if (!p) + return -ENOMEM; + + p[0] = '@'; + memcpy(p+1, sa->un.sun_path+1, sizeof(sa->un.sun_path)-1); + p[sizeof(sa->un.sun_path)] = 0; + + } else { + p = strndup(sa->un.sun_path, sizeof(sa->un.sun_path)); + if (!p) + return -ENOMEM; + } + + break; + + default: + return -EOPNOTSUPP; + } + + + *ret = p; + return 0; +} + +int getpeername_pretty(int fd, bool include_port, char **ret) { + union sockaddr_union sa; + socklen_t salen = sizeof(sa); + int r; + + assert(fd >= 0); + assert(ret); + + if (getpeername(fd, &sa.sa, &salen) < 0) + return -errno; + + if (sa.sa.sa_family == AF_UNIX) { + struct ucred ucred = {}; + + /* UNIX connection sockets are anonymous, so let's use + * PID/UID as pretty credentials instead */ + + r = getpeercred(fd, &ucred); + if (r < 0) + return r; + + if (asprintf(ret, "PID "PID_FMT"/UID "UID_FMT, ucred.pid, ucred.uid) < 0) + return -ENOMEM; + + return 0; + } + + /* For remote sockets we translate IPv6 addresses back to IPv4 + * if applicable, since that's nicer. */ + + return sockaddr_pretty(&sa.sa, salen, true, include_port, ret); +} + +int getsockname_pretty(int fd, char **ret) { + union sockaddr_union sa; + socklen_t salen = sizeof(sa); + + assert(fd >= 0); + assert(ret); + + if (getsockname(fd, &sa.sa, &salen) < 0) + return -errno; + + /* For local sockets we do not translate IPv6 addresses back + * to IPv6 if applicable, since this is usually used for + * listening sockets where the difference between IPv4 and + * IPv6 matters. */ + + return sockaddr_pretty(&sa.sa, salen, false, true, ret); +} + +int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret) { + int r; + char host[NI_MAXHOST], *ret; + + assert(_ret); + + r = getnameinfo(&sa->sa, salen, host, sizeof(host), NULL, 0, + NI_IDN|NI_IDN_USE_STD3_ASCII_RULES); + if (r != 0) { + int saved_errno = errno; + + r = sockaddr_pretty(&sa->sa, salen, true, true, &ret); + if (r < 0) + return r; + + log_debug_errno(saved_errno, "getnameinfo(%s) failed: %m", ret); + } else { + ret = strdup(host); + if (!ret) + return -ENOMEM; + } + + *_ret = ret; + return 0; +} + +int getnameinfo_pretty(int fd, char **ret) { + union sockaddr_union sa; + socklen_t salen = sizeof(sa); + + assert(fd >= 0); + assert(ret); + + if (getsockname(fd, &sa.sa, &salen) < 0) + return -errno; + + return socknameinfo_pretty(&sa, salen, ret); +} + +int socket_address_unlink(SocketAddress *a) { + assert(a); + + if (socket_address_family(a) != AF_UNIX) + return 0; + + if (a->sockaddr.un.sun_path[0] == 0) + return 0; + + if (unlink(a->sockaddr.un.sun_path) < 0) + return -errno; + + return 1; +} + +static const char* const netlink_family_table[] = { + [NETLINK_ROUTE] = "route", + [NETLINK_FIREWALL] = "firewall", + [NETLINK_INET_DIAG] = "inet-diag", + [NETLINK_NFLOG] = "nflog", + [NETLINK_XFRM] = "xfrm", + [NETLINK_SELINUX] = "selinux", + [NETLINK_ISCSI] = "iscsi", + [NETLINK_AUDIT] = "audit", + [NETLINK_FIB_LOOKUP] = "fib-lookup", + [NETLINK_CONNECTOR] = "connector", + [NETLINK_NETFILTER] = "netfilter", + [NETLINK_IP6_FW] = "ip6-fw", + [NETLINK_DNRTMSG] = "dnrtmsg", + [NETLINK_KOBJECT_UEVENT] = "kobject-uevent", + [NETLINK_GENERIC] = "generic", + [NETLINK_SCSITRANSPORT] = "scsitransport", + [NETLINK_ECRYPTFS] = "ecryptfs" +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(netlink_family, int, INT_MAX); + +static const char* const socket_address_bind_ipv6_only_table[_SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX] = { + [SOCKET_ADDRESS_DEFAULT] = "default", + [SOCKET_ADDRESS_BOTH] = "both", + [SOCKET_ADDRESS_IPV6_ONLY] = "ipv6-only" +}; + +DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only, SocketAddressBindIPv6Only); + +bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b) { + assert(a); + assert(b); + + if (a->sa.sa_family != b->sa.sa_family) + return false; + + if (a->sa.sa_family == AF_INET) + return a->in.sin_addr.s_addr == b->in.sin_addr.s_addr; + + if (a->sa.sa_family == AF_INET6) + return memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr)) == 0; + + return false; +} + +int fd_inc_sndbuf(int fd, size_t n) { + int r, value; + socklen_t l = sizeof(value); + + r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l); + if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2) + return 0; + + /* If we have the privileges we will ignore the kernel limit. */ + + value = (int) n; + if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0) + if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0) + return -errno; + + return 1; +} + +int fd_inc_rcvbuf(int fd, size_t n) { + int r, value; + socklen_t l = sizeof(value); + + r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l); + if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2) + return 0; + + /* If we have the privileges we will ignore the kernel limit. */ + + value = (int) n; + if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0) + if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0) + return -errno; + return 1; +} + +static const char* const ip_tos_table[] = { + [IPTOS_LOWDELAY] = "low-delay", + [IPTOS_THROUGHPUT] = "throughput", + [IPTOS_RELIABILITY] = "reliability", + [IPTOS_LOWCOST] = "low-cost", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff); + +int getpeercred(int fd, struct ucred *ucred) { + socklen_t n = sizeof(struct ucred); + struct ucred u; + int r; + + assert(fd >= 0); + assert(ucred); + + r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &u, &n); + if (r < 0) + return -errno; + + if (n != sizeof(struct ucred)) + return -EIO; + + /* Check if the data is actually useful and not suppressed due + * to namespacing issues */ + if (u.pid <= 0) + return -ENODATA; + if (u.uid == UID_INVALID) + return -ENODATA; + if (u.gid == GID_INVALID) + return -ENODATA; + + *ucred = u; + return 0; +} + +int getpeersec(int fd, char **ret) { + socklen_t n = 64; + char *s; + int r; + + assert(fd >= 0); + assert(ret); + + s = new0(char, n); + if (!s) + return -ENOMEM; + + r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n); + if (r < 0) { + free(s); + + if (errno != ERANGE) + return -errno; + + s = new0(char, n); + if (!s) + return -ENOMEM; + + r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n); + if (r < 0) { + free(s); + return -errno; + } + } + + if (isempty(s)) { + free(s); + return -EOPNOTSUPP; + } + + *ret = s; + return 0; +} + +int send_one_fd_sa( + int transport_fd, + int fd, + const struct sockaddr *sa, socklen_t len, + int flags) { + + union { + struct cmsghdr cmsghdr; + uint8_t buf[CMSG_SPACE(sizeof(int))]; + } control = {}; + struct msghdr mh = { + .msg_name = (struct sockaddr*) sa, + .msg_namelen = len, + .msg_control = &control, + .msg_controllen = sizeof(control), + }; + struct cmsghdr *cmsg; + + assert(transport_fd >= 0); + assert(fd >= 0); + + cmsg = CMSG_FIRSTHDR(&mh); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + memcpy(CMSG_DATA(cmsg), &fd, sizeof(int)); + + mh.msg_controllen = CMSG_SPACE(sizeof(int)); + if (sendmsg(transport_fd, &mh, MSG_NOSIGNAL | flags) < 0) + return -errno; + + return 0; +} + +int receive_one_fd(int transport_fd, int flags) { + union { + struct cmsghdr cmsghdr; + uint8_t buf[CMSG_SPACE(sizeof(int))]; + } control = {}; + struct msghdr mh = { + .msg_control = &control, + .msg_controllen = sizeof(control), + }; + struct cmsghdr *cmsg, *found = NULL; + + assert(transport_fd >= 0); + + /* + * Receive a single FD via @transport_fd. We don't care for + * the transport-type. We retrieve a single FD at most, so for + * packet-based transports, the caller must ensure to send + * only a single FD per packet. This is best used in + * combination with send_one_fd(). + */ + + if (recvmsg(transport_fd, &mh, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC | flags) < 0) + return -errno; + + CMSG_FOREACH(cmsg, &mh) { + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_RIGHTS && + cmsg->cmsg_len == CMSG_LEN(sizeof(int))) { + assert(!found); + found = cmsg; + break; + } + } + + if (!found) { + cmsg_close_all(&mh); + return -EIO; + } + + return *(int*) CMSG_DATA(found); +} +#endif /* NM_IGNORED */ + +ssize_t next_datagram_size_fd(int fd) { + ssize_t l; + int k; + + /* This is a bit like FIONREAD/SIOCINQ, however a bit more powerful. The difference being: recv(MSG_PEEK) will + * actually cause the next datagram in the queue to be validated regarding checksums, which FIONREAD doesn't + * do. This difference is actually of major importance as we need to be sure that the size returned here + * actually matches what we will read with recvmsg() next, as otherwise we might end up allocating a buffer of + * the wrong size. */ + + l = recv(fd, NULL, 0, MSG_PEEK|MSG_TRUNC); + if (l < 0) { + if (errno == EOPNOTSUPP) + goto fallback; + + return -errno; + } + if (l == 0) + goto fallback; + + return l; + +fallback: + k = 0; + + /* Some sockets (AF_PACKET) do not support null-sized recv() with MSG_TRUNC set, let's fall back to FIONREAD + * for them. Checksums don't matter for raw sockets anyway, hence this should be fine. */ + + if (ioctl(fd, FIONREAD, &k) < 0) + return -errno; + + return (ssize_t) k; +} diff --git a/src/systemd/src/basic/socket-util.h b/src/systemd/src/basic/socket-util.h index 92edc1dc..d17a2f35 100644 --- a/src/systemd/src/basic/socket-util.h +++ b/src/systemd/src/basic/socket-util.h @@ -133,5 +133,7 @@ int send_one_fd_sa(int transport_fd, #define send_one_fd(transport_fd, fd, flags) send_one_fd_sa(transport_fd, fd, NULL, 0, flags) int receive_one_fd(int transport_fd, int flags); +ssize_t next_datagram_size_fd(int fd); + #define CMSG_FOREACH(cmsg, mh) \ for ((cmsg) = CMSG_FIRSTHDR(mh); (cmsg); (cmsg) = CMSG_NXTHDR((mh), (cmsg))) diff --git a/src/systemd/src/basic/stdio-util.h b/src/systemd/src/basic/stdio-util.h index 0a675571..bd1144b4 100644 --- a/src/systemd/src/basic/stdio-util.h +++ b/src/systemd/src/basic/stdio-util.h @@ -73,4 +73,4 @@ do { \ assert_not_reached("Unknown format string argument."); \ } \ } \ -} while(false) +} while (false) diff --git a/src/systemd/src/basic/string-util.c b/src/systemd/src/basic/string-util.c index 75df2121..68de772e 100644 --- a/src/systemd/src/basic/string-util.c +++ b/src/systemd/src/basic/string-util.c @@ -482,7 +482,7 @@ char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigne } if (k > x) /* last character was wide and went over quota */ - x ++; + x++; for (j = s + old_length; k < new_length && j > i; ) { char32_t c; diff --git a/src/systemd/src/basic/strv.c b/src/systemd/src/basic/strv.c index c003091b..e885c598 100644 --- a/src/systemd/src/basic/strv.c +++ b/src/systemd/src/basic/strv.c @@ -377,7 +377,7 @@ char *strv_join(char **l, const char *separator) { n = 0; STRV_FOREACH(s, l) { - if (n != 0) + if (s != l) n += k; n += strlen(*s); } @@ -388,7 +388,7 @@ char *strv_join(char **l, const char *separator) { e = r; STRV_FOREACH(s, l) { - if (e != r) + if (s != l) e = stpcpy(e, separator); e = stpcpy(e, *s); diff --git a/src/systemd/src/basic/time-util.c b/src/systemd/src/basic/time-util.c index ed239be1..5b2b2180 100644 --- a/src/systemd/src/basic/time-util.c +++ b/src/systemd/src/basic/time-util.c @@ -44,10 +44,33 @@ static nsec_t timespec_load_nsec(const struct timespec *ts); +static clockid_t map_clock_id(clockid_t c) { + + /* Some more exotic archs (s390, ppc, …) lack the "ALARM" flavour of the clocks. Thus, clock_gettime() will + * fail for them. Since they are essentially the same as their non-ALARM pendants (their only difference is + * when timers are set on them), let's just map them accordingly. This way, we can get the correct time even on + * those archs. + * + * Also, older kernels don't support CLOCK_BOOTTIME: fall back to CLOCK_MONOTONIC. */ + + switch (c) { + + case CLOCK_BOOTTIME: + case CLOCK_BOOTTIME_ALARM: + return clock_boottime_or_monotonic (); + + case CLOCK_REALTIME_ALARM: + return CLOCK_REALTIME; + + default: + return c; + } +} + usec_t now(clockid_t clock_id) { struct timespec ts; - assert_se(clock_gettime(clock_id, &ts) == 0); + assert_se(clock_gettime(map_clock_id(clock_id), &ts) == 0); return timespec_load(&ts); } @@ -55,7 +78,7 @@ usec_t now(clockid_t clock_id) { nsec_t now_nsec(clockid_t clock_id) { struct timespec ts; - assert_se(clock_gettime(clock_id, &ts) == 0); + assert_se(clock_gettime(map_clock_id(clock_id), &ts) == 0); return timespec_load_nsec(&ts); } @@ -121,8 +144,7 @@ dual_timestamp* dual_timestamp_from_boottime_or_monotonic(dual_timestamp *ts, us usec_t timespec_load(const struct timespec *ts) { assert(ts); - if (ts->tv_sec == (time_t) -1 && - ts->tv_nsec == (long) -1) + if (ts->tv_sec == (time_t) -1 && ts->tv_nsec == (long) -1) return USEC_INFINITY; if ((usec_t) ts->tv_sec > (UINT64_MAX - (ts->tv_nsec / NSEC_PER_USEC)) / USEC_PER_SEC) @@ -136,13 +158,13 @@ usec_t timespec_load(const struct timespec *ts) { static nsec_t timespec_load_nsec(const struct timespec *ts) { assert(ts); - if (ts->tv_sec == (time_t) -1 && - ts->tv_nsec == (long) -1) + if (ts->tv_sec == (time_t) -1 && ts->tv_nsec == (long) -1) return NSEC_INFINITY; - return - (nsec_t) ts->tv_sec * NSEC_PER_SEC + - (nsec_t) ts->tv_nsec; + if ((nsec_t) ts->tv_sec >= (UINT64_MAX - ts->tv_nsec) / NSEC_PER_SEC) + return NSEC_INFINITY; + + return (nsec_t) ts->tv_sec * NSEC_PER_SEC + (nsec_t) ts->tv_nsec; } struct timespec *timespec_store(struct timespec *ts, usec_t u) { @@ -434,7 +456,7 @@ int dual_timestamp_deserialize(const char *value, dual_timestamp *t) { assert(t); if (sscanf(value, "%llu %llu", &a, &b) != 2) { - log_debug("Failed to parse finish timestamp value %s.", value); + log_debug("Failed to parse dual timestamp value \"%s\": %m", value); return -EINVAL; } @@ -444,6 +466,18 @@ int dual_timestamp_deserialize(const char *value, dual_timestamp *t) { return 0; } +int timestamp_deserialize(const char *value, usec_t *timestamp) { + int r; + + assert(value); + + r = safe_atou64(value, timestamp); + if (r < 0) + return log_debug_errno(r, "Failed to parse timestamp value \"%s\": %m", value); + + return r; +} + int parse_timestamp(const char *t, usec_t *usec) { static const struct { const char *name; @@ -550,12 +584,12 @@ int parse_timestamp(const char *t, usec_t *usec) { goto from_tm; } else if (streq(t, "yesterday")) { - tm.tm_mday --; + tm.tm_mday--; tm.tm_sec = tm.tm_min = tm.tm_hour = 0; goto from_tm; } else if (streq(t, "tomorrow")) { - tm.tm_mday ++; + tm.tm_mday++; tm.tm_sec = tm.tm_min = tm.tm_hour = 0; goto from_tm; } @@ -678,8 +712,7 @@ finish: return 0; } -int parse_time(const char *t, usec_t *usec, usec_t default_unit) { - +static char* extract_multiplier(char *p, usec_t *multiplier) { static const struct { const char *suffix; usec_t usec; @@ -713,7 +746,22 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) { { "usec", 1ULL }, { "us", 1ULL }, }; + unsigned i; + + for (i = 0; i < ELEMENTSOF(table); i++) { + char *e; + e = startswith(p, table[i].suffix); + if (e) { + *multiplier = table[i].usec; + return e; + } + } + + return p; +} + +int parse_time(const char *t, usec_t *usec, usec_t default_unit) { const char *p, *s; usec_t r = 0; bool something = false; @@ -738,8 +786,8 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) { for (;;) { long long l, z = 0; char *e; - unsigned i, n = 0; - usec_t multiplier, k; + unsigned n = 0; + usec_t multiplier = default_unit, k; p += strspn(p, WHITESPACE); @@ -752,10 +800,8 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) { errno = 0; l = strtoll(p, &e, 10); - if (errno > 0) return -errno; - if (l < 0) return -ERANGE; @@ -779,18 +825,7 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) { return -EINVAL; e += strspn(e, WHITESPACE); - - for (i = 0; i < ELEMENTSOF(table); i++) - if (startswith(e, table[i].suffix)) { - multiplier = table[i].usec; - p = e + strlen(table[i].suffix); - break; - } - - if (i >= ELEMENTSOF(table)) { - multiplier = default_unit; - p = e; - } + p = extract_multiplier(e, &multiplier); something = true; diff --git a/src/systemd/src/basic/time-util.h b/src/systemd/src/basic/time-util.h index 9894e626..77e3cd08 100644 --- a/src/systemd/src/basic/time-util.h +++ b/src/systemd/src/basic/time-util.h @@ -99,6 +99,7 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy); void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t); int dual_timestamp_deserialize(const char *value, dual_timestamp *t); +int timestamp_deserialize(const char *value, usec_t *timestamp); int parse_timestamp(const char *t, usec_t *usec); diff --git a/src/systemd/src/basic/utf8.c b/src/systemd/src/basic/utf8.c index 5a1d3678..a6bdda6e 100644 --- a/src/systemd/src/basic/utf8.c +++ b/src/systemd/src/basic/utf8.c @@ -243,7 +243,7 @@ char *utf8_escape_non_printable(const char *str) { *(s++) = hexchar((int) *str); str += 1; - len --; + len--; } } } else { diff --git a/src/systemd/src/basic/util.h b/src/systemd/src/basic/util.h index 5033b029..3225269a 100644 --- a/src/systemd/src/basic/util.h +++ b/src/systemd/src/basic/util.h @@ -36,6 +36,7 @@ #include <sys/socket.h> #include <sys/stat.h> #include <sys/statfs.h> +#include <sys/sysmacros.h> #include <sys/types.h> #include <time.h> #include <unistd.h> @@ -106,6 +107,16 @@ static inline void qsort_safe(void *base, size_t nmemb, size_t size, comparison_ qsort(base, nmemb, size, compar); } +/** + * Normal memcpy requires src to be nonnull. We do nothing if n is 0. + */ +static inline void memcpy_safe(void *dst, const void *src, size_t n) { + if (n == 0) + return; + assert(src); + memcpy(dst, src, n); +} + int on_ac_power(void); #define memzero(x,l) (memset((x), 0, (l))) diff --git a/src/systemd/src/libsystemd-network/dhcp-internal.h b/src/systemd/src/libsystemd-network/dhcp-internal.h index a3b842cd..4662b0d8 100644 --- a/src/systemd/src/libsystemd-network/dhcp-internal.h +++ b/src/systemd/src/libsystemd-network/dhcp-internal.h @@ -42,10 +42,10 @@ int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port, int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset, uint8_t overload, uint8_t code, size_t optlen, const void *optval); -typedef int (*dhcp_option_cb_t)(uint8_t code, uint8_t len, +typedef int (*dhcp_option_callback_t)(uint8_t code, uint8_t len, const void *option, void *userdata); -int dhcp_option_parse(DHCPMessage *message, size_t len, dhcp_option_cb_t cb, void *userdata, char **error_message); +int dhcp_option_parse(DHCPMessage *message, size_t len, dhcp_option_callback_t cb, void *userdata, char **error_message); int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid, uint8_t type, uint16_t arp_type, size_t optlen, diff --git a/src/systemd/src/libsystemd-network/dhcp-option.c b/src/systemd/src/libsystemd-network/dhcp-option.c index 4f025b68..e003e088 100644 --- a/src/systemd/src/libsystemd-network/dhcp-option.c +++ b/src/systemd/src/libsystemd-network/dhcp-option.c @@ -36,7 +36,7 @@ static int option_append(uint8_t options[], size_t size, size_t *offset, if (code != SD_DHCP_OPTION_END) /* always make sure there is space for an END option */ - size --; + size--; switch (code) { @@ -56,12 +56,7 @@ static int option_append(uint8_t options[], size_t size, size_t *offset, options[*offset] = code; options[*offset + 1] = optlen; - if (optlen) { - assert(optval); - - memcpy(&options[*offset + 2], optval, optlen); - } - + memcpy_safe(&options[*offset + 2], optval, optlen); *offset += optlen + 2; break; @@ -142,7 +137,7 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset, } static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overload, - uint8_t *message_type, char **error_message, dhcp_option_cb_t cb, + uint8_t *message_type, char **error_message, dhcp_option_callback_t cb, void *userdata) { uint8_t code, len; const uint8_t *option; @@ -228,7 +223,7 @@ static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overlo return 0; } -int dhcp_option_parse(DHCPMessage *message, size_t len, dhcp_option_cb_t cb, void *userdata, char **_error_message) { +int dhcp_option_parse(DHCPMessage *message, size_t len, dhcp_option_callback_t cb, void *userdata, char **_error_message) { _cleanup_free_ char *error_message = NULL; uint8_t overload = 0; uint8_t message_type = 0; diff --git a/src/systemd/src/libsystemd-network/dhcp-packet.c b/src/systemd/src/libsystemd-network/dhcp-packet.c index 26dc2fa2..90d09912 100644 --- a/src/systemd/src/libsystemd-network/dhcp-packet.c +++ b/src/systemd/src/libsystemd-network/dhcp-packet.c @@ -68,7 +68,7 @@ uint16_t dhcp_packet_checksum(uint8_t *buf, size_t len) { /* wrap around in one's complement */ sum++; - buf_64 ++; + buf_64++; } if (len % sizeof(uint64_t)) { diff --git a/src/systemd/src/libsystemd-network/dhcp6-option.c b/src/systemd/src/libsystemd-network/dhcp6-option.c index d4f726b5..ee63142c 100644 --- a/src/systemd/src/libsystemd-network/dhcp6-option.c +++ b/src/systemd/src/libsystemd-network/dhcp6-option.c @@ -73,8 +73,7 @@ int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code, if (r < 0) return r; - if (optval) - memcpy(*buf, optval, optlen); + memcpy_safe(*buf, optval, optlen); *buf += optlen; *buflen -= optlen; diff --git a/src/systemd/src/libsystemd-network/lldp-internal.c b/src/systemd/src/libsystemd-network/lldp-internal.c deleted file mode 100644 index 8194a601..00000000 --- a/src/systemd/src/libsystemd-network/lldp-internal.c +++ /dev/null @@ -1,362 +0,0 @@ -/*** - This file is part of systemd. - - Copyright (C) 2014 Tom Gundersen - Copyright (C) 2014 Susant Sahani - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include "nm-sd-adapt.h" - -#include "sd-lldp.h" - -#include "alloc-util.h" -#include "lldp-internal.h" - -/* We store maximum 1K chassis entries */ -#define LLDP_MIB_MAX_CHASSIS 1024 - -/* Maximum Ports can be attached to any chassis */ -#define LLDP_MIB_MAX_PORT_PER_CHASSIS 32 - -/* 10.5.5.2.2 mibUpdateObjects () - * The mibUpdateObjects () procedure updates the MIB objects corresponding to - * the TLVs contained in the received LLDPDU for the LLDP remote system - * indicated by the LLDP remote systems update process defined in 10.3.5 */ - -int lldp_mib_update_objects(lldp_chassis *c, tlv_packet *tlv) { - lldp_neighbour_port *p; - uint16_t length, ttl; - uint8_t *data; - uint8_t type; - int r; - - assert_return(c, -EINVAL); - assert_return(tlv, -EINVAL); - - r = sd_lldp_packet_read_port_id(tlv, &type, &data, &length); - if (r < 0) - return r; - - /* Update the packet if we already have */ - LIST_FOREACH(port, p, c->ports) { - - if ((p->type == type && p->length == length && !memcmp(p->data, data, p->length))) { - - r = sd_lldp_packet_read_ttl(tlv, &ttl); - if (r < 0) - return r; - - p->until = ttl * USEC_PER_SEC + now(clock_boottime_or_monotonic()); - - sd_lldp_packet_unref(p->packet); - p->packet = tlv; - - prioq_reshuffle(p->c->by_expiry, p, &p->prioq_idx); - - return 0; - } - } - - return -1; -} - -int lldp_mib_remove_objects(lldp_chassis *c, tlv_packet *tlv) { - lldp_neighbour_port *p, *q; - uint8_t *data; - uint16_t length; - uint8_t type; - int r; - - assert_return(c, -EINVAL); - assert_return(tlv, -EINVAL); - - r = sd_lldp_packet_read_port_id(tlv, &type, &data, &length); - if (r < 0) - return r; - - LIST_FOREACH_SAFE(port, p, q, c->ports) { - - /* Find the port */ - if (p->type == type && p->length == length && !memcmp(p->data, data, p->length)) { - lldp_neighbour_port_remove_and_free(p); - break; - } - } - - return 0; -} - -int lldp_mib_add_objects(Prioq *by_expiry, - Hashmap *neighbour_mib, - tlv_packet *tlv) { - _cleanup_lldp_neighbour_port_free_ lldp_neighbour_port *p = NULL; - _cleanup_lldp_chassis_free_ lldp_chassis *c = NULL; - lldp_chassis_id chassis_id; - bool new_chassis = false; - uint8_t subtype, *data; - uint16_t ttl, length; - int r; - - assert_return(by_expiry, -EINVAL); - assert_return(neighbour_mib, -EINVAL); - assert_return(tlv, -EINVAL); - - r = sd_lldp_packet_read_chassis_id(tlv, &subtype, &data, &length); - if (r < 0) - goto drop; - - r = sd_lldp_packet_read_ttl(tlv, &ttl); - if (r < 0) - goto drop; - - /* Make hash key */ - chassis_id.type = subtype; - chassis_id.length = length; - chassis_id.data = data; - - /* Try to find the Chassis */ - c = hashmap_get(neighbour_mib, &chassis_id); - if (!c) { - - /* Don't create chassis if ttl 0 is received . Silently drop it */ - if (ttl == 0) { - log_lldp("TTL value 0 received. Skiping Chassis creation."); - goto drop; - } - - /* Admission Control: Can we store this packet ? */ - if (hashmap_size(neighbour_mib) >= LLDP_MIB_MAX_CHASSIS) { - - log_lldp("Exceeding number of chassie: %d. Dropping ...", - hashmap_size(neighbour_mib)); - goto drop; - } - - r = lldp_chassis_new(tlv, by_expiry, neighbour_mib, &c); - if (r < 0) - goto drop; - - new_chassis = true; - - r = hashmap_put(neighbour_mib, &c->chassis_id, c); - if (r < 0) - goto drop; - - } else { - - /* When the TTL field is set to zero, the receiving LLDP agent is notified all - * system information associated with the LLDP agent/port is to be deleted */ - if (ttl == 0) { - log_lldp("TTL value 0 received . Deleting associated Port ..."); - - lldp_mib_remove_objects(c, tlv); - - c = NULL; - goto drop; - } - - /* if we already have this port just update it */ - r = lldp_mib_update_objects(c, tlv); - if (r >= 0) { - c = NULL; - return r; - } - - /* Admission Control: Can this port attached to the existing chassis ? */ - if (c->n_ref >= LLDP_MIB_MAX_PORT_PER_CHASSIS) { - log_lldp("Port limit reached. Chassis has: %d ports. Dropping ...", c->n_ref); - - c = NULL; - goto drop; - } - } - - /* This is a new port */ - r = lldp_neighbour_port_new(c, tlv, &p); - if (r < 0) - goto drop; - - r = prioq_put(c->by_expiry, p, &p->prioq_idx); - if (r < 0) - goto drop; - - /* Attach new port to chassis */ - LIST_PREPEND(port, c->ports, p); - c->n_ref ++; - - p = NULL; - c = NULL; - - return 0; - - drop: - sd_lldp_packet_unref(tlv); - - if (new_chassis) - hashmap_remove(neighbour_mib, &c->chassis_id); - - return r; -} - -void lldp_neighbour_port_remove_and_free(lldp_neighbour_port *p) { - lldp_chassis *c; - - assert(p); - assert(p->c); - - c = p->c; - - prioq_remove(c->by_expiry, p, &p->prioq_idx); - - LIST_REMOVE(port, c->ports, p); - lldp_neighbour_port_free(p); - - /* Drop the Chassis if no port is attached */ - c->n_ref --; - if (c->n_ref <= 1) { - hashmap_remove(c->neighbour_mib, &c->chassis_id); - lldp_chassis_free(c); - } -} - -void lldp_neighbour_port_free(lldp_neighbour_port *p) { - - if(!p) - return; - - sd_lldp_packet_unref(p->packet); - - free(p->data); - free(p); -} - -int lldp_neighbour_port_new(lldp_chassis *c, - tlv_packet *tlv, - lldp_neighbour_port **ret) { - _cleanup_lldp_neighbour_port_free_ lldp_neighbour_port *p = NULL; - uint16_t length, ttl; - uint8_t *data; - uint8_t type; - int r; - - assert(tlv); - - r = sd_lldp_packet_read_port_id(tlv, &type, &data, &length); - if (r < 0) - return r; - - r = sd_lldp_packet_read_ttl(tlv, &ttl); - if (r < 0) - return r; - - p = new0(lldp_neighbour_port, 1); - if (!p) - return -ENOMEM; - - p->c = c; - p->type = type; - p->length = length; - p->packet = tlv; - p->prioq_idx = PRIOQ_IDX_NULL; - p->until = ttl * USEC_PER_SEC + now(clock_boottime_or_monotonic()); - - p->data = memdup(data, length); - if (!p->data) - return -ENOMEM; - - *ret = p; - p = NULL; - - return 0; -} - -void lldp_chassis_free(lldp_chassis *c) { - - if (!c) - return; - - if (c->n_ref > 1) - return; - - free(c->chassis_id.data); - free(c); -} - -int lldp_chassis_new(tlv_packet *tlv, - Prioq *by_expiry, - Hashmap *neighbour_mib, - lldp_chassis **ret) { - _cleanup_lldp_chassis_free_ lldp_chassis *c = NULL; - uint16_t length; - uint8_t *data; - uint8_t type; - int r; - - assert(tlv); - - r = sd_lldp_packet_read_chassis_id(tlv, &type, &data, &length); - if (r < 0) - return r; - - c = new0(lldp_chassis, 1); - if (!c) - return -ENOMEM; - - c->n_ref = 1; - c->chassis_id.type = type; - c->chassis_id.length = length; - - c->chassis_id.data = memdup(data, length); - if (!c->chassis_id.data) - return -ENOMEM; - - LIST_HEAD_INIT(c->ports); - - c->by_expiry = by_expiry; - c->neighbour_mib = neighbour_mib; - - *ret = c; - c = NULL; - - return 0; -} - -int lldp_receive_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) { - _cleanup_(sd_lldp_packet_unrefp) tlv_packet *packet = NULL; - tlv_packet *p; - uint16_t length; - int r; - - assert(fd); - assert(userdata); - - r = tlv_packet_new(&packet); - if (r < 0) - return r; - - length = read(fd, &packet->pdu, sizeof(packet->pdu)); - - /* Silently drop the packet */ - if ((size_t) length > ETHER_MAX_LEN) - return 0; - - packet->userdata = userdata; - - p = packet; - packet = NULL; - - return lldp_handle_packet(p, (uint16_t) length); -} diff --git a/src/systemd/src/libsystemd-network/lldp-internal.h b/src/systemd/src/libsystemd-network/lldp-internal.h index 15b4a11b..7592bc43 100644 --- a/src/systemd/src/libsystemd-network/lldp-internal.h +++ b/src/systemd/src/libsystemd-network/lldp-internal.h @@ -1,3 +1,5 @@ +#pragma once + /*** This file is part of systemd. @@ -18,74 +20,34 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#pragma once - #include "sd-event.h" +#include "sd-lldp.h" -#include "list.h" -#include "lldp-tlv.h" +#include "hashmap.h" #include "log.h" #include "prioq.h" -typedef struct lldp_neighbour_port lldp_neighbour_port; -typedef struct lldp_chassis lldp_chassis; -typedef struct lldp_chassis_id lldp_chassis_id; -typedef struct lldp_agent_statistics lldp_agent_statistics; +struct sd_lldp { + int ifindex; + int fd; -struct lldp_neighbour_port { - uint8_t type; - uint8_t *data; + sd_event *event; + int64_t event_priority; + sd_event_source *io_event_source; + sd_event_source *timer_event_source; - uint16_t length; - usec_t until; + Prioq *neighbor_by_expiry; + Hashmap *neighbor_by_id; - unsigned prioq_idx; + uint64_t neighbors_max; - lldp_chassis *c; - tlv_packet *packet; + sd_lldp_callback_t callback; + void *userdata; - LIST_FIELDS(lldp_neighbour_port, port); -}; + uint16_t capability_mask; -int lldp_neighbour_port_new(lldp_chassis *c, tlv_packet *tlv, lldp_neighbour_port **ret); -void lldp_neighbour_port_free(lldp_neighbour_port *p); -void lldp_neighbour_port_remove_and_free(lldp_neighbour_port *p); - -DEFINE_TRIVIAL_CLEANUP_FUNC(lldp_neighbour_port *, lldp_neighbour_port_free); -#define _cleanup_lldp_neighbour_port_free_ _cleanup_(lldp_neighbour_port_freep) - -struct lldp_chassis_id { - uint8_t type; - uint16_t length; - - uint8_t *data; + struct ether_addr filter_address; }; -struct lldp_chassis { - unsigned n_ref; - - lldp_chassis_id chassis_id; - - Prioq *by_expiry; - Hashmap *neighbour_mib; - - LIST_HEAD(lldp_neighbour_port, ports); -}; - -int lldp_chassis_new(tlv_packet *tlv, - Prioq *by_expiry, - Hashmap *neighbour_mib, - lldp_chassis **ret); - -void lldp_chassis_free(lldp_chassis *c); - -DEFINE_TRIVIAL_CLEANUP_FUNC(lldp_chassis *, lldp_chassis_free); -#define _cleanup_lldp_chassis_free_ _cleanup_(lldp_chassis_freep) - -int lldp_mib_update_objects(lldp_chassis *c, tlv_packet *tlv); -int lldp_mib_add_objects(Prioq *by_expiry, Hashmap *neighbour_mib, tlv_packet *tlv); -int lldp_mib_remove_objects(lldp_chassis *c, tlv_packet *tlv); - -int lldp_handle_packet(tlv_packet *m, uint16_t length); -int lldp_receive_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata); -#define log_lldp(fmt, ...) log_internal(LOG_DEBUG, 0, __FILE__, __LINE__, __func__, "LLDP: " fmt, ##__VA_ARGS__) +#define log_lldp_errno(error, fmt, ...) log_internal(LOG_DEBUG, error, __FILE__, __LINE__, __func__, "LLDP: " fmt, ##__VA_ARGS__) +#define log_lldp(fmt, ...) log_lldp_errno(0, fmt, ##__VA_ARGS__) diff --git a/src/systemd/src/libsystemd-network/lldp-neighbor.c b/src/systemd/src/libsystemd-network/lldp-neighbor.c new file mode 100644 index 00000000..0515ce1e --- /dev/null +++ b/src/systemd/src/libsystemd-network/lldp-neighbor.c @@ -0,0 +1,797 @@ +/*** + This file is part of systemd. + + Copyright 2016 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include "nm-sd-adapt.h" + +#include "alloc-util.h" +#include "escape.h" +#include "ether-addr-util.h" +#include "hexdecoct.h" +#include "in-addr-util.h" +#include "lldp-internal.h" +#include "lldp-neighbor.h" +#include "lldp.h" +#include "unaligned.h" + +static void lldp_neighbor_id_hash_func(const void *p, struct siphash *state) { + const LLDPNeighborID *id = p; + + siphash24_compress(id->chassis_id, id->chassis_id_size, state); + siphash24_compress(&id->chassis_id_size, sizeof(id->chassis_id_size), state); + siphash24_compress(id->port_id, id->port_id_size, state); + siphash24_compress(&id->port_id_size, sizeof(id->port_id_size), state); +} + +static int lldp_neighbor_id_compare_func(const void *a, const void *b) { + const LLDPNeighborID *x = a, *y = b; + int r; + + r = memcmp(x->chassis_id, y->chassis_id, MIN(x->chassis_id_size, y->chassis_id_size)); + if (r != 0) + return r; + + if (x->chassis_id_size < y->chassis_id_size) + return -1; + + if (x->chassis_id_size > y->chassis_id_size) + return 1; + + r = memcmp(x->port_id, y->port_id, MIN(x->port_id_size, y->port_id_size)); + if (r != 0) + return r; + + if (x->port_id_size < y->port_id_size) + return -1; + if (x->port_id_size > y->port_id_size) + return 1; + + return 0; +} + +const struct hash_ops lldp_neighbor_id_hash_ops = { + .hash = lldp_neighbor_id_hash_func, + .compare = lldp_neighbor_id_compare_func +}; + +int lldp_neighbor_prioq_compare_func(const void *a, const void *b) { + const sd_lldp_neighbor *x = a, *y = b; + + if (x->until < y->until) + return -1; + + if (x->until > y->until) + return 1; + + return 0; +} + +_public_ sd_lldp_neighbor *sd_lldp_neighbor_ref(sd_lldp_neighbor *n) { + if (!n) + return NULL; + + assert(n->n_ref > 0 || n->lldp); + n->n_ref++; + + return n; +} + +static void lldp_neighbor_free(sd_lldp_neighbor *n) { + assert(n); + + free(n->id.port_id); + free(n->id.chassis_id); + free(n->port_description); + free(n->system_name); + free(n->system_description); + free(n->chassis_id_as_string); + free(n->port_id_as_string); + free(n); +} + +_public_ sd_lldp_neighbor *sd_lldp_neighbor_unref(sd_lldp_neighbor *n) { + + /* Drops one reference from the neighbor. Note that the object is not freed unless it is already unlinked from + * the sd_lldp object. */ + + if (!n) + return NULL; + + assert(n->n_ref > 0); + n->n_ref--; + + if (n->n_ref <= 0 && !n->lldp) + lldp_neighbor_free(n); + + return NULL; +} + +sd_lldp_neighbor *lldp_neighbor_unlink(sd_lldp_neighbor *n) { + + /* Removes the neighbor object from the LLDP object, and frees it if it also has no other reference. */ + + if (!n) + return NULL; + + if (!n->lldp) + return NULL; + + assert_se(hashmap_remove(n->lldp->neighbor_by_id, &n->id) == n); + assert_se(prioq_remove(n->lldp->neighbor_by_expiry, n, &n->prioq_idx) >= 0); + + n->lldp = NULL; + + if (n->n_ref <= 0) + lldp_neighbor_free(n); + + return NULL; +} + +sd_lldp_neighbor *lldp_neighbor_new(size_t raw_size) { + sd_lldp_neighbor *n; + + n = malloc0(ALIGN(sizeof(sd_lldp_neighbor)) + raw_size); + if (!n) + return NULL; + + n->raw_size = raw_size; + n->n_ref = 1; + + return n; +} + +static int parse_string(char **s, const void *q, size_t n) { + const char *p = q; + char *k; + + assert(s); + assert(p || n == 0); + + if (*s) { + log_lldp("Found duplicate string, ignoring field."); + return 0; + } + + /* Strip trailing NULs, just to be nice */ + while (n > 0 && p[n-1] == 0) + n--; + + if (n <= 0) /* Ignore empty strings */ + return 0; + + /* Look for inner NULs */ + if (memchr(p, 0, n)) { + log_lldp("Found inner NUL in string, ignoring field."); + return 0; + } + + /* Let's escape weird chars, for security reasons */ + k = cescape_length(p, n); + if (!k) + return -ENOMEM; + + free(*s); + *s = k; + + return 1; +} + +int lldp_neighbor_parse(sd_lldp_neighbor *n) { + struct ether_header h; + const uint8_t *p; + size_t left; + int r; + + assert(n); + + if (n->raw_size < sizeof(struct ether_header)) { + log_lldp("Recieved truncated packet, ignoring."); + return -EBADMSG; + } + + memcpy(&h, LLDP_NEIGHBOR_RAW(n), sizeof(h)); + + if (h.ether_type != htobe16(ETHERTYPE_LLDP)) { + log_lldp("Received packet with wrong type, ignoring."); + return -EBADMSG; + } + + if (h.ether_dhost[0] != 0x01 || + h.ether_dhost[1] != 0x80 || + h.ether_dhost[2] != 0xc2 || + h.ether_dhost[3] != 0x00 || + h.ether_dhost[4] != 0x00 || + !IN_SET(h.ether_dhost[5], 0x00, 0x03, 0x0e)) { + log_lldp("Received packet with wrong destination address, ignoring."); + return -EBADMSG; + } + + memcpy(&n->source_address, h.ether_shost, sizeof(struct ether_addr)); + memcpy(&n->destination_address, h.ether_dhost, sizeof(struct ether_addr)); + + p = (const uint8_t*) LLDP_NEIGHBOR_RAW(n) + sizeof(struct ether_header); + left = n->raw_size - sizeof(struct ether_header); + + for (;;) { + uint8_t type; + uint16_t length; + + if (left < 2) { + log_lldp("TLV lacks header, ignoring."); + return -EBADMSG; + } + + type = p[0] >> 1; + length = p[1] + (((uint16_t) (p[0] & 1)) << 8); + p += 2, left -= 2; + + if (left < length) { + log_lldp("TLV truncated, ignoring datagram."); + return -EBADMSG; + } + + switch (type) { + + case LLDP_TYPE_END: + if (length != 0) { + log_lldp("End marker TLV not zero-sized, ignoring datagram."); + return -EBADMSG; + } + if (left != 0) { + log_lldp("Trailing garbage in datagram, ignoring datagram."); + return -EBADMSG; + } + + goto end_marker; + + case LLDP_TYPE_CHASSIS_ID: + if (length < 2 || length > 256) { /* includes the chassis subtype, hence one extra byte */ + log_lldp("Chassis ID field size out of range, ignoring datagram."); + return -EBADMSG; + } + if (n->id.chassis_id) { + log_lldp("Duplicate chassis ID field, ignoring datagram."); + return -EBADMSG; + } + + n->id.chassis_id = memdup(p, length); + if (!n->id.chassis_id) + return -ENOMEM; + + n->id.chassis_id_size = length; + break; + + case LLDP_TYPE_PORT_ID: + if (length < 2 || length > 256) { /* includes the port subtype, hence one extra byte */ + log_lldp("Port ID field size out of range, ignoring datagram."); + return -EBADMSG; + } + if (n->id.port_id) { + log_lldp("Duplicate port ID field, ignoring datagram."); + return -EBADMSG; + } + + n->id.port_id = memdup(p, length); + if (!n->id.port_id) + return -ENOMEM; + + n->id.port_id_size = length; + break; + + case LLDP_TYPE_TTL: + if (length != 2) { + log_lldp("TTL field has wrong size, ignoring datagram."); + return -EBADMSG; + } + + if (n->has_ttl) { + log_lldp("Duplicate TTL field, ignoring datagram."); + return -EBADMSG; + } + + n->ttl = unaligned_read_be16(p); + n->has_ttl = true; + break; + + case LLDP_TYPE_PORT_DESCRIPTION: + r = parse_string(&n->port_description, p, length); + if (r < 0) + return r; + break; + + case LLDP_TYPE_SYSTEM_NAME: + r = parse_string(&n->system_name, p, length); + if (r < 0) + return r; + break; + + case LLDP_TYPE_SYSTEM_DESCRIPTION: + r = parse_string(&n->system_description, p, length); + if (r < 0) + return r; + break; + + case LLDP_TYPE_SYSTEM_CAPABILITIES: + if (length != 4) + log_lldp("System capabilities field has wrong size, ignoring."); + else { + n->system_capabilities = unaligned_read_be16(p); + n->enabled_capabilities = unaligned_read_be16(p + 2); + n->has_capabilities = true; + } + + break; + + case LLDP_TYPE_PRIVATE: + if (length < 4) + log_lldp("Found private TLV that is too short, ignoring."); + + break; + } + + + p += length, left -= length; + } + +end_marker: + if (!n->id.chassis_id || !n->id.port_id || !n->has_ttl) { + log_lldp("One or more mandatory TLV missing in datagram. Ignoring."); + return -EBADMSG; + + } + + n->rindex = sizeof(struct ether_header); + + return 0; +} + +void lldp_neighbor_start_ttl(sd_lldp_neighbor *n) { + assert(n); + + if (n->ttl > 0) + n->until = usec_add(now(clock_boottime_or_monotonic()), n->ttl * USEC_PER_SEC); + else + n->until = 0; + + if (n->lldp) + prioq_reshuffle(n->lldp->neighbor_by_expiry, n, &n->prioq_idx); +} + +bool lldp_neighbor_equal(const sd_lldp_neighbor *a, const sd_lldp_neighbor *b) { + if (a == b) + return true; + + if (!a || !b) + return false; + + if (a->raw_size != b->raw_size) + return false; + + return memcmp(LLDP_NEIGHBOR_RAW(a), LLDP_NEIGHBOR_RAW(b), a->raw_size) == 0; +} + +_public_ int sd_lldp_neighbor_get_source_address(sd_lldp_neighbor *n, struct ether_addr* address) { + assert_return(n, -EINVAL); + assert_return(address, -EINVAL); + + *address = n->source_address; + return 0; +} + +_public_ int sd_lldp_neighbor_get_destination_address(sd_lldp_neighbor *n, struct ether_addr* address) { + assert_return(n, -EINVAL); + assert_return(address, -EINVAL); + + *address = n->destination_address; + return 0; +} + +_public_ int sd_lldp_neighbor_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size) { + assert_return(n, -EINVAL); + assert_return(ret, -EINVAL); + assert_return(size, -EINVAL); + + *ret = LLDP_NEIGHBOR_RAW(n); + *size = n->raw_size; + + return 0; +} + +_public_ int sd_lldp_neighbor_get_chassis_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size) { + assert_return(n, -EINVAL); + assert_return(type, -EINVAL); + assert_return(ret, -EINVAL); + assert_return(size, -EINVAL); + + assert(n->id.chassis_id_size > 0); + + *type = *(uint8_t*) n->id.chassis_id; + *ret = (uint8_t*) n->id.chassis_id + 1; + *size = n->id.chassis_id_size - 1; + + return 0; +} + +static int format_mac_address(const void *data, size_t sz, char **ret) { + struct ether_addr a; + char *k; + + assert(data || sz <= 0); + + if (sz != 7) + return 0; + + memcpy(&a, (uint8_t*) data + 1, sizeof(a)); + + k = new(char, ETHER_ADDR_TO_STRING_MAX); + if (!k) + return -ENOMEM; + + *ret = ether_addr_to_string(&a, k); + return 1; +} + +static int format_network_address(const void *data, size_t sz, char **ret) { + union in_addr_union a; + int family, r; + + if (sz == 6 && ((uint8_t*) data)[1] == 1) { + memcpy(&a.in, (uint8_t*) data + 2, sizeof(a.in)); + family = AF_INET; + } else if (sz == 18 && ((uint8_t*) data)[1] == 2) { + memcpy(&a.in6, (uint8_t*) data + 2, sizeof(a.in6)); + family = AF_INET6; + } else + return 0; + + r = in_addr_to_string(family, &a, ret); + if (r < 0) + return r; + return 1; +} + +_public_ int sd_lldp_neighbor_get_chassis_id_as_string(sd_lldp_neighbor *n, const char **ret) { + char *k; + int r; + + assert_return(n, -EINVAL); + assert_return(ret, -EINVAL); + + if (n->chassis_id_as_string) { + *ret = n->chassis_id_as_string; + return 0; + } + + assert(n->id.chassis_id_size > 0); + + switch (*(uint8_t*) n->id.chassis_id) { + + case LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT: + case LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS: + case LLDP_CHASSIS_SUBTYPE_PORT_COMPONENT: + case LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME: + case LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED: + k = cescape_length((char*) n->id.chassis_id + 1, n->id.chassis_id_size - 1); + if (!k) + return -ENOMEM; + + goto done; + + case LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS: + r = format_mac_address(n->id.chassis_id, n->id.chassis_id_size, &k); + if (r < 0) + return r; + if (r > 0) + goto done; + + break; + + case LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS: + r = format_network_address(n->id.chassis_id, n->id.chassis_id_size, &k); + if (r < 0) + return r; + if (r > 0) + goto done; + + break; + } + + /* Generic fallback */ + k = hexmem(n->id.chassis_id, n->id.chassis_id_size); + if (!k) + return -ENOMEM; + +done: + *ret = n->chassis_id_as_string = k; + return 0; +} + +_public_ int sd_lldp_neighbor_get_port_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size) { + assert_return(n, -EINVAL); + assert_return(type, -EINVAL); + assert_return(ret, -EINVAL); + assert_return(size, -EINVAL); + + assert(n->id.port_id_size > 0); + + *type = *(uint8_t*) n->id.port_id; + *ret = (uint8_t*) n->id.port_id + 1; + *size = n->id.port_id_size - 1; + + return 0; +} + +_public_ int sd_lldp_neighbor_get_port_id_as_string(sd_lldp_neighbor *n, const char **ret) { + char *k; + int r; + + assert_return(n, -EINVAL); + assert_return(ret, -EINVAL); + + if (n->port_id_as_string) { + *ret = n->port_id_as_string; + return 0; + } + + assert(n->id.port_id_size > 0); + + switch (*(uint8_t*) n->id.port_id) { + + case LLDP_PORT_SUBTYPE_INTERFACE_ALIAS: + case LLDP_PORT_SUBTYPE_PORT_COMPONENT: + case LLDP_PORT_SUBTYPE_INTERFACE_NAME: + case LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED: + k = cescape_length((char*) n->id.port_id + 1, n->id.port_id_size - 1); + if (!k) + return -ENOMEM; + + goto done; + + case LLDP_PORT_SUBTYPE_MAC_ADDRESS: + r = format_mac_address(n->id.port_id, n->id.port_id_size, &k); + if (r < 0) + return r; + if (r > 0) + goto done; + + break; + + case LLDP_PORT_SUBTYPE_NETWORK_ADDRESS: + r = format_network_address(n->id.port_id, n->id.port_id_size, &k); + if (r < 0) + return r; + if (r > 0) + goto done; + + break; + } + + /* Generic fallback */ + k = hexmem(n->id.port_id, n->id.port_id_size); + if (!k) + return -ENOMEM; + +done: + *ret = n->port_id_as_string = k; + return 0; +} + +_public_ int sd_lldp_neighbor_get_ttl(sd_lldp_neighbor *n, uint16_t *ret) { + assert_return(n, -EINVAL); + assert_return(ret, -EINVAL); + + *ret = n->ttl; + return 0; +} + +_public_ int sd_lldp_neighbor_get_system_name(sd_lldp_neighbor *n, const char **ret) { + assert_return(n, -EINVAL); + assert_return(ret, -EINVAL); + + if (!n->system_name) + return -ENODATA; + + *ret = n->system_name; + return 0; +} + +_public_ int sd_lldp_neighbor_get_system_description(sd_lldp_neighbor *n, const char **ret) { + assert_return(n, -EINVAL); + assert_return(ret, -EINVAL); + + if (!n->system_description) + return -ENODATA; + + *ret = n->system_description; + return 0; +} + +_public_ int sd_lldp_neighbor_get_port_description(sd_lldp_neighbor *n, const char **ret) { + assert_return(n, -EINVAL); + assert_return(ret, -EINVAL); + + if (!n->port_description) + return -ENODATA; + + *ret = n->port_description; + return 0; +} + +_public_ int sd_lldp_neighbor_get_system_capabilities(sd_lldp_neighbor *n, uint16_t *ret) { + assert_return(n, -EINVAL); + assert_return(ret, -EINVAL); + + if (!n->has_capabilities) + return -ENODATA; + + *ret = n->system_capabilities; + return 0; +} + +_public_ int sd_lldp_neighbor_get_enabled_capabilities(sd_lldp_neighbor *n, uint16_t *ret) { + assert_return(n, -EINVAL); + assert_return(ret, -EINVAL); + + if (!n->has_capabilities) + return -ENODATA; + + *ret = n->enabled_capabilities; + return 0; +} + +int sd_lldp_neighbor_from_raw(sd_lldp_neighbor **ret, const void *raw, size_t raw_size) { + _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL; + int r; + + assert_return(ret, -EINVAL); + assert_return(raw || raw_size <= 0, -EINVAL); + + n = lldp_neighbor_new(raw_size); + if (!n) + return -ENOMEM; + + memcpy(LLDP_NEIGHBOR_RAW(n), raw, raw_size); + r = lldp_neighbor_parse(n); + if (r < 0) + return r; + + *ret = n; + n = 0; + + return r; +} + +_public_ int sd_lldp_neighbor_tlv_rewind(sd_lldp_neighbor *n) { + assert_return(n, -EINVAL); + + assert(n->raw_size >= sizeof(struct ether_header)); + n->rindex = sizeof(struct ether_header); + + return 0; +} + +_public_ int sd_lldp_neighbor_tlv_next(sd_lldp_neighbor *n) { + size_t length; + + assert_return(n, -EINVAL); + + if (n->rindex == n->raw_size) /* EOF */ + return -ESPIPE; + + if (n->rindex + 2 > n->raw_size) /* Truncated message */ + return -EBADMSG; + + length = LLDP_NEIGHBOR_LENGTH(n); + if (n->rindex + 2 + length > n->raw_size) + return -EBADMSG; + + n->rindex += 2 + length; + return n->rindex < n->raw_size; +} + +_public_ int sd_lldp_neighbor_tlv_get_type(sd_lldp_neighbor *n, uint8_t *type) { + assert_return(n, -EINVAL); + assert_return(type, -EINVAL); + + if (n->rindex == n->raw_size) /* EOF */ + return -ESPIPE; + + if (n->rindex + 2 > n->raw_size) + return -EBADMSG; + + *type = LLDP_NEIGHBOR_TYPE(n); + return 0; +} + +_public_ int sd_lldp_neighbor_tlv_is_type(sd_lldp_neighbor *n, uint8_t type) { + uint8_t k; + int r; + + assert_return(n, -EINVAL); + + r = sd_lldp_neighbor_tlv_get_type(n, &k); + if (r < 0) + return r; + + return type == k; +} + +_public_ int sd_lldp_neighbor_tlv_get_oui(sd_lldp_neighbor *n, uint8_t oui[3], uint8_t *subtype) { + const uint8_t *d; + size_t length; + int r; + + assert_return(n, -EINVAL); + assert_return(oui, -EINVAL); + assert_return(subtype, -EINVAL); + + r = sd_lldp_neighbor_tlv_is_type(n, LLDP_TYPE_PRIVATE); + if (r < 0) + return r; + if (r == 0) + return -ENXIO; + + length = LLDP_NEIGHBOR_LENGTH(n); + if (length < 4) + return -EBADMSG; + + if (n->rindex + 2 + length > n->raw_size) + return -EBADMSG; + + d = LLDP_NEIGHBOR_DATA(n); + memcpy(oui, d, 3); + *subtype = d[3]; + + return 0; +} + +_public_ int sd_lldp_neighbor_tlv_is_oui(sd_lldp_neighbor *n, const uint8_t oui[3], uint8_t subtype) { + uint8_t k[3], st; + int r; + + r = sd_lldp_neighbor_tlv_get_oui(n, k, &st); + if (r == -ENXIO) + return 0; + if (r < 0) + return r; + + return memcmp(k, oui, 3) == 0 && st == subtype; +} + +_public_ int sd_lldp_neighbor_tlv_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size) { + size_t length; + + assert_return(n, -EINVAL); + assert_return(ret, -EINVAL); + assert_return(size, -EINVAL); + + /* Note that this returns the full TLV, including the TLV header */ + + if (n->rindex + 2 > n->raw_size) + return -EBADMSG; + + length = LLDP_NEIGHBOR_LENGTH(n); + + if (n->rindex + 2 + length > n->raw_size) + return -EBADMSG; + + *ret = (uint8_t*) LLDP_NEIGHBOR_RAW(n) + n->rindex; + *size = length + 2; + + return 0; +} diff --git a/src/systemd/src/libsystemd-network/lldp-neighbor.h b/src/systemd/src/libsystemd-network/lldp-neighbor.h new file mode 100644 index 00000000..f203bfa6 --- /dev/null +++ b/src/systemd/src/libsystemd-network/lldp-neighbor.h @@ -0,0 +1,106 @@ +#pragma once + +/*** + This file is part of systemd. + + Copyright 2016 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <inttypes.h> +#include <stdbool.h> +#include <sys/types.h> + +#include "sd-lldp.h" + +#include "hash-funcs.h" +#include "lldp-internal.h" +#include "time-util.h" + +typedef struct LLDPNeighborID { + /* The spec calls this an "MSAP identifier" */ + void *chassis_id; + size_t chassis_id_size; + + void *port_id; + size_t port_id_size; +} LLDPNeighborID; + +struct sd_lldp_neighbor { + /* Neighbor objects stay around as long as they are linked into an "sd_lldp" object or n_ref > 0. */ + sd_lldp *lldp; + unsigned n_ref; + + usec_t until; + unsigned prioq_idx; + + struct ether_addr source_address; + struct ether_addr destination_address; + + LLDPNeighborID id; + + /* The raw packet size. The data is appended to the object, accessible via LLDP_NEIGHBOR_RAW() */ + size_t raw_size; + + /* The current read index for the iterative TLV interface */ + size_t rindex; + + /* And a couple of fields parsed out. */ + bool has_ttl:1; + bool has_capabilities:1; + bool has_port_vlan_id:1; + + uint16_t ttl; + + uint16_t system_capabilities; + uint16_t enabled_capabilities; + + char *port_description; + char *system_name; + char *system_description; + + uint16_t port_vlan_id; + + char *chassis_id_as_string; + char *port_id_as_string; +}; + +static inline void *LLDP_NEIGHBOR_RAW(const sd_lldp_neighbor *n) { + return (uint8_t*) n + ALIGN(sizeof(sd_lldp_neighbor)); +} + +static inline uint8_t LLDP_NEIGHBOR_TYPE(const sd_lldp_neighbor *n) { + return ((uint8_t*) LLDP_NEIGHBOR_RAW(n))[n->rindex] >> 1; +} + +static inline size_t LLDP_NEIGHBOR_LENGTH(const sd_lldp_neighbor *n) { + uint8_t *p; + + p = (uint8_t*) LLDP_NEIGHBOR_RAW(n) + n->rindex; + return p[1] + (((size_t) (p[0] & 1)) << 8); +} + +static inline void* LLDP_NEIGHBOR_DATA(const sd_lldp_neighbor *n) { + return ((uint8_t*) LLDP_NEIGHBOR_RAW(n)) + n->rindex + 2; +} + +extern const struct hash_ops lldp_neighbor_id_hash_ops; +int lldp_neighbor_prioq_compare_func(const void *a, const void *b); + +sd_lldp_neighbor *lldp_neighbor_unlink(sd_lldp_neighbor *n); +sd_lldp_neighbor *lldp_neighbor_new(size_t raw_size); +int lldp_neighbor_parse(sd_lldp_neighbor *n); +void lldp_neighbor_start_ttl(sd_lldp_neighbor *n); +bool lldp_neighbor_equal(const sd_lldp_neighbor *a, const sd_lldp_neighbor *b); diff --git a/src/systemd/src/libsystemd-network/lldp-network.c b/src/systemd/src/libsystemd-network/lldp-network.c index b96e9741..658448f6 100644 --- a/src/systemd/src/libsystemd-network/lldp-network.c +++ b/src/systemd/src/libsystemd-network/lldp-network.c @@ -21,65 +21,58 @@ #include "nm-sd-adapt.h" #include <linux/filter.h> -#include <linux/if_ether.h> +#include <netinet/if_ether.h> #include "fd-util.h" -#include "lldp-internal.h" #include "lldp-network.h" -#include "lldp-tlv.h" #include "socket-util.h" int lldp_network_bind_raw_socket(int ifindex) { - typedef struct LLDPFrame { - struct ethhdr hdr; - uint8_t tlvs[0]; - } LLDPFrame; - struct sock_filter filter[] = { - BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(LLDPFrame, hdr.h_dest)), /* A <- 4 bytes of destination MAC */ + static const struct sock_filter filter[] = { + BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct ethhdr, h_dest)), /* A <- 4 bytes of destination MAC */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0180c200, 1, 0), /* A != 01:80:c2:00 */ BPF_STMT(BPF_RET + BPF_K, 0), /* drop packet */ - BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(LLDPFrame, hdr.h_dest) + 4), /* A <- remaining 2 bytes of destination MAC */ + BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ethhdr, h_dest) + 4), /* A <- remaining 2 bytes of destination MAC */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0000, 3, 0), /* A != 00:00 */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0003, 2, 0), /* A != 00:03 */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x000e, 1, 0), /* A != 00:0e */ BPF_STMT(BPF_RET + BPF_K, 0), /* drop packet */ - BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(LLDPFrame, hdr.h_proto)), /* A <- protocol */ + BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ethhdr, h_proto)), /* A <- protocol */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_LLDP, 1, 0), /* A != ETHERTYPE_LLDP */ BPF_STMT(BPF_RET + BPF_K, 0), /* drop packet */ BPF_STMT(BPF_RET + BPF_K, (uint32_t) -1), /* accept packet */ }; - struct sock_fprog fprog = { + static const struct sock_fprog fprog = { .len = ELEMENTSOF(filter), - .filter = filter + .filter = (struct sock_filter*) filter, }; - _cleanup_close_ int s = -1; - union sockaddr_union saddrll = { .ll.sll_family = AF_PACKET, .ll.sll_ifindex = ifindex, }; + _cleanup_close_ int fd = -1; int r; assert(ifindex > 0); - s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); - if (s < 0) + fd = socket(PF_PACKET, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, htons(ETHERTYPE_LLDP)); + if (fd < 0) return -errno; - r = setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)); + r = setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)); if (r < 0) return -errno; - r = bind(s, &saddrll.sa, sizeof(saddrll.ll)); + r = bind(fd, &saddrll.sa, sizeof(saddrll.ll)); if (r < 0) return -errno; - r = s; - s = -1; + r = fd; + fd = -1; return r; } diff --git a/src/systemd/src/libsystemd-network/lldp-network.h b/src/systemd/src/libsystemd-network/lldp-network.h index dcf31faa..c4cf8c79 100644 --- a/src/systemd/src/libsystemd-network/lldp-network.h +++ b/src/systemd/src/libsystemd-network/lldp-network.h @@ -1,3 +1,5 @@ +#pragma once + /*** This file is part of systemd. @@ -18,8 +20,6 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#pragma once - #include "sd-event.h" int lldp_network_bind_raw_socket(int ifindex); diff --git a/src/systemd/src/libsystemd-network/lldp-port.c b/src/systemd/src/libsystemd-network/lldp-port.c deleted file mode 100644 index e96ef8a7..00000000 --- a/src/systemd/src/libsystemd-network/lldp-port.c +++ /dev/null @@ -1,118 +0,0 @@ -/*** - This file is part of systemd. - - Copyright (C) 2014 Tom Gundersen - Copyright (C) 2014 Susant Sahani - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include "nm-sd-adapt.h" - -#include "alloc-util.h" -#include "async.h" -#include "lldp-internal.h" -#include "lldp-network.h" -#include "lldp-port.h" - -int lldp_port_start(lldp_port *p) { - int r; - - assert_return(p, -EINVAL); - - r = lldp_network_bind_raw_socket(p->ifindex); - if (r < 0) - return r; - - p->rawfd = r; - - r = sd_event_add_io(p->event, &p->lldp_port_rx, - p->rawfd, EPOLLIN, lldp_receive_packet, p); - if (r < 0) { - log_debug_errno(r, "Failed to allocate event source: %m"); - goto fail; - } - - r = sd_event_source_set_priority(p->lldp_port_rx, p->event_priority); - if (r < 0) { - log_debug_errno(r, "Failed to set event priority: %m"); - goto fail; - } - - r = sd_event_source_set_description(p->lldp_port_rx, "lldp-port-rx"); - if (r < 0) { - log_debug_errno(r, "Failed to set event name: %m"); - goto fail; - } - - return 0; - -fail: - lldp_port_stop(p); - - return r; -} - -int lldp_port_stop(lldp_port *p) { - - assert_return(p, -EINVAL); - - p->rawfd = asynchronous_close(p->rawfd); - p->lldp_port_rx = sd_event_source_unref(p->lldp_port_rx); - - return 0; -} - -void lldp_port_free(lldp_port *p) { - if (!p) - return; - - lldp_port_stop(p); - - free(p->ifname); - free(p); -} - -int lldp_port_new(int ifindex, - const char *ifname, - const struct ether_addr *addr, - void *userdata, - lldp_port **ret) { - _cleanup_free_ lldp_port *p = NULL; - - assert_return(ifindex, -EINVAL); - assert_return(ifname, -EINVAL); - assert_return(addr, -EINVAL); - - p = new0(lldp_port, 1); - if (!p) - return -ENOMEM; - - p->rawfd = -1; - p->ifindex = ifindex; - - p->ifname = strdup(ifname); - if (!p->ifname) - return -ENOMEM; - - memcpy(&p->mac, addr, ETH_ALEN); - - p->userdata = userdata; - - *ret = p; - - p = NULL; - - return 0; -} diff --git a/src/systemd/src/libsystemd-network/lldp-port.h b/src/systemd/src/libsystemd-network/lldp-port.h deleted file mode 100644 index 96092f8d..00000000 --- a/src/systemd/src/libsystemd-network/lldp-port.h +++ /dev/null @@ -1,69 +0,0 @@ -/*** - This file is part of systemd. - - Copyright (C) 2014 Tom Gundersen - Copyright (C) 2014 Susant Sahani - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#pragma once - -#include <net/ethernet.h> - -#include "sd-event.h" -#include "sd-lldp.h" - -#include "util.h" - -typedef struct lldp_port lldp_port; - -typedef enum LLDPPortStatus { - LLDP_PORT_STATUS_NONE, - LLDP_PORT_STATUS_ENABLED, - LLDP_PORT_STATUS_DISABLED, - _LLDP_PORT_STATUS_MAX, - _LLDP_PORT_STATUS_INVALID = -1, -} LLDPPortStatus; - -struct lldp_port { - LLDPPortStatus status; - - int ifindex; - char *ifname; - - struct ether_addr mac; - - int rawfd; - - sd_event *event; - sd_event_source *lldp_port_rx; - - int event_priority; - - void *userdata; -}; - -int lldp_port_new(int ifindex, - const char *ifname, - const struct ether_addr *addr, - void *userdata, - lldp_port **ret); -void lldp_port_free(lldp_port *p); - -DEFINE_TRIVIAL_CLEANUP_FUNC(lldp_port*, lldp_port_free); -#define _cleanup_lldp_port_free_ _cleanup_(lldp_port_freep) - -int lldp_port_start(lldp_port *p); -int lldp_port_stop(lldp_port *p); diff --git a/src/systemd/src/libsystemd-network/lldp-tlv.c b/src/systemd/src/libsystemd-network/lldp-tlv.c deleted file mode 100644 index 28161bc1..00000000 --- a/src/systemd/src/libsystemd-network/lldp-tlv.c +++ /dev/null @@ -1,640 +0,0 @@ -/*** - This file is part of systemd. - - Copyright (C) 2014 Tom Gundersen - Copyright (C) 2014 Susant Sahani - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include "nm-sd-adapt.h" - -#include <arpa/inet.h> -#include <net/ethernet.h> - -#include "alloc-util.h" -#include "lldp-tlv.h" -#include "macro.h" - -int tlv_section_new(tlv_section **ret) { - tlv_section *s; - - s = new0(tlv_section, 1); - if (!s) - return -ENOMEM; - - *ret = s; - - return 0; -} - -void tlv_section_free(tlv_section *m) { - - if (!m) - return; - - free(m); -} - -int tlv_packet_new(tlv_packet **ret) { - tlv_packet *m; - - m = new0(tlv_packet, 1); - if (!m) - return -ENOMEM; - - LIST_HEAD_INIT(m->sections); - m->n_ref = 1; - - *ret = m; - - return 0; -} - -tlv_packet *sd_lldp_packet_ref(tlv_packet *m) { - - if (!m) - return NULL; - - assert(m->n_ref > 0); - m->n_ref++; - - return m; -} - -tlv_packet *sd_lldp_packet_unref(tlv_packet *m) { - tlv_section *s, *n; - - if (!m) - return NULL; - - assert(m->n_ref > 0); - m->n_ref--; - - if (m->n_ref > 0) - return m; - - LIST_FOREACH_SAFE(section, s, n, m->sections) - tlv_section_free(s); - - free(m); - return NULL; -} - -int tlv_packet_append_bytes(tlv_packet *m, const void *data, size_t data_length) { - uint8_t *p; - - assert_return(m, -EINVAL); - assert_return(data, -EINVAL); - assert_return(data_length, -EINVAL); - - if (m->length + data_length > ETHER_MAX_LEN) - return -ENOMEM; - - p = m->pdu + m->length; - memcpy(p, data, data_length); - m->length += data_length; - - return 0; -} - -int tlv_packet_append_u8(tlv_packet *m, uint8_t data) { - - assert_return(m, -EINVAL); - - return tlv_packet_append_bytes(m, &data, sizeof(uint8_t)); -} - -int tlv_packet_append_u16(tlv_packet *m, uint16_t data) { - uint16_t type; - - assert_return(m, -EINVAL); - - type = htons(data); - - return tlv_packet_append_bytes(m, &type, sizeof(uint16_t)); -} - -int tlv_packet_append_u32(tlv_packet *m, uint32_t data) { - uint32_t type; - - assert_return(m, -EINVAL); - - type = htonl(data); - - return tlv_packet_append_bytes(m, &type, sizeof(uint32_t)); -} - -int tlv_packet_append_string(tlv_packet *m, char *data, uint16_t size) { - - assert_return(m, -EINVAL); - - return tlv_packet_append_bytes(m, data, size); -} - -int lldp_tlv_packet_open_container(tlv_packet *m, uint16_t type) { - - assert_return(m, -EINVAL); - - m->container_pos = m->pdu + m->length; - - return tlv_packet_append_u16(m, type << 9); -} - -int lldp_tlv_packet_close_container(tlv_packet *m) { - uint16_t type; - - assert_return(m, -EINVAL); - assert_return(m->container_pos, -EINVAL); - - memcpy(&type, m->container_pos, sizeof(uint16_t)); - - type |= htons(((m->pdu + m->length) - (m->container_pos + 2)) & 0x01ff); - memcpy(m->container_pos, &type, sizeof(uint16_t)); - - return 0; -} - -static inline int tlv_packet_read_internal(tlv_section *m, void **data) { - - assert_return(m->read_pos, -EINVAL); - - *data = m->read_pos; - - return 0; -} - -int tlv_packet_read_u8(tlv_packet *m, uint8_t *data) { - void *val = NULL; - int r; - - assert_return(m, -EINVAL); - - r = tlv_packet_read_internal(m->container, &val); - if (r < 0) - return r; - - memcpy(data, val, sizeof(uint8_t)); - - m->container->read_pos ++; - - return 0; -} - -int tlv_packet_read_u16(tlv_packet *m, uint16_t *data) { - uint16_t t; - void *val = NULL; - int r; - - assert_return(m, -EINVAL); - - r = tlv_packet_read_internal(m->container, &val); - if (r < 0) - return r; - - memcpy(&t, val, sizeof(uint16_t)); - *data = ntohs(t); - - m->container->read_pos += 2; - - return 0; -} - -int tlv_packet_read_u32(tlv_packet *m, uint32_t *data) { - uint32_t t; - void *val; - int r; - - assert_return(m, -EINVAL); - - r = tlv_packet_read_internal(m->container, &val); - if (r < 0) - return r; - - memcpy(&t, val, sizeof(uint32_t)); - *data = ntohl(t); - - m->container->read_pos += 4; - - return r; -} - -int tlv_packet_read_string(tlv_packet *m, char **data, uint16_t *data_length) { - void *val = NULL; - int r; - - assert_return(m, -EINVAL); - - r = tlv_packet_read_internal(m->container, &val); - if (r < 0) - return r; - - *data = (char *) val; - *data_length = m->container->data + m->container->length - m->container->read_pos; - - m->container->read_pos += *data_length; - - return 0; -} - -int tlv_packet_read_bytes(tlv_packet *m, uint8_t **data, uint16_t *data_length) { - void *val = NULL; - int r; - - assert_return(m, -EINVAL); - - r = tlv_packet_read_internal(m->container, &val); - if (r < 0) - return r; - - *data = (uint8_t *) val; - *data_length = m->container->data + m->container->length - m->container->read_pos; - - m->container->read_pos += *data_length; - - return 0; -} - -/* parse raw TLV packet */ -int tlv_packet_parse_pdu(tlv_packet *m, uint16_t size) { - tlv_section *section, *tail; - uint16_t t, l; - uint8_t *p; - int r; - - assert_return(m, -EINVAL); - assert_return(size, -EINVAL); - - p = m->pdu; - - /* extract Ethernet header */ - memcpy(&m->mac, p, ETH_ALEN); - p += sizeof(struct ether_header); - - for (l = 0; l <= size; ) { - r = tlv_section_new(§ion); - if (r < 0) - return r; - - memcpy(&t, p, sizeof(uint16_t)); - - section->type = ntohs(t) >> 9; - section->length = ntohs(t) & 0x01ff; - - if (section->type == LLDP_TYPE_END || section->type >=_LLDP_TYPE_MAX) { - tlv_section_free(section); - break; - } - - p += 2; - - if (section->type == LLDP_TYPE_PRIVATE && - section->length >= LLDP_OUI_LEN + 1) { - section->oui = p; - p += LLDP_OUI_LEN; - section->subtype = *p++; - - section->length -= LLDP_OUI_LEN + 1; - l += LLDP_OUI_LEN + 1; - } - - section->data = p; - - LIST_FIND_TAIL(section, m->sections, tail); - LIST_INSERT_AFTER(section, m->sections, tail, section); - - p += section->length; - l += (section->length + 2); - } - - return 0; -} - -int lldp_tlv_packet_enter_container(tlv_packet *m, uint16_t type) { - tlv_section *s; - - assert_return(m, -EINVAL); - assert_return(type != LLDP_TYPE_PRIVATE, -EINVAL); - - LIST_FOREACH(section, s, m->sections) - if (s->type == type) - break; - if (!s) - return -1; - - m->container = s; - - m->container->read_pos = s->data; - if (!m->container->read_pos) { - m->container = NULL; - return -1; - } - - return 0; -} - -int lldp_tlv_packet_enter_container_oui(tlv_packet *m, const uint8_t *oui, uint8_t subtype) { - tlv_section *s; - - assert_return(m, -EINVAL); - assert_return(oui, -EINVAL); - - LIST_FOREACH(section, s, m->sections) { - if (s->type == LLDP_TYPE_PRIVATE && - s->oui && - s->subtype == subtype && - !memcmp(s->oui, oui, LLDP_OUI_LEN)) - break; - } - - if (!s) - return -1; - - m->container = s; - - m->container->read_pos = s->data; - if (!m->container->read_pos) { - m->container = NULL; - return -1; - } - - return 0; -} - -int lldp_tlv_packet_exit_container(tlv_packet *m) { - assert_return(m, -EINVAL); - - m->container = 0; - - return 0; -} - -static int lldp_tlv_packet_read_u16_tlv(tlv_packet *tlv, uint16_t type, uint16_t *value) { - int r, r2; - - assert_return(tlv, -EINVAL); - - r = lldp_tlv_packet_enter_container(tlv, type); - if (r < 0) - return r; - - r = tlv_packet_read_u16(tlv, value); - r2 = lldp_tlv_packet_exit_container(tlv); - - return r < 0 ? r : r2; -} - -static int lldp_tlv_packet_read_string_tlv(tlv_packet *tlv, uint16_t type, char **data, uint16_t *length) { - char *s; - int r, r2; - - assert_return(tlv, -EINVAL); - - r = lldp_tlv_packet_enter_container(tlv, type); - if (r < 0) - return r; - - r = tlv_packet_read_string(tlv, &s, length); - if (r < 0) - goto out; - - *data = (char *) s; - - out: - r2 = lldp_tlv_packet_exit_container(tlv); - - return r < 0 ? r : r2; -} - -int sd_lldp_packet_read_chassis_id(tlv_packet *tlv, - uint8_t *type, - uint8_t **data, - uint16_t *length) { - uint8_t subtype; - int r, r2; - - assert_return(tlv, -EINVAL); - - r = lldp_tlv_packet_enter_container(tlv, LLDP_TYPE_CHASSIS_ID); - if (r < 0) - return r; - - r = tlv_packet_read_u8(tlv, &subtype); - if (r < 0) - goto out; - - switch (subtype) { - case LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS: - - r = tlv_packet_read_bytes(tlv, data, length); - if (r < 0) - goto out; - - break; - default: - r = -EOPNOTSUPP; - break; - } - - *type = subtype; - - out: - r2 = lldp_tlv_packet_exit_container(tlv); - - return r < 0 ? r : r2; -} - -int sd_lldp_packet_read_port_id(tlv_packet *tlv, - uint8_t *type, - uint8_t **data, - uint16_t *length) { - uint8_t subtype; - char *s; - int r, r2; - - assert_return(tlv, -EINVAL); - - r = lldp_tlv_packet_enter_container(tlv, LLDP_TYPE_PORT_ID); - if (r < 0) - return r; - - r = tlv_packet_read_u8(tlv, &subtype); - if (r < 0) - goto out; - - switch (subtype) { - case LLDP_PORT_SUBTYPE_PORT_COMPONENT: - case LLDP_PORT_SUBTYPE_INTERFACE_ALIAS: - case LLDP_PORT_SUBTYPE_INTERFACE_NAME: - case LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED: - - r = tlv_packet_read_string(tlv, &s, length); - if (r < 0) - goto out; - - *data = (uint8_t *) s; - - break; - case LLDP_PORT_SUBTYPE_MAC_ADDRESS: - - r = tlv_packet_read_bytes(tlv, data, length); - if (r < 0) - goto out; - - break; - default: - r = -EOPNOTSUPP; - break; - } - - *type = subtype; - - out: - r2 = lldp_tlv_packet_exit_container(tlv); - - return r < 0 ? r : r2; -} - -int sd_lldp_packet_read_ttl(tlv_packet *tlv, uint16_t *ttl) { - return lldp_tlv_packet_read_u16_tlv(tlv, LLDP_TYPE_TTL, ttl); -} - -int sd_lldp_packet_read_system_name(tlv_packet *tlv, - char **data, - uint16_t *length) { - return lldp_tlv_packet_read_string_tlv(tlv, LLDP_TYPE_SYSTEM_NAME, data, length); -} - -int sd_lldp_packet_read_system_description(tlv_packet *tlv, - char **data, - uint16_t *length) { - return lldp_tlv_packet_read_string_tlv(tlv, LLDP_TYPE_SYSTEM_DESCRIPTION, data, length); -} - -int sd_lldp_packet_read_port_description(tlv_packet *tlv, - char **data, - uint16_t *length) { - return lldp_tlv_packet_read_string_tlv(tlv, LLDP_TYPE_PORT_DESCRIPTION, data, length); -} - -int sd_lldp_packet_read_system_capability(tlv_packet *tlv, uint16_t *data) { - return lldp_tlv_packet_read_u16_tlv(tlv, LLDP_TYPE_SYSTEM_CAPABILITIES, data); -} - -int sd_lldp_packet_read_port_vlan_id(tlv_packet *tlv, uint16_t *id) { - int r, r2; - - assert_return(tlv, -EINVAL); - - r = lldp_tlv_packet_enter_container_oui(tlv, LLDP_OUI_802_1, LLDP_OUI_SUBTYPE_802_1_PORT_VLAN_ID); - if (r < 0) - return r; - - r = tlv_packet_read_u16(tlv, id); - r2 = lldp_tlv_packet_exit_container(tlv); - - return r < 0 ? r : r2; -} - -int sd_lldp_packet_read_port_protocol_vlan_id(sd_lldp_packet *tlv, uint8_t *flags, uint16_t *id) { - int r, r2; - - assert_return(tlv, -EINVAL); - - r = lldp_tlv_packet_enter_container_oui(tlv, LLDP_OUI_802_1, LLDP_OUI_SUBTYPE_802_1_PORT_PROTOCOL_VLAN_ID); - if (r < 0) - return r; - - r = tlv_packet_read_u8(tlv, flags); - if (r >= 0) - r = tlv_packet_read_u16(tlv, id); - - r2 = lldp_tlv_packet_exit_container(tlv); - - return r < 0 ? r : r2; -} - -int sd_lldp_packet_read_vlan_name(tlv_packet *tlv, uint16_t *vlan_id, char **name, uint16_t *length) { - int r, r2; - uint8_t len = 0; - - assert_return(tlv, -EINVAL); - - r = lldp_tlv_packet_enter_container_oui(tlv, LLDP_OUI_802_1, LLDP_OUI_SUBTYPE_802_1_VLAN_NAME); - if (r < 0) - return r; - - r = tlv_packet_read_u16(tlv, vlan_id); - if (r >= 0) - r = tlv_packet_read_u8(tlv, &len); - if (r >= 0) - r = tlv_packet_read_string(tlv, name, length); - - if (r >= 0 && len < *length) - *length = len; - - r2 = lldp_tlv_packet_exit_container(tlv); - - return r < 0 ? r : r2; -} - -int sd_lldp_packet_read_management_vid(tlv_packet *tlv, uint16_t *id) { - int r, r2; - - assert_return(tlv, -EINVAL); - - r = lldp_tlv_packet_enter_container_oui(tlv, LLDP_OUI_802_1, LLDP_OUI_SUBTYPE_802_1_MANAGEMENT_VID); - if (r < 0) - return r; - - r = tlv_packet_read_u16(tlv, id); - r2 = lldp_tlv_packet_exit_container(tlv); - - return r < 0 ? r : r2; -} - -int sd_lldp_packet_read_link_aggregation(sd_lldp_packet *tlv, uint8_t *status, uint32_t *id) { - int r, r2; - - assert_return(tlv, -EINVAL); - - r = lldp_tlv_packet_enter_container_oui(tlv, LLDP_OUI_802_1, LLDP_OUI_SUBTYPE_802_1_LINK_AGGREGATION); - if (r < 0) - return r; - - r = tlv_packet_read_u8(tlv, status); - if (r >= 0) - r = tlv_packet_read_u32(tlv, id); - - r2 = lldp_tlv_packet_exit_container(tlv); - - return r < 0 ? r : r2; -} - -int sd_lldp_packet_get_destination_type(tlv_packet *tlv, int *dest) { - assert_return(tlv, -EINVAL); - assert_return(dest, -EINVAL); - - /* 802.1AB-2009, Table 7-1 */ - if (!memcmp(&tlv->mac, LLDP_MAC_NEAREST_BRIDGE, ETH_ALEN)) - *dest = SD_LLDP_DESTINATION_TYPE_NEAREST_BRIDGE; - else if (!memcmp(&tlv->mac, LLDP_MAC_NEAREST_NON_TPMR_BRIDGE, ETH_ALEN)) - *dest = SD_LLDP_DESTINATION_TYPE_NEAREST_NON_TPMR_BRIDGE; - else if (!memcmp(&tlv->mac, LLDP_MAC_NEAREST_CUSTOMER_BRIDGE, ETH_ALEN)) - *dest = SD_LLDP_DESTINATION_TYPE_NEAREST_CUSTOMER_BRIDGE; - else - return -EINVAL; - - return 0; -} diff --git a/src/systemd/src/libsystemd-network/lldp-tlv.h b/src/systemd/src/libsystemd-network/lldp-tlv.h deleted file mode 100644 index 8e7706c6..00000000 --- a/src/systemd/src/libsystemd-network/lldp-tlv.h +++ /dev/null @@ -1,94 +0,0 @@ -/*** - This file is part of systemd. - - Copyright (C) 2014 Tom Gundersen - Copyright (C) 2014 Susant Sahani - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#pragma once - -#include <net/ethernet.h> - -#include "sd-lldp.h" - -#include "list.h" -#include "lldp.h" -#include "util.h" - -typedef struct sd_lldp_packet tlv_packet; -typedef struct sd_lldp_section tlv_section; - -#define LLDP_OUI_LEN 3 - -struct sd_lldp_section { - uint16_t type; - uint16_t length; - uint8_t *oui; - uint8_t subtype; - - uint8_t *read_pos; - uint8_t *data; - - LIST_FIELDS(tlv_section, section); -}; - -#define LLDP_MAC_NEAREST_BRIDGE (uint8_t[]) { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e } -#define LLDP_MAC_NEAREST_NON_TPMR_BRIDGE (uint8_t[]) { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 } -#define LLDP_MAC_NEAREST_CUSTOMER_BRIDGE (uint8_t[]) { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 } - -int tlv_section_new(tlv_section **ret); -void tlv_section_free(tlv_section *ret); - -struct sd_lldp_packet { - unsigned n_ref; - - uint16_t type; - uint16_t length; - usec_t ts; - - uint8_t *container_pos; - uint8_t pdu[ETHER_MAX_LEN]; - - void *userdata; - - struct ether_addr mac; - tlv_section *container; - - LIST_HEAD(tlv_section, sections); -}; - -int tlv_packet_new(tlv_packet **ret); - -int lldp_tlv_packet_open_container(tlv_packet *m, uint16_t type); -int lldp_tlv_packet_close_container(tlv_packet *m); - -int tlv_packet_append_bytes(tlv_packet *m, const void *data, size_t data_length); -int tlv_packet_append_u8(tlv_packet *m, uint8_t data); -int tlv_packet_append_u16(tlv_packet *m, uint16_t data); -int tlv_packet_append_u32(tlv_packet *m, uint32_t data); -int tlv_packet_append_string(tlv_packet *m, char *data, uint16_t size); - -int lldp_tlv_packet_enter_container(tlv_packet *m, uint16_t type); -int lldp_tlv_packet_enter_container_oui(tlv_packet *m, const uint8_t *oui, uint8_t subtype); -int lldp_tlv_packet_exit_container(tlv_packet *m); - -int tlv_packet_read_bytes(tlv_packet *m, uint8_t **data, uint16_t *data_length); -int tlv_packet_read_string(tlv_packet *m, char **data, uint16_t *data_length); -int tlv_packet_read_u8(tlv_packet *m, uint8_t *data); -int tlv_packet_read_u16(tlv_packet *m, uint16_t *data); -int tlv_packet_read_u32(tlv_packet *m, uint32_t *data); - -int tlv_packet_parse_pdu(tlv_packet *t, uint16_t size); diff --git a/src/systemd/src/libsystemd-network/lldp.h b/src/systemd/src/libsystemd-network/lldp.h index d2c71646..d61ecabc 100644 --- a/src/systemd/src/libsystemd-network/lldp.h +++ b/src/systemd/src/libsystemd-network/lldp.h @@ -1,3 +1,5 @@ +#pragma once + /*** This file is part of systemd. @@ -18,14 +20,10 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#pragma once - #define LLDP_MULTICAST_ADDR { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e } -#define ETHERTYPE_LLDP 0x88cc - /* IEEE 802.3AB Clause 9: TLV Types */ -typedef enum LLDPTypes { +enum { LLDP_TYPE_END = 0, LLDP_TYPE_CHASSIS_ID = 1, LLDP_TYPE_PORT_ID = 2, @@ -36,12 +34,10 @@ typedef enum LLDPTypes { LLDP_TYPE_SYSTEM_CAPABILITIES = 7, LLDP_TYPE_MGMT_ADDRESS = 8, LLDP_TYPE_PRIVATE = 127, - _LLDP_TYPE_MAX, - _LLDP_TYPE_INVALID = -1, -} LLDPTypes; +}; /* IEEE 802.3AB Clause 9.5.2: Chassis subtypes */ -typedef enum LLDPChassisSubtypes { +enum { LLDP_CHASSIS_SUBTYPE_RESERVED = 0, LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT = 1, LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS = 2, @@ -50,25 +46,21 @@ typedef enum LLDPChassisSubtypes { LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS = 5, LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME = 6, LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED = 7, - _LLDP_CHASSIS_SUBTYPE_MAX, - _LLDP_CHASSIS_SUBTYPE_INVALID = -1, -} LLDPChassisSubtypes; +}; /* IEEE 802.3AB Clause 9.5.3: Port subtype */ -typedef enum LLDPPortSubtypes { +enum { LLDP_PORT_SUBTYPE_RESERVED = 0, LLDP_PORT_SUBTYPE_INTERFACE_ALIAS = 1, LLDP_PORT_SUBTYPE_PORT_COMPONENT = 2, LLDP_PORT_SUBTYPE_MAC_ADDRESS = 3, - LLDP_PORT_SUBTYPE_NETWORK = 4, + LLDP_PORT_SUBTYPE_NETWORK_ADDRESS = 4, LLDP_PORT_SUBTYPE_INTERFACE_NAME = 5, LLDP_PORT_SUBTYPE_AGENT_CIRCUIT_ID = 6, LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED = 7, - _LLDP_PORT_SUBTYPE_MAX, - _LLDP_PORT_SUBTYPE_INVALID = -1 -} LLDPPortSubtypes; +}; -typedef enum LLDPSystemCapabilities { +enum { LLDP_SYSTEM_CAPABILITIES_OTHER = 1 << 0, LLDP_SYSTEM_CAPABILITIES_REPEATER = 1 << 1, LLDP_SYSTEM_CAPABILITIES_BRIDGE = 1 << 2, @@ -80,47 +72,31 @@ typedef enum LLDPSystemCapabilities { LLDP_SYSTEM_CAPABILITIES_CVLAN = 1 << 8, LLDP_SYSTEM_CAPABILITIES_SVLAN = 1 << 9, LLDP_SYSTEM_CAPABILITIES_TPMR = 1 << 10, - _LLDP_SYSTEM_CAPABILITIES_MAX, - _LLDP_SYSTEM_CAPABILITIES_INVALID = -1, -} LLDPSystemCapabilities; +}; + +#define _LLDP_SYSTEM_CAPABILITIES_ALL ((uint16_t) -1) -typedef enum LLDPMedSubtype { - LLDP_MED_SUBTYPE_RESERVED = 0, - LLDP_MED_SUBTYPE_CAPABILITIES = 1, - LLDP_MED_SUBTYPE_NETWORK_POLICY = 2, - LLDP_MED_SUBTYPE_LOCATION_ID = 3, - LLDP_MED_SUBTYPE_EXTENDED_PVMDI = 4, - LLDP_MED_SUBTYPE_INV_HWREV = 5, - LLDP_MED_SUBTYPE_INV_FWREV = 6, - LLDP_MED_SUBTYPE_INV_SWREV = 7, - LLDP_MED_SUBTYPE_INV_SERIAL = 8, - LLDP_MED_SUBTYPE_INV_MANUFACTURER = 9, - LLDP_MED_SUBTYPE_INV_MODELNAME = 10, - LLDP_MED_SUBTYPE_INV_ASSETID = 11, - _LLDP_MED_SUBTYPE_MAX, - _LLDP_MED_SUBTYPE_INVALID = -1, -} LLDPMedSubtype; +#define _LLDP_SYSTEM_CAPABILITIES_ALL_ROUTERS \ + ((uint16_t) \ + (LLDP_SYSTEM_CAPABILITIES_REPEATER| \ + LLDP_SYSTEM_CAPABILITIES_BRIDGE| \ + LLDP_SYSTEM_CAPABILITIES_WLAN_AP| \ + LLDP_SYSTEM_CAPABILITIES_ROUTER| \ + LLDP_SYSTEM_CAPABILITIES_DOCSIS| \ + LLDP_SYSTEM_CAPABILITIES_CVLAN| \ + LLDP_SYSTEM_CAPABILITIES_SVLAN| \ + LLDP_SYSTEM_CAPABILITIES_TPMR)) -typedef enum LLDPMedCapability { - LLDP_MED_CAPABILITY_CAPAPILITIES = 1 << 0, - LLDP_MED_CAPABILITY_NETWORK_POLICY = 1 << 1, - LLDP_MED_CAPABILITY_LOCATION_ID = 1 << 2, - LLDP_MED_CAPABILITY_EXTENDED_PSE = 1 << 3, - LLDP_MED_CAPABILITY_EXTENDED_PD = 1 << 4, - LLDP_MED_CAPABILITY_INVENTORY = 1 << 5, - LLDP_MED_CAPABILITY_MAX, - LLDP_MED_CAPABILITY_INVALID = -1, -} LLDPMedCapability; #define LLDP_OUI_802_1 (uint8_t[]) { 0x00, 0x80, 0xc2 } #define LLDP_OUI_802_3 (uint8_t[]) { 0x00, 0x12, 0x0f } enum { - LLDP_OUI_SUBTYPE_802_1_PORT_VLAN_ID = 1, - LLDP_OUI_SUBTYPE_802_1_PORT_PROTOCOL_VLAN_ID = 2, - LLDP_OUI_SUBTYPE_802_1_VLAN_NAME = 3, - LLDP_OUI_SUBTYPE_802_1_PROTOCOL_IDENTITY = 4, - LLDP_OUI_SUBTYPE_802_1_VID_USAGE_DIGEST = 5, - LLDP_OUI_SUBTYPE_802_1_MANAGEMENT_VID = 6, - LLDP_OUI_SUBTYPE_802_1_LINK_AGGREGATION = 7, + LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID = 1, + LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID = 2, + LLDP_OUI_802_1_SUBTYPE_VLAN_NAME = 3, + LLDP_OUI_802_1_SUBTYPE_PROTOCOL_IDENTITY = 4, + LLDP_OUI_802_1_SUBTYPE_VID_USAGE_DIGEST = 5, + LLDP_OUI_802_1_SUBTYPE_MANAGEMENT_VID = 6, + LLDP_OUI_802_1_SUBTYPE_LINK_AGGREGATION = 7, }; diff --git a/src/systemd/src/libsystemd-network/network-internal.c b/src/systemd/src/libsystemd-network/network-internal.c index 383660f8..4e61c4fa 100644 --- a/src/systemd/src/libsystemd-network/network-internal.c +++ b/src/systemd/src/libsystemd-network/network-internal.c @@ -381,7 +381,7 @@ int deserialize_in_addrs(struct in_addr **ret, const char *string) { if (r <= 0) continue; - size ++; + size++; } *ret = addresses; @@ -488,7 +488,7 @@ int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t return -ENOMEM; entry = strndup(word, len); - if(!entry) + if (!entry) return -ENOMEM; tok = entry; diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/systemd/src/libsystemd-network/sd-dhcp-client.c index d00e1d34..40f3c8e9 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp-client.c @@ -103,7 +103,7 @@ struct sd_dhcp_client { sd_event_source *timeout_t1; sd_event_source *timeout_t2; sd_event_source *timeout_expire; - sd_dhcp_client_cb_t cb; + sd_dhcp_client_callback_t cb; void *userdata; sd_dhcp_lease *lease; usec_t start_delay; @@ -123,7 +123,7 @@ static int client_receive_message_udp(sd_event_source *s, int fd, uint32_t revents, void *userdata); static void client_stop(sd_dhcp_client *client, int error); -int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_cb_t cb, +int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_callback_t cb, void *userdata) { assert_return(client, -EINVAL); @@ -960,7 +960,7 @@ static int client_initialize_time_events(sd_dhcp_client *client) { client->timeout_resend = sd_event_source_unref(client->timeout_resend); if (client->start_delay) { - sd_event_now(client->event, clock_boottime_or_monotonic(), &usec); + assert_se(sd_event_now(client->event, clock_boottime_or_monotonic(), &usec) >= 0); usec += client->start_delay; } @@ -1527,20 +1527,17 @@ static int client_receive_message_udp(sd_event_source *s, int fd, uint32_t revents, void *userdata) { sd_dhcp_client *client = userdata; _cleanup_free_ DHCPMessage *message = NULL; - int buflen = 0, len, r; const struct ether_addr zero_mac = { { 0, 0, 0, 0, 0, 0 } }; const struct ether_addr *expected_chaddr = NULL; uint8_t expected_hlen = 0; + ssize_t len, buflen; assert(s); assert(client); - r = ioctl(fd, FIONREAD, &buflen); - if (r < 0) - return -errno; - else if (buflen < 0) - /* this can't be right */ - return -EIO; + buflen = next_datagram_size_fd(fd); + if (buflen < 0) + return buflen; message = malloc0(buflen); if (!message) @@ -1618,17 +1615,15 @@ static int client_receive_message_raw(sd_event_source *s, int fd, }; struct cmsghdr *cmsg; bool checksum = true; - int buflen = 0, len, r; + ssize_t buflen, len; + int r; assert(s); assert(client); - r = ioctl(fd, FIONREAD, &buflen); - if (r < 0) - return -errno; - else if (buflen < 0) - /* this can't be right */ - return -EIO; + buflen = next_datagram_size_fd(fd); + if (buflen < 0) + return buflen; packet = malloc0(buflen); if (!packet) @@ -1698,8 +1693,7 @@ int sd_dhcp_client_stop(sd_dhcp_client *client) { return 0; } -int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event, - int priority) { +int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event, int64_t priority) { int r; assert_return(client, -EINVAL); diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c index 9665d327..ebec1f12 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c @@ -35,6 +35,7 @@ #include "in-addr-util.h" #include "network-internal.h" #include "random-util.h" +#include "socket-util.h" #include "string-table.h" #include "util.h" @@ -65,7 +66,7 @@ struct sd_dhcp6_client { uint8_t retransmit_count; sd_event_source *timeout_resend; sd_event_source *timeout_resend_expire; - sd_dhcp6_client_cb_t cb; + sd_dhcp6_client_callback_t cb; void *userdata; struct duid duid; size_t duid_len; @@ -112,7 +113,7 @@ DEFINE_STRING_TABLE_LOOKUP(dhcp6_message_status, int); static int client_start(sd_dhcp6_client *client, enum DHCP6State state); -int sd_dhcp6_client_set_callback(sd_dhcp6_client *client, sd_dhcp6_client_cb_t cb, void *userdata) { +int sd_dhcp6_client_set_callback(sd_dhcp6_client *client, sd_dhcp6_client_callback_t cb, void *userdata) { assert_return(client, -EINVAL); client->cb = cb; @@ -893,18 +894,16 @@ static int client_receive_message(sd_event_source *s, int fd, uint32_t revents, sd_dhcp6_client *client = userdata; DHCP6_CLIENT_DONT_DESTROY(client); _cleanup_free_ DHCP6Message *message = NULL; - int r, buflen, len; + ssize_t buflen, len; + int r = 0; assert(s); assert(client); assert(client->event); - r = ioctl(fd, FIONREAD, &buflen); - if (r < 0) - return -errno; - else if (buflen < 0) - /* This really should not happen */ - return -EIO; + buflen = next_datagram_size_fd(fd); + if (buflen < 0) + return buflen; message = malloc(buflen); if (!message) @@ -1207,7 +1206,7 @@ error: return r; } -int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event, int priority) { +int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event, int64_t priority) { int r; assert_return(client, -EINVAL); diff --git a/src/systemd/src/libsystemd-network/sd-ipv4acd.c b/src/systemd/src/libsystemd-network/sd-ipv4acd.c index 99e663c1..9b5ce720 100644 --- a/src/systemd/src/libsystemd-network/sd-ipv4acd.c +++ b/src/systemd/src/libsystemd-network/sd-ipv4acd.c @@ -94,7 +94,7 @@ struct sd_ipv4acd { struct ether_addr mac_addr; sd_event *event; int event_priority; - sd_ipv4acd_cb_t cb; + sd_ipv4acd_callback_t cb; void* userdata; }; @@ -430,7 +430,7 @@ int sd_ipv4acd_detach_event(sd_ipv4acd *ll) { return 0; } -int sd_ipv4acd_attach_event(sd_ipv4acd *ll, sd_event *event, int priority) { +int sd_ipv4acd_attach_event(sd_ipv4acd *ll, sd_event *event, int64_t priority) { int r; assert_return(ll, -EINVAL); @@ -449,7 +449,7 @@ int sd_ipv4acd_attach_event(sd_ipv4acd *ll, sd_event *event, int priority) { return 0; } -int sd_ipv4acd_set_callback(sd_ipv4acd *ll, sd_ipv4acd_cb_t cb, void *userdata) { +int sd_ipv4acd_set_callback(sd_ipv4acd *ll, sd_ipv4acd_callback_t cb, void *userdata) { assert_return(ll, -EINVAL); ll->cb = cb; @@ -458,7 +458,7 @@ int sd_ipv4acd_set_callback(sd_ipv4acd *ll, sd_ipv4acd_cb_t cb, void *userdata) return 0; } -int sd_ipv4acd_set_address(sd_ipv4acd *ll, const struct in_addr *address){ +int sd_ipv4acd_set_address(sd_ipv4acd *ll, const struct in_addr *address) { assert_return(ll, -EINVAL); assert_return(address, -EINVAL); assert_return(ll->state == IPV4ACD_STATE_INIT, -EBUSY); diff --git a/src/systemd/src/libsystemd-network/sd-ipv4ll.c b/src/systemd/src/libsystemd-network/sd-ipv4ll.c index 119d00fc..391be15a 100644 --- a/src/systemd/src/libsystemd-network/sd-ipv4ll.c +++ b/src/systemd/src/libsystemd-network/sd-ipv4ll.c @@ -54,7 +54,7 @@ struct sd_ipv4ll { /* External */ be32_t claimed_address; - sd_ipv4ll_cb_t cb; + sd_ipv4ll_callback_t cb; void* userdata; }; @@ -162,7 +162,7 @@ int sd_ipv4ll_detach_event(sd_ipv4ll *ll) { return sd_ipv4acd_detach_event(ll->acd); } -int sd_ipv4ll_attach_event(sd_ipv4ll *ll, sd_event *event, int priority) { +int sd_ipv4ll_attach_event(sd_ipv4ll *ll, sd_event *event, int64_t priority) { int r; assert_return(ll, -EINVAL); @@ -174,7 +174,7 @@ int sd_ipv4ll_attach_event(sd_ipv4ll *ll, sd_event *event, int priority) { return 0; } -int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_cb_t cb, void *userdata) { +int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_callback_t cb, void *userdata) { assert_return(ll, -EINVAL); ll->cb = cb; @@ -183,7 +183,7 @@ int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_cb_t cb, void *userdata) { return 0; } -int sd_ipv4ll_get_address(sd_ipv4ll *ll, struct in_addr *address){ +int sd_ipv4ll_get_address(sd_ipv4ll *ll, struct in_addr *address) { assert_return(ll, -EINVAL); assert_return(address, -EINVAL); diff --git a/src/systemd/src/libsystemd-network/sd-lldp.c b/src/systemd/src/libsystemd-network/sd-lldp.c index 852d5358..71d15812 100644 --- a/src/systemd/src/libsystemd-network/sd-lldp.c +++ b/src/systemd/src/libsystemd-network/sd-lldp.c @@ -1,21 +1,21 @@ /*** - This file is part of systemd. + This file is part of systemd. - Copyright (C) 2014 Tom Gundersen - Copyright (C) 2014 Susant Sahani + Copyright (C) 2014 Tom Gundersen + Copyright (C) 2014 Susant Sahani - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ #include "nm-sd-adapt.h" @@ -26,733 +26,473 @@ #include "alloc-util.h" #include "fd-util.h" -#include "fileio.h" -#include "hashmap.h" #include "lldp-internal.h" -#include "lldp-port.h" -#include "lldp-tlv.h" -#include "prioq.h" -#include "siphash24.h" -#include "string-util.h" - -typedef enum LLDPAgentRXState { - LLDP_AGENT_RX_WAIT_PORT_OPERATIONAL = 4, - LLDP_AGENT_RX_DELETE_AGED_INFO, - LLDP_AGENT_RX_LLDP_INITIALIZE, - LLDP_AGENT_RX_WAIT_FOR_FRAME, - LLDP_AGENT_RX_RX_FRAME, - LLDP_AGENT_RX_DELETE_INFO, - LLDP_AGENT_RX_UPDATE_INFO, - _LLDP_AGENT_RX_STATE_MAX, - _LLDP_AGENT_RX_INVALID = -1, -} LLDPAgentRXState; - -/* Section 10.5.2.2 Reception counters */ -struct lldp_agent_statistics { - uint64_t stats_ageouts_total; - uint64_t stats_frames_discarded_total; - uint64_t stats_frames_in_errors_total; - uint64_t stats_frames_in_total; - uint64_t stats_tlvs_discarded_total; - uint64_t stats_tlvs_unrecognized_total; -}; - -struct sd_lldp { - lldp_port *port; - - Prioq *by_expiry; - Hashmap *neighbour_mib; - - sd_lldp_cb_t cb; - - void *userdata; - - LLDPAgentRXState rx_state; - lldp_agent_statistics statistics; -}; - -static void chassis_id_hash_func(const void *p, struct siphash *state) { - const lldp_chassis_id *id = p; - - assert(id); - assert(id->data); - - siphash24_compress(&id->length, sizeof(id->length), state); - siphash24_compress(id->data, id->length, state); -} +#include "lldp-neighbor.h" +#include "lldp-network.h" +#include "socket-util.h" +#include "ether-addr-util.h" -static int chassis_id_compare_func(const void *_a, const void *_b) { - const lldp_chassis_id *a, *b; +#define LLDP_DEFAULT_NEIGHBORS_MAX 128U - a = _a; - b = _b; +static void lldp_flush_neighbors(sd_lldp *lldp) { + sd_lldp_neighbor *n; - assert(!a->length || a->data); - assert(!b->length || b->data); + assert(lldp); - if (a->type != b->type) - return -1; + while ((n = hashmap_first(lldp->neighbor_by_id))) + lldp_neighbor_unlink(n); +} - if (a->length != b->length) - return a->length < b->length ? -1 : 1; +static void lldp_callback(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n) { + assert(lldp); + assert(n); - return memcmp(a->data, b->data, a->length); -} + log_lldp("Invoking callback for '%c'.", event); -static const struct hash_ops chassis_id_hash_ops = { - .hash = chassis_id_hash_func, - .compare = chassis_id_compare_func -}; + if (!lldp->callback) + return; -static void lldp_mib_delete_objects(sd_lldp *lldp); -static void lldp_set_state(sd_lldp *lldp, LLDPAgentRXState state); -static void lldp_run_state_machine(sd_lldp *ll); + lldp->callback(lldp, event, n, lldp->userdata); +} -static int lldp_receive_frame(sd_lldp *lldp, tlv_packet *tlv) { - int r; +static int lldp_make_space(sd_lldp *lldp, size_t extra) { + usec_t t = USEC_INFINITY; + bool changed = false; assert(lldp); - assert(tlv); - - /* Remove expired packets */ - if (prioq_size(lldp->by_expiry) > 0) { - lldp_set_state(lldp, LLDP_AGENT_RX_DELETE_INFO); + /* Remove all entries that are past their TTL, and more until at least the specified number of extra entries + * are free. */ - lldp_mib_delete_objects(lldp); - } + for (;;) { + _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL; - r = lldp_mib_add_objects(lldp->by_expiry, lldp->neighbour_mib, tlv); - if (r < 0) - goto out; + n = prioq_peek(lldp->neighbor_by_expiry); + if (!n) + break; - lldp_set_state(lldp, LLDP_AGENT_RX_UPDATE_INFO); + sd_lldp_neighbor_ref(n); - log_lldp("Packet added. MIB size: %d , PQ size: %d", - hashmap_size(lldp->neighbour_mib), - prioq_size(lldp->by_expiry)); + if (hashmap_size(lldp->neighbor_by_id) > LESS_BY(lldp->neighbors_max, extra)) + goto remove_one; - lldp->statistics.stats_frames_in_total ++; + if (t == USEC_INFINITY) + t = now(clock_boottime_or_monotonic()); - out: - if (r < 0) - log_lldp("Receive frame failed: %s", strerror(-r)); + if (n->until > t) + break; - lldp_set_state(lldp, LLDP_AGENT_RX_WAIT_FOR_FRAME); + remove_one: + lldp_neighbor_unlink(n); + lldp_callback(lldp, SD_LLDP_EVENT_REMOVED, n); + changed = true; + } - return 0; + return changed; } -/* 10.3.2 LLDPDU validation: rxProcessFrame() */ -int lldp_handle_packet(tlv_packet *tlv, uint16_t length) { - bool system_description = false, system_name = false, chassis_id = false; - bool malformed = false, port_id = false, ttl = false, end = false; - uint16_t type, len, i, l, t; - lldp_port *port; - uint8_t *p, *q; - sd_lldp *lldp; - int r; - - assert(tlv); - assert(length > 0); - - port = (lldp_port *) tlv->userdata; - lldp = (sd_lldp *) port->userdata; - - if (lldp->port->status == LLDP_PORT_STATUS_DISABLED) { - log_lldp("Port: %s is disabled. Dropping.", lldp->port->ifname); - goto out; - } +static bool lldp_keep_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) { + assert(lldp); + assert(n); - lldp_set_state(lldp, LLDP_AGENT_RX_RX_FRAME); + /* Don't keep data with a zero TTL */ + if (n->ttl <= 0) + return false; - p = tlv->pdu; - p += sizeof(struct ether_header); + /* Filter out data from the filter address */ + if (!ether_addr_is_null(&lldp->filter_address) && + ether_addr_equal(&lldp->filter_address, &n->source_address)) + return false; - for (i = 1, l = 0; l <= length; i++) { + /* Only add if the neighbor has a capability we are interested in. Note that we also store all neighbors with + * no caps field set. */ + if (n->has_capabilities && + (n->enabled_capabilities & lldp->capability_mask) == 0) + return false; - memcpy(&t, p, sizeof(uint16_t)); + /* Keep everything else */ + return true; +} - type = ntohs(t) >> 9; - len = ntohs(t) & 0x01ff; +static int lldp_start_timer(sd_lldp *lldp, sd_lldp_neighbor *neighbor); - if (type == LLDP_TYPE_END) { - if (len != 0) { - log_lldp("TLV type end must be length 0 (not %d). Dropping.", len); +static int lldp_add_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) { + _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *old = NULL; + bool keep; + int r; - malformed = true; - goto out; - } + assert(lldp); + assert(n); + assert(!n->lldp); - end = true; + keep = lldp_keep_neighbor(lldp, n); - break; - } else if (type >=_LLDP_TYPE_MAX) { - log_lldp("TLV type: %d not recognized. Dropping.", type); + /* First retrieve the old entry for this MSAP */ + old = hashmap_get(lldp->neighbor_by_id, &n->id); + if (old) { + sd_lldp_neighbor_ref(old); - malformed = true; - goto out; + if (!keep) { + lldp_neighbor_unlink(old); + lldp_callback(lldp, SD_LLDP_EVENT_REMOVED, old); + return 0; } - /* skip type and length encoding */ - p += 2; - q = p; - - p += len; - l += (len + 2); + if (lldp_neighbor_equal(n, old)) { + /* Is this equal, then restart the TTL counter, but don't do anyting else. */ + lldp_start_timer(lldp, old); + lldp_callback(lldp, SD_LLDP_EVENT_REFRESHED, old); + return 0; + } - if (i <= 3) { - if (i != type) { - log_lldp("TLV missing or out of order. Dropping."); + /* Data changed, remove the old entry, and add a new one */ + lldp_neighbor_unlink(old); - malformed = true; - goto out; - } - } + } else if (!keep) + return 0; - switch(type) { - case LLDP_TYPE_CHASSIS_ID: + /* Then, make room for at least one new neighbor */ + lldp_make_space(lldp, 1); - if (len < 2) { - log_lldp("Received malformed Chassis ID TLV length: %d. Dropping.", len); + r = hashmap_put(lldp->neighbor_by_id, &n->id, n); + if (r < 0) + goto finish; - malformed = true; - goto out; - } + r = prioq_put(lldp->neighbor_by_expiry, n, &n->prioq_idx); + if (r < 0) { + assert_se(hashmap_remove(lldp->neighbor_by_id, &n->id) == n); + goto finish; + } - if (chassis_id) { - log_lldp("Duplicate Chassis ID TLV found. Dropping."); + n->lldp = lldp; - malformed = true; - goto out; - } + lldp_start_timer(lldp, n); + lldp_callback(lldp, old ? SD_LLDP_EVENT_UPDATED : SD_LLDP_EVENT_ADDED, n); - /* Look what subtype it has */ - if (*q == LLDP_CHASSIS_SUBTYPE_RESERVED || *q > LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED) { - log_lldp("Unknown subtype: %d found in Chassis ID TLV. Dropping.", *q); + return 1; - malformed = true; - goto out; +finish: + if (old) + lldp_callback(lldp, SD_LLDP_EVENT_REMOVED, n); - } + return r; +} - chassis_id = true; +static int lldp_handle_datagram(sd_lldp *lldp, sd_lldp_neighbor *n) { + int r; - break; - case LLDP_TYPE_PORT_ID: + assert(lldp); + assert(n); - if (len < 2) { - log_lldp("Received malformed Port ID TLV length: %d. Dropping.", len); + r = lldp_neighbor_parse(n); + if (r == -EBADMSG) /* Ignore bad messages */ + return 0; + if (r < 0) + return r; - malformed = true; - goto out; - } + r = lldp_add_neighbor(lldp, n); + if (r < 0) { + log_lldp_errno(r, "Failed to add datagram. Ignoring."); + return 0; + } - if (port_id) { - log_lldp("Duplicate Port ID TLV found. Dropping."); + log_lldp("Successfully processed LLDP datagram."); + return 0; +} - malformed = true; - goto out; - } +static int lldp_receive_datagram(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL; + ssize_t space, length; + sd_lldp *lldp = userdata; - /* Look what subtype it has */ - if (*q == LLDP_PORT_SUBTYPE_RESERVED || *q > LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED) { - log_lldp("Unknown subtype: %d found in Port ID TLV. Dropping.", *q); + assert(fd >= 0); + assert(lldp); - malformed = true; - goto out; + space = next_datagram_size_fd(fd); + if (space < 0) + return log_lldp_errno(space, "Failed to determine datagram size to read: %m"); - } + n = lldp_neighbor_new(space); + if (!n) + return -ENOMEM; - port_id = true; + length = recv(fd, LLDP_NEIGHBOR_RAW(n), n->raw_size, MSG_DONTWAIT); + if (length < 0) + return log_lldp_errno(errno, "Failed to read LLDP datagram: %m"); - break; - case LLDP_TYPE_TTL: + if ((size_t) length != n->raw_size) { + log_lldp("Packet size mismatch."); + return -EINVAL; + } - if(len != 2) { - log_lldp("Received invalid TTL TLV lenth: %d. Dropping.", len); + return lldp_handle_datagram(lldp, n); +} - malformed = true; - goto out; - } +_public_ int sd_lldp_start(sd_lldp *lldp) { + int r; - if (ttl) { - log_lldp("Duplicate TTL TLV found. Dropping."); + assert_return(lldp, -EINVAL); - malformed = true; - goto out; - } + if (lldp->fd >= 0) + return 0; - ttl = true; + assert(!lldp->io_event_source); - break; - case LLDP_TYPE_SYSTEM_NAME: + lldp->fd = lldp_network_bind_raw_socket(lldp->ifindex); + if (lldp->fd < 0) + return lldp->fd; - /* According to RFC 1035 the length of a FQDN is limited to 255 characters */ - if (len > 255) { - log_lldp("Received invalid system name length: %d. Dropping.", len); - malformed = true; - goto out; - } + if (lldp->event) { + r = sd_event_add_io(lldp->event, &lldp->io_event_source, lldp->fd, EPOLLIN, lldp_receive_datagram, lldp); + if (r < 0) + goto fail; - if (system_name) { - log_lldp("Duplicate system name found. Dropping."); - malformed = true; - goto out; - } + r = sd_event_source_set_priority(lldp->io_event_source, lldp->event_priority); + if (r < 0) + goto fail; - system_name = true; + (void) sd_event_source_set_description(lldp->io_event_source, "lldp-io"); + } - break; - case LLDP_TYPE_SYSTEM_DESCRIPTION: - - /* 0 <= n <= 255 octets */ - if (len > 255) { - log_lldp("Received invalid system description length: %d. Dropping.", len); - malformed = true; - goto out; - } - - if (system_description) { - log_lldp("Duplicate system description found. Dropping."); - malformed = true; - goto out; - } - - system_description = true; - break; - default: + return 1; - if (len == 0) { - log_lldp("TLV type: %d length 0 received. Dropping.", type); +fail: + lldp->io_event_source = sd_event_source_unref(lldp->io_event_source); + lldp->fd = safe_close(lldp->fd); - malformed = true; - goto out; - } - break; - } - } + return r; +} - if(!chassis_id || !port_id || !ttl || !end) { - log_lldp("One or more mandatory TLV missing. Dropping."); +_public_ int sd_lldp_stop(sd_lldp *lldp) { + assert_return(lldp, -EINVAL); - malformed = true; - goto out; + if (lldp->fd < 0) + return 0; - } + lldp->timer_event_source = sd_event_source_unref(lldp->timer_event_source); + lldp->io_event_source = sd_event_source_unref(lldp->io_event_source); + lldp->fd = safe_close(lldp->fd); - r = tlv_packet_parse_pdu(tlv, length); - if (r < 0) { - log_lldp("Failed to parse the TLV. Dropping."); + lldp_flush_neighbors(lldp); - malformed = true; - goto out; - } + return 1; +} - return lldp_receive_frame(lldp, tlv); +_public_ int sd_lldp_attach_event(sd_lldp *lldp, sd_event *event, int64_t priority) { + int r; - out: - lldp_set_state(lldp, LLDP_AGENT_RX_WAIT_FOR_FRAME); + assert_return(lldp, -EINVAL); + assert_return(lldp->fd < 0, -EBUSY); + assert_return(!lldp->event, -EBUSY); - if (malformed) { - lldp->statistics.stats_frames_discarded_total ++; - lldp->statistics.stats_frames_in_errors_total ++; + if (event) + lldp->event = sd_event_ref(event); + else { + r = sd_event_default(&lldp->event); + if (r < 0) + return r; } - sd_lldp_packet_unref(tlv); + lldp->event_priority = priority; return 0; } -static int ttl_expiry_item_prioq_compare_func(const void *a, const void *b) { - const lldp_neighbour_port *p = a, *q = b; +_public_ int sd_lldp_detach_event(sd_lldp *lldp) { - if (p->until < q->until) - return -1; - - if (p->until > q->until) - return 1; + assert_return(lldp, -EINVAL); + assert_return(lldp->fd < 0, -EBUSY); + lldp->event = sd_event_unref(lldp->event); return 0; } -static void lldp_set_state(sd_lldp *lldp, LLDPAgentRXState state) { - - assert(lldp); - assert(state < _LLDP_AGENT_RX_STATE_MAX); +_public_ int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_callback_t cb, void *userdata) { + assert_return(lldp, -EINVAL); - lldp->rx_state = state; + lldp->callback = cb; + lldp->userdata = userdata; - lldp_run_state_machine(lldp); + return 0; } -static void lldp_run_state_machine(sd_lldp *lldp) { - if (!lldp->cb) - return; - - switch (lldp->rx_state) { - case LLDP_AGENT_RX_UPDATE_INFO: - lldp->cb(lldp, SD_LLDP_EVENT_UPDATE_INFO, lldp->userdata); - break; - default: - break; - } -} +_public_ sd_lldp* sd_lldp_unref(sd_lldp *lldp) { -/* 10.5.5.2.1 mibDeleteObjects () - * The mibDeleteObjects () procedure deletes all information in the LLDP remote - * systems MIB associated with the MSAP identifier if an LLDPDU is received with - * an rxTTL value of zero (see 10.3.2) or the timing counter rxInfoTTL expires. */ + if (!lldp) + return NULL; -static void lldp_mib_delete_objects(sd_lldp *lldp) { - lldp_neighbour_port *p; - usec_t t = 0; + lldp_flush_neighbors(lldp); - /* Remove all entries that are past their TTL */ - for (;;) { + hashmap_free(lldp->neighbor_by_id); + prioq_free(lldp->neighbor_by_expiry); - if (prioq_size(lldp->by_expiry) <= 0) - break; + sd_event_source_unref(lldp->io_event_source); + sd_event_source_unref(lldp->timer_event_source); + sd_event_unref(lldp->event); + safe_close(lldp->fd); - p = prioq_peek(lldp->by_expiry); - if (!p) - break; + free(lldp); - if (t <= 0) - t = now(clock_boottime_or_monotonic()); + return NULL; +} - if (p->until > t) - break; +_public_ int sd_lldp_new(sd_lldp **ret, int ifindex) { + _cleanup_(sd_lldp_unrefp) sd_lldp *lldp = NULL; + int r; - lldp_neighbour_port_remove_and_free(p); + assert_return(ret, -EINVAL); + assert_return(ifindex > 0, -EINVAL); - lldp->statistics.stats_ageouts_total ++; - } -} + lldp = new0(sd_lldp, 1); + if (!lldp) + return -ENOMEM; -static void lldp_mib_objects_flush(sd_lldp *lldp) { - lldp_neighbour_port *p, *q; - lldp_chassis *c; + lldp->fd = -1; + lldp->ifindex = ifindex; + lldp->neighbors_max = LLDP_DEFAULT_NEIGHBORS_MAX; + lldp->capability_mask = (uint16_t) -1; - assert(lldp); - assert(lldp->neighbour_mib); - assert(lldp->by_expiry); + lldp->neighbor_by_id = hashmap_new(&lldp_neighbor_id_hash_ops); + if (!lldp->neighbor_by_id) + return -ENOMEM; - /* Drop all packets */ - while ((c = hashmap_steal_first(lldp->neighbour_mib))) { + r = prioq_ensure_allocated(&lldp->neighbor_by_expiry, lldp_neighbor_prioq_compare_func); + if (r < 0) + return r; - LIST_FOREACH_SAFE(port, p, q, c->ports) { - lldp_neighbour_port_remove_and_free(p); - } - } + *ret = lldp; + lldp = NULL; - assert(hashmap_size(lldp->neighbour_mib) == 0); - assert(prioq_size(lldp->by_expiry) == 0); + return 0; } -int sd_lldp_save(sd_lldp *lldp, const char *lldp_file) { - _cleanup_free_ char *temp_path = NULL; - _cleanup_fclose_ FILE *f = NULL; - uint8_t *mac, *port_id, type; - lldp_neighbour_port *p; - uint16_t data = 0, length = 0; - char buf[LINE_MAX]; - lldp_chassis *c; - usec_t time; - Iterator i; - int r; +static int neighbor_compare_func(const void *a, const void *b) { + const sd_lldp_neighbor * const*x = a, * const *y = b; - assert(lldp); - assert(lldp_file); + return lldp_neighbor_id_hash_ops.compare(&(*x)->id, &(*y)->id); +} - r = fopen_temporary(lldp_file, &f, &temp_path); - if (r < 0) - goto fail; - - fchmod(fileno(f), 0644); - - HASHMAP_FOREACH(c, lldp->neighbour_mib, i) { - LIST_FOREACH(port, p, c->ports) { - _cleanup_free_ char *s = NULL; - char *k, *t; - - r = sd_lldp_packet_read_chassis_id(p->packet, &type, &mac, &length); - if (r < 0) - continue; - - sprintf(buf, "'_Chassis=%02x:%02x:%02x:%02x:%02x:%02x' '_CType=%d' ", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], type); - - s = strdup(buf); - if (!s) { - r = -ENOMEM; - goto fail; - } - - r = sd_lldp_packet_read_port_id(p->packet, &type, &port_id, &length); - if (r < 0) - continue; - - if (type != LLDP_PORT_SUBTYPE_MAC_ADDRESS) { - k = strndup((char *) port_id, length -1); - if (!k) { - r = -ENOMEM; - goto fail; - } - - sprintf(buf, "'_Port=%s' '_PType=%d' ", k , type); - free(k); - } else { - mac = port_id; - sprintf(buf, "'_Port=%02x:%02x:%02x:%02x:%02x:%02x' '_PType=%d' ", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], type); - } - - k = strappend(s, buf); - if (!k) { - r = -ENOMEM; - goto fail; - } - - free(s); - s = k; - - time = now(clock_boottime_or_monotonic()); - - /* Don't write expired packets */ - if (time - p->until <= 0) - continue; - - sprintf(buf, "'_TTL="USEC_FMT"' ", p->until); - - k = strappend(s, buf); - if (!k) { - r = -ENOMEM; - goto fail; - } - - free(s); - s = k; - - r = sd_lldp_packet_read_system_name(p->packet, &k, &length); - if (r < 0) - k = strappend(s, "'_NAME=N/A' "); - else { - t = strndup(k, length); - if (!t) { - r = -ENOMEM; - goto fail; - } - - k = strjoin(s, "'_NAME=", t, "' ", NULL); - free(t); - } - - if (!k) { - r = -ENOMEM; - goto fail; - } - - free(s); - s = k; - - (void) sd_lldp_packet_read_system_capability(p->packet, &data); - - sprintf(buf, "'_CAP=%x'", data); - - k = strappend(s, buf); - if (!k) { - r = -ENOMEM; - goto fail; - } - - free(s); - s = k; - - fprintf(f, "%s\n", s); - } - } +static int on_timer_event(sd_event_source *s, uint64_t usec, void *userdata) { + sd_lldp *lldp = userdata; + int r, q; - r = fflush_and_check(f); + r = lldp_make_space(lldp, 0); if (r < 0) - goto fail; + return log_lldp_errno(r, "Failed to make space: %m"); - if (rename(temp_path, lldp_file) < 0) { - r = -errno; - goto fail; - } + q = lldp_start_timer(lldp, NULL); + if (q < 0) + return log_lldp_errno(q, "Failed to restart timer: %m"); return 0; - - fail: - if (temp_path) - (void) unlink(temp_path); - - return log_error_errno(r, "Failed to save lldp data %s: %m", lldp_file); } -int sd_lldp_start(sd_lldp *lldp) { +static int lldp_start_timer(sd_lldp *lldp, sd_lldp_neighbor *neighbor) { + sd_lldp_neighbor *n; int r; - assert_return(lldp, -EINVAL); - assert_return(lldp->port, -EINVAL); + assert(lldp); - lldp->port->status = LLDP_PORT_STATUS_ENABLED; + if (neighbor) + lldp_neighbor_start_ttl(neighbor); - lldp_set_state(lldp, LLDP_AGENT_RX_LLDP_INITIALIZE); + n = prioq_peek(lldp->neighbor_by_expiry); + if (!n) { - r = lldp_port_start(lldp->port); - if (r < 0) { - log_lldp("Failed to start Port : %s , %s", - lldp->port->ifname, - strerror(-r)); + if (lldp->timer_event_source) + return sd_event_source_set_enabled(lldp->timer_event_source, SD_EVENT_OFF); - lldp_set_state(lldp, LLDP_AGENT_RX_WAIT_PORT_OPERATIONAL); - - return r; + return 0; } - lldp_set_state(lldp, LLDP_AGENT_RX_WAIT_FOR_FRAME); - - return 0; -} - -int sd_lldp_stop(sd_lldp *lldp) { - int r; + if (lldp->timer_event_source) { + r = sd_event_source_set_time(lldp->timer_event_source, n->until); + if (r < 0) + return r; - assert_return(lldp, -EINVAL); - assert_return(lldp->port, -EINVAL); + return sd_event_source_set_enabled(lldp->timer_event_source, SD_EVENT_ONESHOT); + } - lldp->port->status = LLDP_PORT_STATUS_DISABLED; + if (!lldp->event) + return 0; - r = lldp_port_stop(lldp->port); + r = sd_event_add_time(lldp->event, &lldp->timer_event_source, clock_boottime_or_monotonic(), n->until, 0, on_timer_event, lldp); if (r < 0) return r; - lldp_mib_objects_flush(lldp); + r = sd_event_source_set_priority(lldp->timer_event_source, lldp->event_priority); + if (r < 0) + return r; + (void) sd_event_source_set_description(lldp->timer_event_source, "lldp-timer"); return 0; } -int sd_lldp_attach_event(sd_lldp *lldp, sd_event *event, int priority) { - int r; +_public_ int sd_lldp_get_neighbors(sd_lldp *lldp, sd_lldp_neighbor ***ret) { + sd_lldp_neighbor **l = NULL, *n; + Iterator i; + int k = 0, r; assert_return(lldp, -EINVAL); - assert_return(!lldp->port->event, -EBUSY); + assert_return(ret, -EINVAL); - if (event) - lldp->port->event = sd_event_ref(event); - else { - r = sd_event_default(&lldp->port->event); - if (r < 0) - return r; + if (hashmap_isempty(lldp->neighbor_by_id)) { /* Special shortcut */ + *ret = NULL; + return 0; } - lldp->port->event_priority = priority; + l = new0(sd_lldp_neighbor*, hashmap_size(lldp->neighbor_by_id)); + if (!l) + return -ENOMEM; - return 0; -} + r = lldp_start_timer(lldp, NULL); + if (r < 0) { + free(l); + return r; + } -int sd_lldp_detach_event(sd_lldp *lldp) { + HASHMAP_FOREACH(n, lldp->neighbor_by_id, i) + l[k++] = sd_lldp_neighbor_ref(n); - assert_return(lldp, -EINVAL); + assert((size_t) k == hashmap_size(lldp->neighbor_by_id)); - lldp->port->event = sd_event_unref(lldp->port->event); + /* Return things in a stable order */ + qsort(l, k, sizeof(sd_lldp_neighbor*), neighbor_compare_func); + *ret = l; - return 0; + return k; } -int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_cb_t cb, void *userdata) { +_public_ int sd_lldp_set_neighbors_max(sd_lldp *lldp, uint64_t m) { assert_return(lldp, -EINVAL); + assert_return(m <= 0, -EINVAL); - lldp->cb = cb; - lldp->userdata = userdata; + lldp->neighbors_max = m; + lldp_make_space(lldp, 0); return 0; } -sd_lldp* sd_lldp_unref(sd_lldp *lldp) { - - if (!lldp) - return NULL; - - /* Drop all packets */ - lldp_mib_objects_flush(lldp); - - lldp_port_free(lldp->port); - - hashmap_free(lldp->neighbour_mib); - prioq_free(lldp->by_expiry); - - free(lldp); - return NULL; -} - -int sd_lldp_new(int ifindex, - const char *ifname, - const struct ether_addr *mac, - sd_lldp **ret) { - _cleanup_(sd_lldp_unrefp) sd_lldp *lldp = NULL; - int r; - - assert_return(ret, -EINVAL); - assert_return(ifindex > 0, -EINVAL); - assert_return(ifname, -EINVAL); - assert_return(mac, -EINVAL); - - lldp = new0(sd_lldp, 1); - if (!lldp) - return -ENOMEM; - - r = lldp_port_new(ifindex, ifname, mac, lldp, &lldp->port); - if (r < 0) - return r; - - lldp->neighbour_mib = hashmap_new(&chassis_id_hash_ops); - if (!lldp->neighbour_mib) - return -ENOMEM; - - r = prioq_ensure_allocated(&lldp->by_expiry, - ttl_expiry_item_prioq_compare_func); - if (r < 0) - return r; - - lldp->rx_state = LLDP_AGENT_RX_WAIT_PORT_OPERATIONAL; +_public_ int sd_lldp_match_capabilities(sd_lldp *lldp, uint16_t mask) { + assert_return(lldp, -EINVAL); + assert_return(mask != 0, -EINVAL); - *ret = lldp; - lldp = NULL; + lldp->capability_mask = mask; return 0; } -int sd_lldp_get_packets(sd_lldp *lldp, sd_lldp_packet ***tlvs) { - lldp_neighbour_port *p; - lldp_chassis *c; - Iterator iter; - unsigned count = 0, i; - +_public_ int sd_lldp_set_filter_address(sd_lldp *lldp, const struct ether_addr *addr) { assert_return(lldp, -EINVAL); - assert_return(tlvs, -EINVAL); - HASHMAP_FOREACH(c, lldp->neighbour_mib, iter) { - LIST_FOREACH(port, p, c->ports) - count++; - } + /* In order to deal nicely with bridges that send back our own packets, allow one address to be filtered, so + * that our own can be filtered out here. */ - if (!count) { - *tlvs = NULL; + if (!addr) { + zero(lldp->filter_address); return 0; } - *tlvs = new(sd_lldp_packet *, count); - if (!*tlvs) - return -ENOMEM; - - i = 0; - HASHMAP_FOREACH(c, lldp->neighbour_mib, iter) { - LIST_FOREACH(port, p, c->ports) - (*tlvs)[i++] = sd_lldp_packet_ref(p->packet); - } - - return count; + lldp->filter_address = *addr; + return 0; } diff --git a/src/systemd/src/libsystemd/sd-event/sd-event.c b/src/systemd/src/libsystemd/sd-event/sd-event.c new file mode 100644 index 00000000..31e8e7fa --- /dev/null +++ b/src/systemd/src/libsystemd/sd-event/sd-event.c @@ -0,0 +1,2905 @@ +/*** + This file is part of systemd. + + Copyright 2013 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include "nm-sd-adapt.h" + +#include <sys/epoll.h> +#include <sys/timerfd.h> +#include <sys/wait.h> + +#if 0 /* NM_IGNORED */ +#include "sd-daemon.h" +#endif +#include "sd-event.h" +#include "sd-id128.h" + +#include "alloc-util.h" +#include "fd-util.h" +#include "hashmap.h" +#include "list.h" +#include "macro.h" +#if 0 /* NM_IGNORED */ +#include "missing.h" +#endif +#include "prioq.h" +#if 0 /* NM_IGNORED */ +#include "process-util.h" +#endif +#include "set.h" +#if 0 /* NM_IGNORED */ +#include "signal-util.h" +#endif +#include "string-table.h" +#include "string-util.h" +#include "time-util.h" +#include "util.h" + +#define DEFAULT_ACCURACY_USEC (250 * USEC_PER_MSEC) + +typedef enum EventSourceType { + SOURCE_IO, + SOURCE_TIME_REALTIME, + SOURCE_TIME_BOOTTIME, + SOURCE_TIME_MONOTONIC, + SOURCE_TIME_REALTIME_ALARM, + SOURCE_TIME_BOOTTIME_ALARM, + SOURCE_SIGNAL, + SOURCE_CHILD, + SOURCE_DEFER, + SOURCE_POST, + SOURCE_EXIT, + SOURCE_WATCHDOG, + _SOURCE_EVENT_SOURCE_TYPE_MAX, + _SOURCE_EVENT_SOURCE_TYPE_INVALID = -1 +} EventSourceType; + +static const char* const event_source_type_table[_SOURCE_EVENT_SOURCE_TYPE_MAX] = { + [SOURCE_IO] = "io", + [SOURCE_TIME_REALTIME] = "realtime", + [SOURCE_TIME_BOOTTIME] = "bootime", + [SOURCE_TIME_MONOTONIC] = "monotonic", + [SOURCE_TIME_REALTIME_ALARM] = "realtime-alarm", + [SOURCE_TIME_BOOTTIME_ALARM] = "boottime-alarm", + [SOURCE_SIGNAL] = "signal", + [SOURCE_CHILD] = "child", + [SOURCE_DEFER] = "defer", + [SOURCE_POST] = "post", + [SOURCE_EXIT] = "exit", + [SOURCE_WATCHDOG] = "watchdog", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(event_source_type, int); + +/* All objects we use in epoll events start with this value, so that + * we know how to dispatch it */ +typedef enum WakeupType { + WAKEUP_NONE, + WAKEUP_EVENT_SOURCE, + WAKEUP_CLOCK_DATA, + WAKEUP_SIGNAL_DATA, + _WAKEUP_TYPE_MAX, + _WAKEUP_TYPE_INVALID = -1, +} WakeupType; + +#define EVENT_SOURCE_IS_TIME(t) IN_SET((t), SOURCE_TIME_REALTIME, SOURCE_TIME_BOOTTIME, SOURCE_TIME_MONOTONIC, SOURCE_TIME_REALTIME_ALARM, SOURCE_TIME_BOOTTIME_ALARM) + +struct sd_event_source { + WakeupType wakeup; + + unsigned n_ref; + + sd_event *event; + void *userdata; + sd_event_handler_t prepare; + + char *description; + + EventSourceType type:5; + int enabled:3; + bool pending:1; + bool dispatching:1; + bool floating:1; + + int64_t priority; + unsigned pending_index; + unsigned prepare_index; + unsigned pending_iteration; + unsigned prepare_iteration; + + LIST_FIELDS(sd_event_source, sources); + + union { + struct { + sd_event_io_handler_t callback; + int fd; + uint32_t events; + uint32_t revents; + bool registered:1; + } io; + struct { + sd_event_time_handler_t callback; + usec_t next, accuracy; + unsigned earliest_index; + unsigned latest_index; + } time; + struct { + sd_event_signal_handler_t callback; + struct signalfd_siginfo siginfo; + int sig; + } signal; + struct { + sd_event_child_handler_t callback; + siginfo_t siginfo; + pid_t pid; + int options; + } child; + struct { + sd_event_handler_t callback; + } defer; + struct { + sd_event_handler_t callback; + } post; + struct { + sd_event_handler_t callback; + unsigned prioq_index; + } exit; + }; +}; + +struct clock_data { + WakeupType wakeup; + int fd; + + /* For all clocks we maintain two priority queues each, one + * ordered for the earliest times the events may be + * dispatched, and one ordered by the latest times they must + * have been dispatched. The range between the top entries in + * the two prioqs is the time window we can freely schedule + * wakeups in */ + + Prioq *earliest; + Prioq *latest; + usec_t next; + + bool needs_rearm:1; +}; + +struct signal_data { + WakeupType wakeup; + + /* For each priority we maintain one signal fd, so that we + * only have to dequeue a single event per priority at a + * time. */ + + int fd; + int64_t priority; + sigset_t sigset; + sd_event_source *current; +}; + +struct sd_event { + unsigned n_ref; + + int epoll_fd; + int watchdog_fd; + + Prioq *pending; + Prioq *prepare; + + /* timerfd_create() only supports these five clocks so far. We + * can add support for more clocks when the kernel learns to + * deal with them, too. */ + struct clock_data realtime; + struct clock_data boottime; + struct clock_data monotonic; + struct clock_data realtime_alarm; + struct clock_data boottime_alarm; + + usec_t perturb; + + sd_event_source **signal_sources; /* indexed by signal number */ + Hashmap *signal_data; /* indexed by priority */ + + Hashmap *child_sources; + unsigned n_enabled_child_sources; + + Set *post_sources; + + Prioq *exit; + + pid_t original_pid; + + unsigned iteration; + dual_timestamp timestamp; + usec_t timestamp_boottime; + int state; + + bool exit_requested:1; + bool need_process_child:1; + bool watchdog:1; + bool profile_delays:1; + + int exit_code; + + pid_t tid; + sd_event **default_event_ptr; + + usec_t watchdog_last, watchdog_period; + + unsigned n_sources; + + LIST_HEAD(sd_event_source, sources); + + usec_t last_run, last_log; + unsigned delays[sizeof(usec_t) * 8]; +}; + +static void source_disconnect(sd_event_source *s); + +static int pending_prioq_compare(const void *a, const void *b) { + const sd_event_source *x = a, *y = b; + + assert(x->pending); + assert(y->pending); + + /* Enabled ones first */ + if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) + return -1; + if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) + return 1; + + /* Lower priority values first */ + if (x->priority < y->priority) + return -1; + if (x->priority > y->priority) + return 1; + + /* Older entries first */ + if (x->pending_iteration < y->pending_iteration) + return -1; + if (x->pending_iteration > y->pending_iteration) + return 1; + + return 0; +} + +static int prepare_prioq_compare(const void *a, const void *b) { + const sd_event_source *x = a, *y = b; + + assert(x->prepare); + assert(y->prepare); + + /* Enabled ones first */ + if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) + return -1; + if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) + return 1; + + /* Move most recently prepared ones last, so that we can stop + * preparing as soon as we hit one that has already been + * prepared in the current iteration */ + if (x->prepare_iteration < y->prepare_iteration) + return -1; + if (x->prepare_iteration > y->prepare_iteration) + return 1; + + /* Lower priority values first */ + if (x->priority < y->priority) + return -1; + if (x->priority > y->priority) + return 1; + + return 0; +} + +static int earliest_time_prioq_compare(const void *a, const void *b) { + const sd_event_source *x = a, *y = b; + + assert(EVENT_SOURCE_IS_TIME(x->type)); + assert(x->type == y->type); + + /* Enabled ones first */ + if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) + return -1; + if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) + return 1; + + /* Move the pending ones to the end */ + if (!x->pending && y->pending) + return -1; + if (x->pending && !y->pending) + return 1; + + /* Order by time */ + if (x->time.next < y->time.next) + return -1; + if (x->time.next > y->time.next) + return 1; + + return 0; +} + +static usec_t time_event_source_latest(const sd_event_source *s) { + return usec_add(s->time.next, s->time.accuracy); +} + +static int latest_time_prioq_compare(const void *a, const void *b) { + const sd_event_source *x = a, *y = b; + + assert(EVENT_SOURCE_IS_TIME(x->type)); + assert(x->type == y->type); + + /* Enabled ones first */ + if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) + return -1; + if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) + return 1; + + /* Move the pending ones to the end */ + if (!x->pending && y->pending) + return -1; + if (x->pending && !y->pending) + return 1; + + /* Order by time */ + if (time_event_source_latest(x) < time_event_source_latest(y)) + return -1; + if (time_event_source_latest(x) > time_event_source_latest(y)) + return 1; + + return 0; +} + +static int exit_prioq_compare(const void *a, const void *b) { + const sd_event_source *x = a, *y = b; + + assert(x->type == SOURCE_EXIT); + assert(y->type == SOURCE_EXIT); + + /* Enabled ones first */ + if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) + return -1; + if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) + return 1; + + /* Lower priority values first */ + if (x->priority < y->priority) + return -1; + if (x->priority > y->priority) + return 1; + + return 0; +} + +static void free_clock_data(struct clock_data *d) { + assert(d); + assert(d->wakeup == WAKEUP_CLOCK_DATA); + + safe_close(d->fd); + prioq_free(d->earliest); + prioq_free(d->latest); +} + +static void event_free(sd_event *e) { + sd_event_source *s; + + assert(e); + + while ((s = e->sources)) { + assert(s->floating); + source_disconnect(s); + sd_event_source_unref(s); + } + + assert(e->n_sources == 0); + + if (e->default_event_ptr) + *(e->default_event_ptr) = NULL; + + safe_close(e->epoll_fd); + safe_close(e->watchdog_fd); + + free_clock_data(&e->realtime); + free_clock_data(&e->boottime); + free_clock_data(&e->monotonic); + free_clock_data(&e->realtime_alarm); + free_clock_data(&e->boottime_alarm); + + prioq_free(e->pending); + prioq_free(e->prepare); + prioq_free(e->exit); + + free(e->signal_sources); + hashmap_free(e->signal_data); + + hashmap_free(e->child_sources); + set_free(e->post_sources); + free(e); +} + +_public_ int sd_event_new(sd_event** ret) { + sd_event *e; + int r; + + assert_return(ret, -EINVAL); + + e = new0(sd_event, 1); + if (!e) + return -ENOMEM; + + e->n_ref = 1; + e->watchdog_fd = e->epoll_fd = e->realtime.fd = e->boottime.fd = e->monotonic.fd = e->realtime_alarm.fd = e->boottime_alarm.fd = -1; + e->realtime.next = e->boottime.next = e->monotonic.next = e->realtime_alarm.next = e->boottime_alarm.next = USEC_INFINITY; + e->realtime.wakeup = e->boottime.wakeup = e->monotonic.wakeup = e->realtime_alarm.wakeup = e->boottime_alarm.wakeup = WAKEUP_CLOCK_DATA; + e->original_pid = getpid(); + e->perturb = USEC_INFINITY; + + r = prioq_ensure_allocated(&e->pending, pending_prioq_compare); + if (r < 0) + goto fail; + + e->epoll_fd = epoll_create1(EPOLL_CLOEXEC); + if (e->epoll_fd < 0) { + r = -errno; + goto fail; + } + + if (secure_getenv("SD_EVENT_PROFILE_DELAYS")) { + log_debug("Event loop profiling enabled. Logarithmic histogram of event loop iterations in the range 2^0 ... 2^63 us will be logged every 5s."); + e->profile_delays = true; + } + + *ret = e; + return 0; + +fail: + event_free(e); + return r; +} + +_public_ sd_event* sd_event_ref(sd_event *e) { + + if (!e) + return NULL; + + assert(e->n_ref >= 1); + e->n_ref++; + + return e; +} + +_public_ sd_event* sd_event_unref(sd_event *e) { + + if (!e) + return NULL; + + assert(e->n_ref >= 1); + e->n_ref--; + + if (e->n_ref <= 0) + event_free(e); + + return NULL; +} + +static bool event_pid_changed(sd_event *e) { + assert(e); + + /* We don't support people creating an event loop and keeping + * it around over a fork(). Let's complain. */ + + return e->original_pid != getpid(); +} + +static void source_io_unregister(sd_event_source *s) { + int r; + + assert(s); + assert(s->type == SOURCE_IO); + + if (event_pid_changed(s->event)) + return; + + if (!s->io.registered) + return; + + r = epoll_ctl(s->event->epoll_fd, EPOLL_CTL_DEL, s->io.fd, NULL); + if (r < 0) + log_debug_errno(errno, "Failed to remove source %s (type %s) from epoll: %m", + strna(s->description), event_source_type_to_string(s->type)); + + s->io.registered = false; +} + +static int source_io_register( + sd_event_source *s, + int enabled, + uint32_t events) { + + struct epoll_event ev = {}; + int r; + + assert(s); + assert(s->type == SOURCE_IO); + assert(enabled != SD_EVENT_OFF); + + ev.events = events; + ev.data.ptr = s; + + if (enabled == SD_EVENT_ONESHOT) + ev.events |= EPOLLONESHOT; + + if (s->io.registered) + r = epoll_ctl(s->event->epoll_fd, EPOLL_CTL_MOD, s->io.fd, &ev); + else + r = epoll_ctl(s->event->epoll_fd, EPOLL_CTL_ADD, s->io.fd, &ev); + if (r < 0) + return -errno; + + s->io.registered = true; + + return 0; +} + +static clockid_t event_source_type_to_clock(EventSourceType t) { + + switch (t) { + + case SOURCE_TIME_REALTIME: + return CLOCK_REALTIME; + + case SOURCE_TIME_BOOTTIME: + return CLOCK_BOOTTIME; + + case SOURCE_TIME_MONOTONIC: + return CLOCK_MONOTONIC; + + case SOURCE_TIME_REALTIME_ALARM: + return CLOCK_REALTIME_ALARM; + + case SOURCE_TIME_BOOTTIME_ALARM: + return CLOCK_BOOTTIME_ALARM; + + default: + return (clockid_t) -1; + } +} + +static EventSourceType clock_to_event_source_type(clockid_t clock) { + + switch (clock) { + + case CLOCK_REALTIME: + return SOURCE_TIME_REALTIME; + + case CLOCK_BOOTTIME: + return SOURCE_TIME_BOOTTIME; + + case CLOCK_MONOTONIC: + return SOURCE_TIME_MONOTONIC; + + case CLOCK_REALTIME_ALARM: + return SOURCE_TIME_REALTIME_ALARM; + + case CLOCK_BOOTTIME_ALARM: + return SOURCE_TIME_BOOTTIME_ALARM; + + default: + return _SOURCE_EVENT_SOURCE_TYPE_INVALID; + } +} + +static struct clock_data* event_get_clock_data(sd_event *e, EventSourceType t) { + assert(e); + + switch (t) { + + case SOURCE_TIME_REALTIME: + return &e->realtime; + + case SOURCE_TIME_BOOTTIME: + return &e->boottime; + + case SOURCE_TIME_MONOTONIC: + return &e->monotonic; + + case SOURCE_TIME_REALTIME_ALARM: + return &e->realtime_alarm; + + case SOURCE_TIME_BOOTTIME_ALARM: + return &e->boottime_alarm; + + default: + return NULL; + } +} + +static int event_make_signal_data( + sd_event *e, + int sig, + struct signal_data **ret) { + + struct epoll_event ev = {}; + struct signal_data *d; + bool added = false; + sigset_t ss_copy; + int64_t priority; + int r; + + assert(e); + + if (event_pid_changed(e)) + return -ECHILD; + + if (e->signal_sources && e->signal_sources[sig]) + priority = e->signal_sources[sig]->priority; + else + priority = 0; + + d = hashmap_get(e->signal_data, &priority); + if (d) { + if (sigismember(&d->sigset, sig) > 0) { + if (ret) + *ret = d; + return 0; + } + } else { + r = hashmap_ensure_allocated(&e->signal_data, &uint64_hash_ops); + if (r < 0) + return r; + + d = new0(struct signal_data, 1); + if (!d) + return -ENOMEM; + + d->wakeup = WAKEUP_SIGNAL_DATA; + d->fd = -1; + d->priority = priority; + + r = hashmap_put(e->signal_data, &d->priority, d); + if (r < 0) { + free(d); + return r; + } + + added = true; + } + + ss_copy = d->sigset; + assert_se(sigaddset(&ss_copy, sig) >= 0); + + r = signalfd(d->fd, &ss_copy, SFD_NONBLOCK|SFD_CLOEXEC); + if (r < 0) { + r = -errno; + goto fail; + } + + d->sigset = ss_copy; + + if (d->fd >= 0) { + if (ret) + *ret = d; + return 0; + } + + d->fd = r; + + ev.events = EPOLLIN; + ev.data.ptr = d; + + r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, d->fd, &ev); + if (r < 0) { + r = -errno; + goto fail; + } + + if (ret) + *ret = d; + + return 0; + +fail: + if (added) { + d->fd = safe_close(d->fd); + hashmap_remove(e->signal_data, &d->priority); + free(d); + } + + return r; +} + +static void event_unmask_signal_data(sd_event *e, struct signal_data *d, int sig) { + assert(e); + assert(d); + + /* Turns off the specified signal in the signal data + * object. If the signal mask of the object becomes empty that + * way removes it. */ + + if (sigismember(&d->sigset, sig) == 0) + return; + + assert_se(sigdelset(&d->sigset, sig) >= 0); + + if (sigisemptyset(&d->sigset)) { + + /* If all the mask is all-zero we can get rid of the structure */ + hashmap_remove(e->signal_data, &d->priority); + assert(!d->current); + safe_close(d->fd); + free(d); + return; + } + + assert(d->fd >= 0); + + if (signalfd(d->fd, &d->sigset, SFD_NONBLOCK|SFD_CLOEXEC) < 0) + log_debug_errno(errno, "Failed to unset signal bit, ignoring: %m"); +} + +static void event_gc_signal_data(sd_event *e, const int64_t *priority, int sig) { + struct signal_data *d; + static const int64_t zero_priority = 0; + + assert(e); + + /* Rechecks if the specified signal is still something we are + * interested in. If not, we'll unmask it, and possibly drop + * the signalfd for it. */ + + if (sig == SIGCHLD && + e->n_enabled_child_sources > 0) + return; + + if (e->signal_sources && + e->signal_sources[sig] && + e->signal_sources[sig]->enabled != SD_EVENT_OFF) + return; + + /* + * The specified signal might be enabled in three different queues: + * + * 1) the one that belongs to the priority passed (if it is non-NULL) + * 2) the one that belongs to the priority of the event source of the signal (if there is one) + * 3) the 0 priority (to cover the SIGCHLD case) + * + * Hence, let's remove it from all three here. + */ + + if (priority) { + d = hashmap_get(e->signal_data, priority); + if (d) + event_unmask_signal_data(e, d, sig); + } + + if (e->signal_sources && e->signal_sources[sig]) { + d = hashmap_get(e->signal_data, &e->signal_sources[sig]->priority); + if (d) + event_unmask_signal_data(e, d, sig); + } + + d = hashmap_get(e->signal_data, &zero_priority); + if (d) + event_unmask_signal_data(e, d, sig); +} + +static void source_disconnect(sd_event_source *s) { + sd_event *event; + + assert(s); + + if (!s->event) + return; + + assert(s->event->n_sources > 0); + + switch (s->type) { + + case SOURCE_IO: + if (s->io.fd >= 0) + source_io_unregister(s); + + break; + + case SOURCE_TIME_REALTIME: + case SOURCE_TIME_BOOTTIME: + case SOURCE_TIME_MONOTONIC: + case SOURCE_TIME_REALTIME_ALARM: + case SOURCE_TIME_BOOTTIME_ALARM: { + struct clock_data *d; + + d = event_get_clock_data(s->event, s->type); + assert(d); + + prioq_remove(d->earliest, s, &s->time.earliest_index); + prioq_remove(d->latest, s, &s->time.latest_index); + d->needs_rearm = true; + break; + } + + case SOURCE_SIGNAL: + if (s->signal.sig > 0) { + + if (s->event->signal_sources) + s->event->signal_sources[s->signal.sig] = NULL; + + event_gc_signal_data(s->event, &s->priority, s->signal.sig); + } + + break; + + case SOURCE_CHILD: + if (s->child.pid > 0) { + if (s->enabled != SD_EVENT_OFF) { + assert(s->event->n_enabled_child_sources > 0); + s->event->n_enabled_child_sources--; + } + + (void) hashmap_remove(s->event->child_sources, PID_TO_PTR(s->child.pid)); + event_gc_signal_data(s->event, &s->priority, SIGCHLD); + } + + break; + + case SOURCE_DEFER: + /* nothing */ + break; + + case SOURCE_POST: + set_remove(s->event->post_sources, s); + break; + + case SOURCE_EXIT: + prioq_remove(s->event->exit, s, &s->exit.prioq_index); + break; + + default: + assert_not_reached("Wut? I shouldn't exist."); + } + + if (s->pending) + prioq_remove(s->event->pending, s, &s->pending_index); + + if (s->prepare) + prioq_remove(s->event->prepare, s, &s->prepare_index); + + event = s->event; + + s->type = _SOURCE_EVENT_SOURCE_TYPE_INVALID; + s->event = NULL; + LIST_REMOVE(sources, event->sources, s); + event->n_sources--; + + if (!s->floating) + sd_event_unref(event); +} + +static void source_free(sd_event_source *s) { + assert(s); + + source_disconnect(s); + free(s->description); + free(s); +} + +static int source_set_pending(sd_event_source *s, bool b) { + int r; + + assert(s); + assert(s->type != SOURCE_EXIT); + + if (s->pending == b) + return 0; + + s->pending = b; + + if (b) { + s->pending_iteration = s->event->iteration; + + r = prioq_put(s->event->pending, s, &s->pending_index); + if (r < 0) { + s->pending = false; + return r; + } + } else + assert_se(prioq_remove(s->event->pending, s, &s->pending_index)); + + if (EVENT_SOURCE_IS_TIME(s->type)) { + struct clock_data *d; + + d = event_get_clock_data(s->event, s->type); + assert(d); + + prioq_reshuffle(d->earliest, s, &s->time.earliest_index); + prioq_reshuffle(d->latest, s, &s->time.latest_index); + d->needs_rearm = true; + } + + if (s->type == SOURCE_SIGNAL && !b) { + struct signal_data *d; + + d = hashmap_get(s->event->signal_data, &s->priority); + if (d && d->current == s) + d->current = NULL; + } + + return 0; +} + +static sd_event_source *source_new(sd_event *e, bool floating, EventSourceType type) { + sd_event_source *s; + + assert(e); + + s = new0(sd_event_source, 1); + if (!s) + return NULL; + + s->n_ref = 1; + s->event = e; + s->floating = floating; + s->type = type; + s->pending_index = s->prepare_index = PRIOQ_IDX_NULL; + + if (!floating) + sd_event_ref(e); + + LIST_PREPEND(sources, e->sources, s); + e->n_sources++; + + return s; +} + +_public_ int sd_event_add_io( + sd_event *e, + sd_event_source **ret, + int fd, + uint32_t events, + sd_event_io_handler_t callback, + void *userdata) { + + sd_event_source *s; + int r; + + assert_return(e, -EINVAL); + assert_return(fd >= 0, -EBADF); + assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET)), -EINVAL); + assert_return(callback, -EINVAL); + assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(e), -ECHILD); + + s = source_new(e, !ret, SOURCE_IO); + if (!s) + return -ENOMEM; + + s->wakeup = WAKEUP_EVENT_SOURCE; + s->io.fd = fd; + s->io.events = events; + s->io.callback = callback; + s->userdata = userdata; + s->enabled = SD_EVENT_ON; + + r = source_io_register(s, s->enabled, events); + if (r < 0) { + source_free(s); + return r; + } + + if (ret) + *ret = s; + + return 0; +} + +static void initialize_perturb(sd_event *e) { + sd_id128_t bootid = {}; + + /* When we sleep for longer, we try to realign the wakeup to + the same time wihtin each minute/second/250ms, so that + events all across the system can be coalesced into a single + CPU wakeup. However, let's take some system-specific + randomness for this value, so that in a network of systems + with synced clocks timer events are distributed a + bit. Here, we calculate a perturbation usec offset from the + boot ID. */ + + if (_likely_(e->perturb != USEC_INFINITY)) + return; + + if (sd_id128_get_boot(&bootid) >= 0) + e->perturb = (bootid.qwords[0] ^ bootid.qwords[1]) % USEC_PER_MINUTE; +} + +static int event_setup_timer_fd( + sd_event *e, + struct clock_data *d, + clockid_t clock) { + + struct epoll_event ev = {}; + int r, fd; + + assert(e); + assert(d); + + if (_likely_(d->fd >= 0)) + return 0; + + fd = timerfd_create(clock, TFD_NONBLOCK|TFD_CLOEXEC); + if (fd < 0) + return -errno; + + ev.events = EPOLLIN; + ev.data.ptr = d; + + r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, fd, &ev); + if (r < 0) { + safe_close(fd); + return -errno; + } + + d->fd = fd; + return 0; +} + +static int time_exit_callback(sd_event_source *s, uint64_t usec, void *userdata) { + assert(s); + + return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata)); +} + +_public_ int sd_event_add_time( + sd_event *e, + sd_event_source **ret, + clockid_t clock, + uint64_t usec, + uint64_t accuracy, + sd_event_time_handler_t callback, + void *userdata) { + + EventSourceType type; + sd_event_source *s; + struct clock_data *d; + int r; + + assert_return(e, -EINVAL); + assert_return(accuracy != (uint64_t) -1, -EINVAL); + assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(e), -ECHILD); + + if (!callback) + callback = time_exit_callback; + + type = clock_to_event_source_type(clock); + assert_return(type >= 0, -EOPNOTSUPP); + + d = event_get_clock_data(e, type); + assert(d); + + r = prioq_ensure_allocated(&d->earliest, earliest_time_prioq_compare); + if (r < 0) + return r; + + r = prioq_ensure_allocated(&d->latest, latest_time_prioq_compare); + if (r < 0) + return r; + + if (d->fd < 0) { + r = event_setup_timer_fd(e, d, clock); + if (r < 0) + return r; + } + + s = source_new(e, !ret, type); + if (!s) + return -ENOMEM; + + s->time.next = usec; + s->time.accuracy = accuracy == 0 ? DEFAULT_ACCURACY_USEC : accuracy; + s->time.callback = callback; + s->time.earliest_index = s->time.latest_index = PRIOQ_IDX_NULL; + s->userdata = userdata; + s->enabled = SD_EVENT_ONESHOT; + + d->needs_rearm = true; + + r = prioq_put(d->earliest, s, &s->time.earliest_index); + if (r < 0) + goto fail; + + r = prioq_put(d->latest, s, &s->time.latest_index); + if (r < 0) + goto fail; + + if (ret) + *ret = s; + + return 0; + +fail: + source_free(s); + return r; +} + +#if 0 /* NM_IGNORED */ +static int signal_exit_callback(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { + assert(s); + + return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata)); +} + +_public_ int sd_event_add_signal( + sd_event *e, + sd_event_source **ret, + int sig, + sd_event_signal_handler_t callback, + void *userdata) { + + sd_event_source *s; + struct signal_data *d; + sigset_t ss; + int r; + + assert_return(e, -EINVAL); + assert_return(sig > 0, -EINVAL); + assert_return(sig < _NSIG, -EINVAL); + assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(e), -ECHILD); + + if (!callback) + callback = signal_exit_callback; + + r = pthread_sigmask(SIG_SETMASK, NULL, &ss); + if (r != 0) + return -r; + + if (!sigismember(&ss, sig)) + return -EBUSY; + + if (!e->signal_sources) { + e->signal_sources = new0(sd_event_source*, _NSIG); + if (!e->signal_sources) + return -ENOMEM; + } else if (e->signal_sources[sig]) + return -EBUSY; + + s = source_new(e, !ret, SOURCE_SIGNAL); + if (!s) + return -ENOMEM; + + s->signal.sig = sig; + s->signal.callback = callback; + s->userdata = userdata; + s->enabled = SD_EVENT_ON; + + e->signal_sources[sig] = s; + + r = event_make_signal_data(e, sig, &d); + if (r < 0) { + source_free(s); + return r; + } + + /* Use the signal name as description for the event source by default */ + (void) sd_event_source_set_description(s, signal_to_string(sig)); + + if (ret) + *ret = s; + + return 0; +} +#endif /* NM_IGNORED */ + +_public_ int sd_event_add_child( + sd_event *e, + sd_event_source **ret, + pid_t pid, + int options, + sd_event_child_handler_t callback, + void *userdata) { + + sd_event_source *s; + int r; + + assert_return(e, -EINVAL); + assert_return(pid > 1, -EINVAL); + assert_return(!(options & ~(WEXITED|WSTOPPED|WCONTINUED)), -EINVAL); + assert_return(options != 0, -EINVAL); + assert_return(callback, -EINVAL); + assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(e), -ECHILD); + + r = hashmap_ensure_allocated(&e->child_sources, NULL); + if (r < 0) + return r; + + if (hashmap_contains(e->child_sources, PID_TO_PTR(pid))) + return -EBUSY; + + s = source_new(e, !ret, SOURCE_CHILD); + if (!s) + return -ENOMEM; + + s->child.pid = pid; + s->child.options = options; + s->child.callback = callback; + s->userdata = userdata; + s->enabled = SD_EVENT_ONESHOT; + + r = hashmap_put(e->child_sources, PID_TO_PTR(pid), s); + if (r < 0) { + source_free(s); + return r; + } + + e->n_enabled_child_sources++; + + r = event_make_signal_data(e, SIGCHLD, NULL); + if (r < 0) { + e->n_enabled_child_sources--; + source_free(s); + return r; + } + + e->need_process_child = true; + + if (ret) + *ret = s; + + return 0; +} + +_public_ int sd_event_add_defer( + sd_event *e, + sd_event_source **ret, + sd_event_handler_t callback, + void *userdata) { + + sd_event_source *s; + int r; + + assert_return(e, -EINVAL); + assert_return(callback, -EINVAL); + assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(e), -ECHILD); + + s = source_new(e, !ret, SOURCE_DEFER); + if (!s) + return -ENOMEM; + + s->defer.callback = callback; + s->userdata = userdata; + s->enabled = SD_EVENT_ONESHOT; + + r = source_set_pending(s, true); + if (r < 0) { + source_free(s); + return r; + } + + if (ret) + *ret = s; + + return 0; +} + +_public_ int sd_event_add_post( + sd_event *e, + sd_event_source **ret, + sd_event_handler_t callback, + void *userdata) { + + sd_event_source *s; + int r; + + assert_return(e, -EINVAL); + assert_return(callback, -EINVAL); + assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(e), -ECHILD); + + r = set_ensure_allocated(&e->post_sources, NULL); + if (r < 0) + return r; + + s = source_new(e, !ret, SOURCE_POST); + if (!s) + return -ENOMEM; + + s->post.callback = callback; + s->userdata = userdata; + s->enabled = SD_EVENT_ON; + + r = set_put(e->post_sources, s); + if (r < 0) { + source_free(s); + return r; + } + + if (ret) + *ret = s; + + return 0; +} + +_public_ int sd_event_add_exit( + sd_event *e, + sd_event_source **ret, + sd_event_handler_t callback, + void *userdata) { + + sd_event_source *s; + int r; + + assert_return(e, -EINVAL); + assert_return(callback, -EINVAL); + assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(e), -ECHILD); + + r = prioq_ensure_allocated(&e->exit, exit_prioq_compare); + if (r < 0) + return r; + + s = source_new(e, !ret, SOURCE_EXIT); + if (!s) + return -ENOMEM; + + s->exit.callback = callback; + s->userdata = userdata; + s->exit.prioq_index = PRIOQ_IDX_NULL; + s->enabled = SD_EVENT_ONESHOT; + + r = prioq_put(s->event->exit, s, &s->exit.prioq_index); + if (r < 0) { + source_free(s); + return r; + } + + if (ret) + *ret = s; + + return 0; +} + +_public_ sd_event_source* sd_event_source_ref(sd_event_source *s) { + + if (!s) + return NULL; + + assert(s->n_ref >= 1); + s->n_ref++; + + return s; +} + +_public_ sd_event_source* sd_event_source_unref(sd_event_source *s) { + + if (!s) + return NULL; + + assert(s->n_ref >= 1); + s->n_ref--; + + if (s->n_ref <= 0) { + /* Here's a special hack: when we are called from a + * dispatch handler we won't free the event source + * immediately, but we will detach the fd from the + * epoll. This way it is safe for the caller to unref + * the event source and immediately close the fd, but + * we still retain a valid event source object after + * the callback. */ + + if (s->dispatching) { + if (s->type == SOURCE_IO) + source_io_unregister(s); + + source_disconnect(s); + } else + source_free(s); + } + + return NULL; +} + +_public_ int sd_event_source_set_description(sd_event_source *s, const char *description) { + assert_return(s, -EINVAL); + assert_return(!event_pid_changed(s->event), -ECHILD); + + return free_and_strdup(&s->description, description); +} + +_public_ int sd_event_source_get_description(sd_event_source *s, const char **description) { + assert_return(s, -EINVAL); + assert_return(description, -EINVAL); + assert_return(s->description, -ENXIO); + assert_return(!event_pid_changed(s->event), -ECHILD); + + *description = s->description; + return 0; +} + +_public_ sd_event *sd_event_source_get_event(sd_event_source *s) { + assert_return(s, NULL); + + return s->event; +} + +_public_ int sd_event_source_get_pending(sd_event_source *s) { + assert_return(s, -EINVAL); + assert_return(s->type != SOURCE_EXIT, -EDOM); + assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(s->event), -ECHILD); + + return s->pending; +} + +_public_ int sd_event_source_get_io_fd(sd_event_source *s) { + assert_return(s, -EINVAL); + assert_return(s->type == SOURCE_IO, -EDOM); + assert_return(!event_pid_changed(s->event), -ECHILD); + + return s->io.fd; +} + +_public_ int sd_event_source_set_io_fd(sd_event_source *s, int fd) { + int r; + + assert_return(s, -EINVAL); + assert_return(fd >= 0, -EBADF); + assert_return(s->type == SOURCE_IO, -EDOM); + assert_return(!event_pid_changed(s->event), -ECHILD); + + if (s->io.fd == fd) + return 0; + + if (s->enabled == SD_EVENT_OFF) { + s->io.fd = fd; + s->io.registered = false; + } else { + int saved_fd; + + saved_fd = s->io.fd; + assert(s->io.registered); + + s->io.fd = fd; + s->io.registered = false; + + r = source_io_register(s, s->enabled, s->io.events); + if (r < 0) { + s->io.fd = saved_fd; + s->io.registered = true; + return r; + } + + epoll_ctl(s->event->epoll_fd, EPOLL_CTL_DEL, saved_fd, NULL); + } + + return 0; +} + +_public_ int sd_event_source_get_io_events(sd_event_source *s, uint32_t* events) { + assert_return(s, -EINVAL); + assert_return(events, -EINVAL); + assert_return(s->type == SOURCE_IO, -EDOM); + assert_return(!event_pid_changed(s->event), -ECHILD); + + *events = s->io.events; + return 0; +} + +_public_ int sd_event_source_set_io_events(sd_event_source *s, uint32_t events) { + int r; + + assert_return(s, -EINVAL); + assert_return(s->type == SOURCE_IO, -EDOM); + assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET)), -EINVAL); + assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(s->event), -ECHILD); + + /* edge-triggered updates are never skipped, so we can reset edges */ + if (s->io.events == events && !(events & EPOLLET)) + return 0; + + if (s->enabled != SD_EVENT_OFF) { + r = source_io_register(s, s->enabled, events); + if (r < 0) + return r; + } + + s->io.events = events; + source_set_pending(s, false); + + return 0; +} + +_public_ int sd_event_source_get_io_revents(sd_event_source *s, uint32_t* revents) { + assert_return(s, -EINVAL); + assert_return(revents, -EINVAL); + assert_return(s->type == SOURCE_IO, -EDOM); + assert_return(s->pending, -ENODATA); + assert_return(!event_pid_changed(s->event), -ECHILD); + + *revents = s->io.revents; + return 0; +} + +_public_ int sd_event_source_get_signal(sd_event_source *s) { + assert_return(s, -EINVAL); + assert_return(s->type == SOURCE_SIGNAL, -EDOM); + assert_return(!event_pid_changed(s->event), -ECHILD); + + return s->signal.sig; +} + +_public_ int sd_event_source_get_priority(sd_event_source *s, int64_t *priority) { + assert_return(s, -EINVAL); + assert_return(!event_pid_changed(s->event), -ECHILD); + + return s->priority; +} + +_public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority) { + int r; + + assert_return(s, -EINVAL); + assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(s->event), -ECHILD); + + if (s->priority == priority) + return 0; + + if (s->type == SOURCE_SIGNAL && s->enabled != SD_EVENT_OFF) { + struct signal_data *old, *d; + + /* Move us from the signalfd belonging to the old + * priority to the signalfd of the new priority */ + + assert_se(old = hashmap_get(s->event->signal_data, &s->priority)); + + s->priority = priority; + + r = event_make_signal_data(s->event, s->signal.sig, &d); + if (r < 0) { + s->priority = old->priority; + return r; + } + + event_unmask_signal_data(s->event, old, s->signal.sig); + } else + s->priority = priority; + + if (s->pending) + prioq_reshuffle(s->event->pending, s, &s->pending_index); + + if (s->prepare) + prioq_reshuffle(s->event->prepare, s, &s->prepare_index); + + if (s->type == SOURCE_EXIT) + prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index); + + return 0; +} + +_public_ int sd_event_source_get_enabled(sd_event_source *s, int *m) { + assert_return(s, -EINVAL); + assert_return(m, -EINVAL); + assert_return(!event_pid_changed(s->event), -ECHILD); + + *m = s->enabled; + return 0; +} + +_public_ int sd_event_source_set_enabled(sd_event_source *s, int m) { + int r; + + assert_return(s, -EINVAL); + assert_return(m == SD_EVENT_OFF || m == SD_EVENT_ON || m == SD_EVENT_ONESHOT, -EINVAL); + assert_return(!event_pid_changed(s->event), -ECHILD); + + /* If we are dead anyway, we are fine with turning off + * sources, but everything else needs to fail. */ + if (s->event->state == SD_EVENT_FINISHED) + return m == SD_EVENT_OFF ? 0 : -ESTALE; + + if (s->enabled == m) + return 0; + + if (m == SD_EVENT_OFF) { + + switch (s->type) { + + case SOURCE_IO: + source_io_unregister(s); + s->enabled = m; + break; + + case SOURCE_TIME_REALTIME: + case SOURCE_TIME_BOOTTIME: + case SOURCE_TIME_MONOTONIC: + case SOURCE_TIME_REALTIME_ALARM: + case SOURCE_TIME_BOOTTIME_ALARM: { + struct clock_data *d; + + s->enabled = m; + d = event_get_clock_data(s->event, s->type); + assert(d); + + prioq_reshuffle(d->earliest, s, &s->time.earliest_index); + prioq_reshuffle(d->latest, s, &s->time.latest_index); + d->needs_rearm = true; + break; + } + + case SOURCE_SIGNAL: + s->enabled = m; + + event_gc_signal_data(s->event, &s->priority, s->signal.sig); + break; + + case SOURCE_CHILD: + s->enabled = m; + + assert(s->event->n_enabled_child_sources > 0); + s->event->n_enabled_child_sources--; + + event_gc_signal_data(s->event, &s->priority, SIGCHLD); + break; + + case SOURCE_EXIT: + s->enabled = m; + prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index); + break; + + case SOURCE_DEFER: + case SOURCE_POST: + s->enabled = m; + break; + + default: + assert_not_reached("Wut? I shouldn't exist."); + } + + } else { + switch (s->type) { + + case SOURCE_IO: + r = source_io_register(s, m, s->io.events); + if (r < 0) + return r; + + s->enabled = m; + break; + + case SOURCE_TIME_REALTIME: + case SOURCE_TIME_BOOTTIME: + case SOURCE_TIME_MONOTONIC: + case SOURCE_TIME_REALTIME_ALARM: + case SOURCE_TIME_BOOTTIME_ALARM: { + struct clock_data *d; + + s->enabled = m; + d = event_get_clock_data(s->event, s->type); + assert(d); + + prioq_reshuffle(d->earliest, s, &s->time.earliest_index); + prioq_reshuffle(d->latest, s, &s->time.latest_index); + d->needs_rearm = true; + break; + } + + case SOURCE_SIGNAL: + + s->enabled = m; + + r = event_make_signal_data(s->event, s->signal.sig, NULL); + if (r < 0) { + s->enabled = SD_EVENT_OFF; + event_gc_signal_data(s->event, &s->priority, s->signal.sig); + return r; + } + + break; + + case SOURCE_CHILD: + + if (s->enabled == SD_EVENT_OFF) + s->event->n_enabled_child_sources++; + + s->enabled = m; + + r = event_make_signal_data(s->event, SIGCHLD, NULL); + if (r < 0) { + s->enabled = SD_EVENT_OFF; + s->event->n_enabled_child_sources--; + event_gc_signal_data(s->event, &s->priority, SIGCHLD); + return r; + } + + break; + + case SOURCE_EXIT: + s->enabled = m; + prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index); + break; + + case SOURCE_DEFER: + case SOURCE_POST: + s->enabled = m; + break; + + default: + assert_not_reached("Wut? I shouldn't exist."); + } + } + + if (s->pending) + prioq_reshuffle(s->event->pending, s, &s->pending_index); + + if (s->prepare) + prioq_reshuffle(s->event->prepare, s, &s->prepare_index); + + return 0; +} + +_public_ int sd_event_source_get_time(sd_event_source *s, uint64_t *usec) { + assert_return(s, -EINVAL); + assert_return(usec, -EINVAL); + assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); + assert_return(!event_pid_changed(s->event), -ECHILD); + + *usec = s->time.next; + return 0; +} + +_public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) { + struct clock_data *d; + + assert_return(s, -EINVAL); + assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); + assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(s->event), -ECHILD); + + s->time.next = usec; + + source_set_pending(s, false); + + d = event_get_clock_data(s->event, s->type); + assert(d); + + prioq_reshuffle(d->earliest, s, &s->time.earliest_index); + prioq_reshuffle(d->latest, s, &s->time.latest_index); + d->needs_rearm = true; + + return 0; +} + +_public_ int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *usec) { + assert_return(s, -EINVAL); + assert_return(usec, -EINVAL); + assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); + assert_return(!event_pid_changed(s->event), -ECHILD); + + *usec = s->time.accuracy; + return 0; +} + +_public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec) { + struct clock_data *d; + + assert_return(s, -EINVAL); + assert_return(usec != (uint64_t) -1, -EINVAL); + assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); + assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(s->event), -ECHILD); + + if (usec == 0) + usec = DEFAULT_ACCURACY_USEC; + + s->time.accuracy = usec; + + source_set_pending(s, false); + + d = event_get_clock_data(s->event, s->type); + assert(d); + + prioq_reshuffle(d->latest, s, &s->time.latest_index); + d->needs_rearm = true; + + return 0; +} + +_public_ int sd_event_source_get_time_clock(sd_event_source *s, clockid_t *clock) { + assert_return(s, -EINVAL); + assert_return(clock, -EINVAL); + assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); + assert_return(!event_pid_changed(s->event), -ECHILD); + + *clock = event_source_type_to_clock(s->type); + return 0; +} + +_public_ int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid) { + assert_return(s, -EINVAL); + assert_return(pid, -EINVAL); + assert_return(s->type == SOURCE_CHILD, -EDOM); + assert_return(!event_pid_changed(s->event), -ECHILD); + + *pid = s->child.pid; + return 0; +} + +_public_ int sd_event_source_set_prepare(sd_event_source *s, sd_event_handler_t callback) { + int r; + + assert_return(s, -EINVAL); + assert_return(s->type != SOURCE_EXIT, -EDOM); + assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(s->event), -ECHILD); + + if (s->prepare == callback) + return 0; + + if (callback && s->prepare) { + s->prepare = callback; + return 0; + } + + r = prioq_ensure_allocated(&s->event->prepare, prepare_prioq_compare); + if (r < 0) + return r; + + s->prepare = callback; + + if (callback) { + r = prioq_put(s->event->prepare, s, &s->prepare_index); + if (r < 0) + return r; + } else + prioq_remove(s->event->prepare, s, &s->prepare_index); + + return 0; +} + +_public_ void* sd_event_source_get_userdata(sd_event_source *s) { + assert_return(s, NULL); + + return s->userdata; +} + +_public_ void *sd_event_source_set_userdata(sd_event_source *s, void *userdata) { + void *ret; + + assert_return(s, NULL); + + ret = s->userdata; + s->userdata = userdata; + + return ret; +} + +static usec_t sleep_between(sd_event *e, usec_t a, usec_t b) { + usec_t c; + assert(e); + assert(a <= b); + + if (a <= 0) + return 0; + if (a >= USEC_INFINITY) + return USEC_INFINITY; + + if (b <= a + 1) + return a; + + initialize_perturb(e); + + /* + Find a good time to wake up again between times a and b. We + have two goals here: + + a) We want to wake up as seldom as possible, hence prefer + later times over earlier times. + + b) But if we have to wake up, then let's make sure to + dispatch as much as possible on the entire system. + + We implement this by waking up everywhere at the same time + within any given minute if we can, synchronised via the + perturbation value determined from the boot ID. If we can't, + then we try to find the same spot in every 10s, then 1s and + then 250ms step. Otherwise, we pick the last possible time + to wake up. + */ + + c = (b / USEC_PER_MINUTE) * USEC_PER_MINUTE + e->perturb; + if (c >= b) { + if (_unlikely_(c < USEC_PER_MINUTE)) + return b; + + c -= USEC_PER_MINUTE; + } + + if (c >= a) + return c; + + c = (b / (USEC_PER_SEC*10)) * (USEC_PER_SEC*10) + (e->perturb % (USEC_PER_SEC*10)); + if (c >= b) { + if (_unlikely_(c < USEC_PER_SEC*10)) + return b; + + c -= USEC_PER_SEC*10; + } + + if (c >= a) + return c; + + c = (b / USEC_PER_SEC) * USEC_PER_SEC + (e->perturb % USEC_PER_SEC); + if (c >= b) { + if (_unlikely_(c < USEC_PER_SEC)) + return b; + + c -= USEC_PER_SEC; + } + + if (c >= a) + return c; + + c = (b / (USEC_PER_MSEC*250)) * (USEC_PER_MSEC*250) + (e->perturb % (USEC_PER_MSEC*250)); + if (c >= b) { + if (_unlikely_(c < USEC_PER_MSEC*250)) + return b; + + c -= USEC_PER_MSEC*250; + } + + if (c >= a) + return c; + + return b; +} + +static int event_arm_timer( + sd_event *e, + struct clock_data *d) { + + struct itimerspec its = {}; + sd_event_source *a, *b; + usec_t t; + int r; + + assert(e); + assert(d); + + if (!d->needs_rearm) + return 0; + else + d->needs_rearm = false; + + a = prioq_peek(d->earliest); + if (!a || a->enabled == SD_EVENT_OFF || a->time.next == USEC_INFINITY) { + + if (d->fd < 0) + return 0; + + if (d->next == USEC_INFINITY) + return 0; + + /* disarm */ + r = timerfd_settime(d->fd, TFD_TIMER_ABSTIME, &its, NULL); + if (r < 0) + return r; + + d->next = USEC_INFINITY; + return 0; + } + + b = prioq_peek(d->latest); + assert_se(b && b->enabled != SD_EVENT_OFF); + + t = sleep_between(e, a->time.next, time_event_source_latest(b)); + if (d->next == t) + return 0; + + assert_se(d->fd >= 0); + + if (t == 0) { + /* We don' want to disarm here, just mean some time looooong ago. */ + its.it_value.tv_sec = 0; + its.it_value.tv_nsec = 1; + } else + timespec_store(&its.it_value, t); + + r = timerfd_settime(d->fd, TFD_TIMER_ABSTIME, &its, NULL); + if (r < 0) + return -errno; + + d->next = t; + return 0; +} + +static int process_io(sd_event *e, sd_event_source *s, uint32_t revents) { + assert(e); + assert(s); + assert(s->type == SOURCE_IO); + + /* If the event source was already pending, we just OR in the + * new revents, otherwise we reset the value. The ORing is + * necessary to handle EPOLLONESHOT events properly where + * readability might happen independently of writability, and + * we need to keep track of both */ + + if (s->pending) + s->io.revents |= revents; + else + s->io.revents = revents; + + return source_set_pending(s, true); +} + +static int flush_timer(sd_event *e, int fd, uint32_t events, usec_t *next) { + uint64_t x; + ssize_t ss; + + assert(e); + assert(fd >= 0); + + assert_return(events == EPOLLIN, -EIO); + + ss = read(fd, &x, sizeof(x)); + if (ss < 0) { + if (errno == EAGAIN || errno == EINTR) + return 0; + + return -errno; + } + + if (_unlikely_(ss != sizeof(x))) + return -EIO; + + if (next) + *next = USEC_INFINITY; + + return 0; +} + +static int process_timer( + sd_event *e, + usec_t n, + struct clock_data *d) { + + sd_event_source *s; + int r; + + assert(e); + assert(d); + + for (;;) { + s = prioq_peek(d->earliest); + if (!s || + s->time.next > n || + s->enabled == SD_EVENT_OFF || + s->pending) + break; + + r = source_set_pending(s, true); + if (r < 0) + return r; + + prioq_reshuffle(d->earliest, s, &s->time.earliest_index); + prioq_reshuffle(d->latest, s, &s->time.latest_index); + d->needs_rearm = true; + } + + return 0; +} + +static int process_child(sd_event *e) { + sd_event_source *s; + Iterator i; + int r; + + assert(e); + + e->need_process_child = false; + + /* + So, this is ugly. We iteratively invoke waitid() with P_PID + + WNOHANG for each PID we wait for, instead of using + P_ALL. This is because we only want to get child + information of very specific child processes, and not all + of them. We might not have processed the SIGCHLD even of a + previous invocation and we don't want to maintain a + unbounded *per-child* event queue, hence we really don't + want anything flushed out of the kernel's queue that we + don't care about. Since this is O(n) this means that if you + have a lot of processes you probably want to handle SIGCHLD + yourself. + + We do not reap the children here (by using WNOWAIT), this + is only done after the event source is dispatched so that + the callback still sees the process as a zombie. + */ + + HASHMAP_FOREACH(s, e->child_sources, i) { + assert(s->type == SOURCE_CHILD); + + if (s->pending) + continue; + + if (s->enabled == SD_EVENT_OFF) + continue; + + zero(s->child.siginfo); + r = waitid(P_PID, s->child.pid, &s->child.siginfo, + WNOHANG | (s->child.options & WEXITED ? WNOWAIT : 0) | s->child.options); + if (r < 0) + return -errno; + + if (s->child.siginfo.si_pid != 0) { + bool zombie = + s->child.siginfo.si_code == CLD_EXITED || + s->child.siginfo.si_code == CLD_KILLED || + s->child.siginfo.si_code == CLD_DUMPED; + + if (!zombie && (s->child.options & WEXITED)) { + /* If the child isn't dead then let's + * immediately remove the state change + * from the queue, since there's no + * benefit in leaving it queued */ + + assert(s->child.options & (WSTOPPED|WCONTINUED)); + waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG|(s->child.options & (WSTOPPED|WCONTINUED))); + } + + r = source_set_pending(s, true); + if (r < 0) + return r; + } + } + + return 0; +} + +static int process_signal(sd_event *e, struct signal_data *d, uint32_t events) { + bool read_one = false; + int r; + + assert(e); + assert_return(events == EPOLLIN, -EIO); + + /* If there's a signal queued on this priority and SIGCHLD is + on this priority too, then make sure to recheck the + children we watch. This is because we only ever dequeue + the first signal per priority, and if we dequeue one, and + SIGCHLD might be enqueued later we wouldn't know, but we + might have higher priority children we care about hence we + need to check that explicitly. */ + + if (sigismember(&d->sigset, SIGCHLD)) + e->need_process_child = true; + + /* If there's already an event source pending for this + * priority we don't read another */ + if (d->current) + return 0; + + for (;;) { + struct signalfd_siginfo si; + ssize_t n; + sd_event_source *s = NULL; + + n = read(d->fd, &si, sizeof(si)); + if (n < 0) { + if (errno == EAGAIN || errno == EINTR) + return read_one; + + return -errno; + } + + if (_unlikely_(n != sizeof(si))) + return -EIO; + + assert(si.ssi_signo < _NSIG); + + read_one = true; + + if (e->signal_sources) + s = e->signal_sources[si.ssi_signo]; + if (!s) + continue; + if (s->pending) + continue; + + s->signal.siginfo = si; + d->current = s; + + r = source_set_pending(s, true); + if (r < 0) + return r; + + return 1; + } +} + +static int source_dispatch(sd_event_source *s) { + int r = 0; + + assert(s); + assert(s->pending || s->type == SOURCE_EXIT); + + if (s->type != SOURCE_DEFER && s->type != SOURCE_EXIT) { + r = source_set_pending(s, false); + if (r < 0) + return r; + } + + if (s->type != SOURCE_POST) { + sd_event_source *z; + Iterator i; + + /* If we execute a non-post source, let's mark all + * post sources as pending */ + + SET_FOREACH(z, s->event->post_sources, i) { + if (z->enabled == SD_EVENT_OFF) + continue; + + r = source_set_pending(z, true); + if (r < 0) + return r; + } + } + + if (s->enabled == SD_EVENT_ONESHOT) { + r = sd_event_source_set_enabled(s, SD_EVENT_OFF); + if (r < 0) + return r; + } + + s->dispatching = true; + + switch (s->type) { + + case SOURCE_IO: + r = s->io.callback(s, s->io.fd, s->io.revents, s->userdata); + break; + + case SOURCE_TIME_REALTIME: + case SOURCE_TIME_BOOTTIME: + case SOURCE_TIME_MONOTONIC: + case SOURCE_TIME_REALTIME_ALARM: + case SOURCE_TIME_BOOTTIME_ALARM: + r = s->time.callback(s, s->time.next, s->userdata); + break; + + case SOURCE_SIGNAL: + r = s->signal.callback(s, &s->signal.siginfo, s->userdata); + break; + + case SOURCE_CHILD: { + bool zombie; + + zombie = s->child.siginfo.si_code == CLD_EXITED || + s->child.siginfo.si_code == CLD_KILLED || + s->child.siginfo.si_code == CLD_DUMPED; + + r = s->child.callback(s, &s->child.siginfo, s->userdata); + + /* Now, reap the PID for good. */ + if (zombie) + waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG|WEXITED); + + break; + } + + case SOURCE_DEFER: + r = s->defer.callback(s, s->userdata); + break; + + case SOURCE_POST: + r = s->post.callback(s, s->userdata); + break; + + case SOURCE_EXIT: + r = s->exit.callback(s, s->userdata); + break; + + case SOURCE_WATCHDOG: + case _SOURCE_EVENT_SOURCE_TYPE_MAX: + case _SOURCE_EVENT_SOURCE_TYPE_INVALID: + assert_not_reached("Wut? I shouldn't exist."); + } + + s->dispatching = false; + + if (r < 0) + log_debug_errno(r, "Event source %s (type %s) returned error, disabling: %m", + strna(s->description), event_source_type_to_string(s->type)); + + if (s->n_ref == 0) + source_free(s); + else if (r < 0) + sd_event_source_set_enabled(s, SD_EVENT_OFF); + + return 1; +} + +static int event_prepare(sd_event *e) { + int r; + + assert(e); + + for (;;) { + sd_event_source *s; + + s = prioq_peek(e->prepare); + if (!s || s->prepare_iteration == e->iteration || s->enabled == SD_EVENT_OFF) + break; + + s->prepare_iteration = e->iteration; + r = prioq_reshuffle(e->prepare, s, &s->prepare_index); + if (r < 0) + return r; + + assert(s->prepare); + + s->dispatching = true; + r = s->prepare(s, s->userdata); + s->dispatching = false; + + if (r < 0) + log_debug_errno(r, "Prepare callback of event source %s (type %s) returned error, disabling: %m", + strna(s->description), event_source_type_to_string(s->type)); + + if (s->n_ref == 0) + source_free(s); + else if (r < 0) + sd_event_source_set_enabled(s, SD_EVENT_OFF); + } + + return 0; +} + +static int dispatch_exit(sd_event *e) { + sd_event_source *p; + int r; + + assert(e); + + p = prioq_peek(e->exit); + if (!p || p->enabled == SD_EVENT_OFF) { + e->state = SD_EVENT_FINISHED; + return 0; + } + + sd_event_ref(e); + e->iteration++; + e->state = SD_EVENT_EXITING; + + r = source_dispatch(p); + + e->state = SD_EVENT_INITIAL; + sd_event_unref(e); + + return r; +} + +static sd_event_source* event_next_pending(sd_event *e) { + sd_event_source *p; + + assert(e); + + p = prioq_peek(e->pending); + if (!p) + return NULL; + + if (p->enabled == SD_EVENT_OFF) + return NULL; + + return p; +} + +static int arm_watchdog(sd_event *e) { + struct itimerspec its = {}; + usec_t t; + int r; + + assert(e); + assert(e->watchdog_fd >= 0); + + t = sleep_between(e, + e->watchdog_last + (e->watchdog_period / 2), + e->watchdog_last + (e->watchdog_period * 3 / 4)); + + timespec_store(&its.it_value, t); + + /* Make sure we never set the watchdog to 0, which tells the + * kernel to disable it. */ + if (its.it_value.tv_sec == 0 && its.it_value.tv_nsec == 0) + its.it_value.tv_nsec = 1; + + r = timerfd_settime(e->watchdog_fd, TFD_TIMER_ABSTIME, &its, NULL); + if (r < 0) + return -errno; + + return 0; +} + +static int process_watchdog(sd_event *e) { + assert(e); + + if (!e->watchdog) + return 0; + + /* Don't notify watchdog too often */ + if (e->watchdog_last + e->watchdog_period / 4 > e->timestamp.monotonic) + return 0; + + sd_notify(false, "WATCHDOG=1"); + e->watchdog_last = e->timestamp.monotonic; + + return arm_watchdog(e); +} + +_public_ int sd_event_prepare(sd_event *e) { + int r; + + assert_return(e, -EINVAL); + assert_return(!event_pid_changed(e), -ECHILD); + assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(e->state == SD_EVENT_INITIAL, -EBUSY); + + if (e->exit_requested) + goto pending; + + e->iteration++; + + e->state = SD_EVENT_PREPARING; + r = event_prepare(e); + e->state = SD_EVENT_INITIAL; + if (r < 0) + return r; + + r = event_arm_timer(e, &e->realtime); + if (r < 0) + return r; + + r = event_arm_timer(e, &e->boottime); + if (r < 0) + return r; + + r = event_arm_timer(e, &e->monotonic); + if (r < 0) + return r; + + r = event_arm_timer(e, &e->realtime_alarm); + if (r < 0) + return r; + + r = event_arm_timer(e, &e->boottime_alarm); + if (r < 0) + return r; + + if (event_next_pending(e) || e->need_process_child) + goto pending; + + e->state = SD_EVENT_ARMED; + + return 0; + +pending: + e->state = SD_EVENT_ARMED; + r = sd_event_wait(e, 0); + if (r == 0) + e->state = SD_EVENT_ARMED; + + return r; +} + +_public_ int sd_event_wait(sd_event *e, uint64_t timeout) { + struct epoll_event *ev_queue; + unsigned ev_queue_max; + int r, m, i; + + assert_return(e, -EINVAL); + assert_return(!event_pid_changed(e), -ECHILD); + assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(e->state == SD_EVENT_ARMED, -EBUSY); + + if (e->exit_requested) { + e->state = SD_EVENT_PENDING; + return 1; + } + + ev_queue_max = MAX(e->n_sources, 1u); + ev_queue = newa(struct epoll_event, ev_queue_max); + + m = epoll_wait(e->epoll_fd, ev_queue, ev_queue_max, + timeout == (uint64_t) -1 ? -1 : (int) ((timeout + USEC_PER_MSEC - 1) / USEC_PER_MSEC)); + if (m < 0) { + if (errno == EINTR) { + e->state = SD_EVENT_PENDING; + return 1; + } + + r = -errno; + goto finish; + } + + dual_timestamp_get(&e->timestamp); + e->timestamp_boottime = now(CLOCK_BOOTTIME); + + for (i = 0; i < m; i++) { + + if (ev_queue[i].data.ptr == INT_TO_PTR(SOURCE_WATCHDOG)) + r = flush_timer(e, e->watchdog_fd, ev_queue[i].events, NULL); + else { + WakeupType *t = ev_queue[i].data.ptr; + + switch (*t) { + + case WAKEUP_EVENT_SOURCE: + r = process_io(e, ev_queue[i].data.ptr, ev_queue[i].events); + break; + + case WAKEUP_CLOCK_DATA: { + struct clock_data *d = ev_queue[i].data.ptr; + r = flush_timer(e, d->fd, ev_queue[i].events, &d->next); + break; + } + + case WAKEUP_SIGNAL_DATA: + r = process_signal(e, ev_queue[i].data.ptr, ev_queue[i].events); + break; + + default: + assert_not_reached("Invalid wake-up pointer"); + } + } + if (r < 0) + goto finish; + } + + r = process_watchdog(e); + if (r < 0) + goto finish; + + r = process_timer(e, e->timestamp.realtime, &e->realtime); + if (r < 0) + goto finish; + + r = process_timer(e, e->timestamp_boottime, &e->boottime); + if (r < 0) + goto finish; + + r = process_timer(e, e->timestamp.monotonic, &e->monotonic); + if (r < 0) + goto finish; + + r = process_timer(e, e->timestamp.realtime, &e->realtime_alarm); + if (r < 0) + goto finish; + + r = process_timer(e, e->timestamp_boottime, &e->boottime_alarm); + if (r < 0) + goto finish; + + if (e->need_process_child) { + r = process_child(e); + if (r < 0) + goto finish; + } + + if (event_next_pending(e)) { + e->state = SD_EVENT_PENDING; + + return 1; + } + + r = 0; + +finish: + e->state = SD_EVENT_INITIAL; + + return r; +} + +_public_ int sd_event_dispatch(sd_event *e) { + sd_event_source *p; + int r; + + assert_return(e, -EINVAL); + assert_return(!event_pid_changed(e), -ECHILD); + assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(e->state == SD_EVENT_PENDING, -EBUSY); + + if (e->exit_requested) + return dispatch_exit(e); + + p = event_next_pending(e); + if (p) { + sd_event_ref(e); + + e->state = SD_EVENT_RUNNING; + r = source_dispatch(p); + e->state = SD_EVENT_INITIAL; + + sd_event_unref(e); + + return r; + } + + e->state = SD_EVENT_INITIAL; + + return 1; +} + +static void event_log_delays(sd_event *e) { + char b[ELEMENTSOF(e->delays) * DECIMAL_STR_MAX(unsigned) + 1]; + unsigned i; + int o; + + for (i = o = 0; i < ELEMENTSOF(e->delays); i++) { + o += snprintf(&b[o], sizeof(b) - o, "%u ", e->delays[i]); + e->delays[i] = 0; + } + log_debug("Event loop iterations: %.*s", o, b); +} + +_public_ int sd_event_run(sd_event *e, uint64_t timeout) { + int r; + + assert_return(e, -EINVAL); + assert_return(!event_pid_changed(e), -ECHILD); + assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(e->state == SD_EVENT_INITIAL, -EBUSY); + + if (e->profile_delays && e->last_run) { + usec_t this_run; + unsigned l; + + this_run = now(CLOCK_MONOTONIC); + + l = u64log2(this_run - e->last_run); + assert(l < sizeof(e->delays)); + e->delays[l]++; + + if (this_run - e->last_log >= 5*USEC_PER_SEC) { + event_log_delays(e); + e->last_log = this_run; + } + } + + r = sd_event_prepare(e); + if (r == 0) + /* There was nothing? Then wait... */ + r = sd_event_wait(e, timeout); + + if (e->profile_delays) + e->last_run = now(CLOCK_MONOTONIC); + + if (r > 0) { + /* There's something now, then let's dispatch it */ + r = sd_event_dispatch(e); + if (r < 0) + return r; + + return 1; + } + + return r; +} + +_public_ int sd_event_loop(sd_event *e) { + int r; + + assert_return(e, -EINVAL); + assert_return(!event_pid_changed(e), -ECHILD); + assert_return(e->state == SD_EVENT_INITIAL, -EBUSY); + + sd_event_ref(e); + + while (e->state != SD_EVENT_FINISHED) { + r = sd_event_run(e, (uint64_t) -1); + if (r < 0) + goto finish; + } + + r = e->exit_code; + +finish: + sd_event_unref(e); + return r; +} + +_public_ int sd_event_get_fd(sd_event *e) { + + assert_return(e, -EINVAL); + assert_return(!event_pid_changed(e), -ECHILD); + + return e->epoll_fd; +} + +_public_ int sd_event_get_state(sd_event *e) { + assert_return(e, -EINVAL); + assert_return(!event_pid_changed(e), -ECHILD); + + return e->state; +} + +_public_ int sd_event_get_exit_code(sd_event *e, int *code) { + assert_return(e, -EINVAL); + assert_return(code, -EINVAL); + assert_return(!event_pid_changed(e), -ECHILD); + + if (!e->exit_requested) + return -ENODATA; + + *code = e->exit_code; + return 0; +} + +_public_ int sd_event_exit(sd_event *e, int code) { + assert_return(e, -EINVAL); + assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(e), -ECHILD); + + e->exit_requested = true; + e->exit_code = code; + + return 0; +} + +_public_ int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec) { + assert_return(e, -EINVAL); + assert_return(usec, -EINVAL); + assert_return(!event_pid_changed(e), -ECHILD); + assert_return(IN_SET(clock, + CLOCK_REALTIME, + CLOCK_REALTIME_ALARM, + CLOCK_MONOTONIC, + CLOCK_BOOTTIME, + CLOCK_BOOTTIME_ALARM), -EOPNOTSUPP); + + if (!dual_timestamp_is_set(&e->timestamp)) { + /* Implicitly fall back to now() if we never ran + * before and thus have no cached time. */ + *usec = now(clock); + return 1; + } + + switch (clock) { + + case CLOCK_REALTIME: + case CLOCK_REALTIME_ALARM: + *usec = e->timestamp.realtime; + break; + + case CLOCK_MONOTONIC: + *usec = e->timestamp.monotonic; + break; + + case CLOCK_BOOTTIME: + case CLOCK_BOOTTIME_ALARM: + *usec = e->timestamp_boottime; + break; + + default: + assert_not_reached("Unknown clock?"); + } + + return 0; +} + +_public_ int sd_event_default(sd_event **ret) { + + static thread_local sd_event *default_event = NULL; + sd_event *e = NULL; + int r; + + if (!ret) + return !!default_event; + + if (default_event) { + *ret = sd_event_ref(default_event); + return 0; + } + + r = sd_event_new(&e); + if (r < 0) + return r; + + e->default_event_ptr = &default_event; + e->tid = gettid(); + default_event = e; + + *ret = e; + return 1; +} + +#if 0 /* NM_IGNORED */ +_public_ int sd_event_get_tid(sd_event *e, pid_t *tid) { + assert_return(e, -EINVAL); + assert_return(tid, -EINVAL); + assert_return(!event_pid_changed(e), -ECHILD); + + if (e->tid != 0) { + *tid = e->tid; + return 0; + } + + return -ENXIO; +} + +_public_ int sd_event_set_watchdog(sd_event *e, int b) { + int r; + + assert_return(e, -EINVAL); + assert_return(!event_pid_changed(e), -ECHILD); + + if (e->watchdog == !!b) + return e->watchdog; + + if (b) { + struct epoll_event ev = {}; + + r = sd_watchdog_enabled(false, &e->watchdog_period); + if (r <= 0) + return r; + + /* Issue first ping immediately */ + sd_notify(false, "WATCHDOG=1"); + e->watchdog_last = now(CLOCK_MONOTONIC); + + e->watchdog_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC); + if (e->watchdog_fd < 0) + return -errno; + + r = arm_watchdog(e); + if (r < 0) + goto fail; + + ev.events = EPOLLIN; + ev.data.ptr = INT_TO_PTR(SOURCE_WATCHDOG); + + r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, e->watchdog_fd, &ev); + if (r < 0) { + r = -errno; + goto fail; + } + + } else { + if (e->watchdog_fd >= 0) { + epoll_ctl(e->epoll_fd, EPOLL_CTL_DEL, e->watchdog_fd, NULL); + e->watchdog_fd = safe_close(e->watchdog_fd); + } + } + + e->watchdog = !!b; + return e->watchdog; + +fail: + e->watchdog_fd = safe_close(e->watchdog_fd); + return r; +} + +_public_ int sd_event_get_watchdog(sd_event *e) { + assert_return(e, -EINVAL); + assert_return(!event_pid_changed(e), -ECHILD); + + return e->watchdog; +} +#endif /* NM_IGNORED */ diff --git a/src/systemd/src/libsystemd/sd-id128/sd-id128.c b/src/systemd/src/libsystemd/sd-id128/sd-id128.c index ea09d19e..01b805a1 100644 --- a/src/systemd/src/libsystemd/sd-id128/sd-id128.c +++ b/src/systemd/src/libsystemd/sd-id128/sd-id128.c @@ -155,7 +155,6 @@ _public_ int sd_id128_get_machine(sd_id128_t *ret) { return 0; } -#if 0 /* NM_IGNORED */ _public_ int sd_id128_get_boot(sd_id128_t *ret) { static thread_local sd_id128_t saved_boot_id; static thread_local bool saved_boot_id_valid = false; @@ -211,6 +210,7 @@ _public_ int sd_id128_get_boot(sd_id128_t *ret) { return 0; } +#if 0 /* NM_IGNORED */ _public_ int sd_id128_randomize(sd_id128_t *ret) { sd_id128_t t; int r; diff --git a/src/systemd/src/shared/dns-domain.c b/src/systemd/src/shared/dns-domain.c index 525ce7fb..e147637b 100644 --- a/src/systemd/src/shared/dns-domain.c +++ b/src/systemd/src/shared/dns-domain.c @@ -182,7 +182,7 @@ int dns_label_unescape_suffix(const char *name, const char **label_terminal, cha unsigned slashes = 0; for (y = terminal - 1; y >= name && *y == '\\'; y--) - slashes ++; + slashes++; if (slashes % 2 == 0) { /* The '.' was not escaped */ @@ -194,7 +194,7 @@ int dns_label_unescape_suffix(const char *name, const char **label_terminal, cha } } - terminal --; + terminal--; } r = dns_label_unescape(&name, dest, sz); @@ -333,7 +333,7 @@ int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded l = strlen(buffer); - /* Verify that the the result is not longer than one DNS label. */ + /* Verify that the result is not longer than one DNS label. */ if (l <= 0 || l > DNS_LABEL_MAX) return -EINVAL; if (l > decoded_max) @@ -1177,7 +1177,7 @@ int dns_name_skip(const char *a, unsigned n_labels, const char **ret) { assert(a); assert(ret); - for (; n_labels > 0; n_labels --) { + for (; n_labels > 0; n_labels--) { r = dns_name_parent(&a); if (r < 0) return r; diff --git a/src/systemd/src/shared/dns-domain.h b/src/systemd/src/shared/dns-domain.h index 2de3642c..af780f0b 100644 --- a/src/systemd/src/shared/dns-domain.h +++ b/src/systemd/src/shared/dns-domain.h @@ -1,3 +1,5 @@ +#pragma once + /*** This file is part of systemd. @@ -17,9 +19,6 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#pragma once - - #include <errno.h> #include <stdbool.h> #include <stddef.h> diff --git a/src/systemd/src/systemd/_sd-common.h b/src/systemd/src/systemd/_sd-common.h index 2d4e1f26..3bb886be 100644 --- a/src/systemd/src/systemd/_sd-common.h +++ b/src/systemd/src/systemd/_sd-common.h @@ -74,7 +74,7 @@ #endif #define _SD_DEFINE_POINTER_CLEANUP_FUNC(type, func) \ - static inline void func##p(type **p) { \ + static __inline__ void func##p(type **p) { \ if (*p) \ func(*p); \ } \ diff --git a/src/systemd/src/systemd/sd-dhcp-client.h b/src/systemd/src/systemd/sd-dhcp-client.h index 2b865a80..ef453705 100644 --- a/src/systemd/src/systemd/sd-dhcp-client.h +++ b/src/systemd/src/systemd/sd-dhcp-client.h @@ -84,9 +84,9 @@ enum { typedef struct sd_dhcp_client sd_dhcp_client; -typedef void (*sd_dhcp_client_cb_t)(sd_dhcp_client *client, int event, +typedef void (*sd_dhcp_client_callback_t)(sd_dhcp_client *client, int event, void *userdata); -int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_cb_t cb, +int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_callback_t cb, void *userdata); int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option); @@ -113,7 +113,7 @@ sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client); int sd_dhcp_client_new(sd_dhcp_client **ret); -int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event, int priority); +int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event, int64_t priority); int sd_dhcp_client_detach_event(sd_dhcp_client *client); sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client); diff --git a/src/systemd/src/systemd/sd-dhcp6-client.h b/src/systemd/src/systemd/sd-dhcp6-client.h index 96080608..1bedc941 100644 --- a/src/systemd/src/systemd/sd-dhcp6-client.h +++ b/src/systemd/src/systemd/sd-dhcp6-client.h @@ -76,10 +76,10 @@ enum { typedef struct sd_dhcp6_client sd_dhcp6_client; -typedef void (*sd_dhcp6_client_cb_t)(sd_dhcp6_client *client, int event, +typedef void (*sd_dhcp6_client_callback_t)(sd_dhcp6_client *client, int event, void *userdata); int sd_dhcp6_client_set_callback(sd_dhcp6_client *client, - sd_dhcp6_client_cb_t cb, void *userdata); + sd_dhcp6_client_callback_t cb, void *userdata); int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index); int sd_dhcp6_client_set_local_address(sd_dhcp6_client *client, const struct in6_addr *local_address); @@ -97,8 +97,7 @@ int sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret); int sd_dhcp6_client_stop(sd_dhcp6_client *client); int sd_dhcp6_client_start(sd_dhcp6_client *client); int sd_dhcp6_client_is_running(sd_dhcp6_client *client); -int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event, - int priority); +int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event, int64_t priority); int sd_dhcp6_client_detach_event(sd_dhcp6_client *client); sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client); sd_dhcp6_client *sd_dhcp6_client_ref(sd_dhcp6_client *client); diff --git a/src/systemd/src/systemd/sd-event.h b/src/systemd/src/systemd/sd-event.h index 1ea97e47..531ace1c 100644 --- a/src/systemd/src/systemd/sd-event.h +++ b/src/systemd/src/systemd/sd-event.h @@ -55,7 +55,7 @@ enum { SD_EVENT_RUNNING, SD_EVENT_EXITING, SD_EVENT_FINISHED, - SD_EVENT_PREPARING, + SD_EVENT_PREPARING }; enum { @@ -69,7 +69,11 @@ typedef int (*sd_event_handler_t)(sd_event_source *s, void *userdata); typedef int (*sd_event_io_handler_t)(sd_event_source *s, int fd, uint32_t revents, void *userdata); typedef int (*sd_event_time_handler_t)(sd_event_source *s, uint64_t usec, void *userdata); typedef int (*sd_event_signal_handler_t)(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata); +#if defined __USE_POSIX199309 || defined __USE_XOPEN_EXTENDED typedef int (*sd_event_child_handler_t)(sd_event_source *s, const siginfo_t *si, void *userdata); +#else +typedef void* sd_event_child_handler_t; +#endif int sd_event_default(sd_event **e); diff --git a/src/systemd/src/systemd/sd-id128.h b/src/systemd/src/systemd/sd-id128.h index a3bf5897..4dff0b9b 100644 --- a/src/systemd/src/systemd/sd-id128.h +++ b/src/systemd/src/systemd/sd-id128.h @@ -100,11 +100,11 @@ int sd_id128_get_boot(sd_id128_t *ret); ((x).bytes[15] & 15) >= 10 ? 'a' + ((x).bytes[15] & 15) - 10 : '0' + ((x).bytes[15] & 15), \ 0 }) -_sd_pure_ static inline int sd_id128_equal(sd_id128_t a, sd_id128_t b) { +_sd_pure_ static __inline__ int sd_id128_equal(sd_id128_t a, sd_id128_t b) { return memcmp(&a, &b, 16) == 0; } -_sd_pure_ static inline int sd_id128_is_null(sd_id128_t a) { +_sd_pure_ static __inline__ int sd_id128_is_null(sd_id128_t a) { return a.qwords[0] == 0 && a.qwords[1] == 0; } diff --git a/src/systemd/src/systemd/sd-ipv4acd.h b/src/systemd/src/systemd/sd-ipv4acd.h index 3a2219c8..9e3e14a3 100644 --- a/src/systemd/src/systemd/sd-ipv4acd.h +++ b/src/systemd/src/systemd/sd-ipv4acd.h @@ -37,12 +37,12 @@ enum { }; typedef struct sd_ipv4acd sd_ipv4acd; -typedef void (*sd_ipv4acd_cb_t)(sd_ipv4acd *ll, int event, void *userdata); +typedef void (*sd_ipv4acd_callback_t)(sd_ipv4acd *ll, int event, void *userdata); int sd_ipv4acd_detach_event(sd_ipv4acd *ll); -int sd_ipv4acd_attach_event(sd_ipv4acd *ll, sd_event *event, int priority); +int sd_ipv4acd_attach_event(sd_ipv4acd *ll, sd_event *event, int64_t priority); int sd_ipv4acd_get_address(sd_ipv4acd *ll, struct in_addr *address); -int sd_ipv4acd_set_callback(sd_ipv4acd *ll, sd_ipv4acd_cb_t cb, void *userdata); +int sd_ipv4acd_set_callback(sd_ipv4acd *ll, sd_ipv4acd_callback_t cb, void *userdata); int sd_ipv4acd_set_mac(sd_ipv4acd *ll, const struct ether_addr *addr); int sd_ipv4acd_set_index(sd_ipv4acd *ll, int interface_index); int sd_ipv4acd_set_address(sd_ipv4acd *ll, const struct in_addr *address); diff --git a/src/systemd/src/systemd/sd-ipv4ll.h b/src/systemd/src/systemd/sd-ipv4ll.h index 67c566fe..6fa38a22 100644 --- a/src/systemd/src/systemd/sd-ipv4ll.h +++ b/src/systemd/src/systemd/sd-ipv4ll.h @@ -36,12 +36,12 @@ enum { }; typedef struct sd_ipv4ll sd_ipv4ll; -typedef void (*sd_ipv4ll_cb_t)(sd_ipv4ll *ll, int event, void *userdata); +typedef void (*sd_ipv4ll_callback_t)(sd_ipv4ll *ll, int event, void *userdata); int sd_ipv4ll_detach_event(sd_ipv4ll *ll); -int sd_ipv4ll_attach_event(sd_ipv4ll *ll, sd_event *event, int priority); +int sd_ipv4ll_attach_event(sd_ipv4ll *ll, sd_event *event, int64_t priority); int sd_ipv4ll_get_address(sd_ipv4ll *ll, struct in_addr *address); -int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_cb_t cb, void *userdata); +int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_callback_t cb, void *userdata); int sd_ipv4ll_set_mac(sd_ipv4ll *ll, const struct ether_addr *addr); int sd_ipv4ll_set_index(sd_ipv4ll *ll, int interface_index); int sd_ipv4ll_set_address(sd_ipv4ll *ll, const struct in_addr *address); diff --git a/src/systemd/src/systemd/sd-lldp.h b/src/systemd/src/systemd/sd-lldp.h index ea952ef1..f7eff587 100644 --- a/src/systemd/src/systemd/sd-lldp.h +++ b/src/systemd/src/systemd/sd-lldp.h @@ -30,57 +30,69 @@ _SD_BEGIN_DECLARATIONS; -enum { - SD_LLDP_EVENT_UPDATE_INFO = 0, -}; - -enum { - SD_LLDP_DESTINATION_TYPE_NEAREST_BRIDGE, - SD_LLDP_DESTINATION_TYPE_NEAREST_NON_TPMR_BRIDGE, - SD_LLDP_DESTINATION_TYPE_NEAREST_CUSTOMER_BRIDGE, -}; - typedef struct sd_lldp sd_lldp; -typedef struct sd_lldp_packet sd_lldp_packet; +typedef struct sd_lldp_neighbor sd_lldp_neighbor; -typedef void (*sd_lldp_cb_t)(sd_lldp *lldp, int event, void *userdata); +typedef enum sd_lldp_event { + SD_LLDP_EVENT_ADDED = 'a', + SD_LLDP_EVENT_REMOVED = 'r', + SD_LLDP_EVENT_UPDATED = 'u', + SD_LLDP_EVENT_REFRESHED = 'f', +} sd_lldp_event; -int sd_lldp_new(int ifindex, const char *ifname, const struct ether_addr *mac, sd_lldp **ret); +typedef void (*sd_lldp_callback_t)(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n, void *userdata); + +int sd_lldp_new(sd_lldp **ret, int ifindex); sd_lldp* sd_lldp_unref(sd_lldp *lldp); int sd_lldp_start(sd_lldp *lldp); int sd_lldp_stop(sd_lldp *lldp); -int sd_lldp_attach_event(sd_lldp *lldp, sd_event *event, int priority); +int sd_lldp_attach_event(sd_lldp *lldp, sd_event *event, int64_t priority); int sd_lldp_detach_event(sd_lldp *lldp); -int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_cb_t cb, void *userdata); -int sd_lldp_save(sd_lldp *lldp, const char *file); - -int sd_lldp_packet_read_chassis_id(sd_lldp_packet *tlv, uint8_t *type, uint8_t **data, uint16_t *length); -int sd_lldp_packet_read_port_id(sd_lldp_packet *tlv, uint8_t *type, uint8_t **data, uint16_t *length); -int sd_lldp_packet_read_ttl(sd_lldp_packet *tlv, uint16_t *ttl); -int sd_lldp_packet_read_system_name(sd_lldp_packet *tlv, char **data, uint16_t *length); -int sd_lldp_packet_read_system_description(sd_lldp_packet *tlv, char **data, uint16_t *length); -int sd_lldp_packet_read_system_capability(sd_lldp_packet *tlv, uint16_t *data); -int sd_lldp_packet_read_port_description(sd_lldp_packet *tlv, char **data, uint16_t *length); - -/* IEEE 802.1 organizationally specific TLVs */ -int sd_lldp_packet_read_port_vlan_id(sd_lldp_packet *tlv, uint16_t *id); -int sd_lldp_packet_read_port_protocol_vlan_id(sd_lldp_packet *tlv, uint8_t *flags, uint16_t *id); -int sd_lldp_packet_read_vlan_name(sd_lldp_packet *tlv, uint16_t *vlan_id, char **name, uint16_t *length); -int sd_lldp_packet_read_management_vid(sd_lldp_packet *tlv, uint16_t *id); -int sd_lldp_packet_read_link_aggregation(sd_lldp_packet *tlv, uint8_t *status, uint32_t *id); - -sd_lldp_packet *sd_lldp_packet_ref(sd_lldp_packet *tlv); -sd_lldp_packet *sd_lldp_packet_unref(sd_lldp_packet *tlv); - -int sd_lldp_packet_get_destination_type(sd_lldp_packet *tlv, int *dest); - -int sd_lldp_get_packets(sd_lldp *lldp, sd_lldp_packet ***tlvs); +int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_callback_t cb, void *userdata); + +/* Controls how much and what to store in the neighbors database */ +int sd_lldp_set_neighbors_max(sd_lldp *lldp, uint64_t n); +int sd_lldp_match_capabilities(sd_lldp *lldp, uint16_t mask); +int sd_lldp_set_filter_address(sd_lldp *lldp, const struct ether_addr *address); + +int sd_lldp_get_neighbors(sd_lldp *lldp, sd_lldp_neighbor ***neighbors); + +int sd_lldp_neighbor_from_raw(sd_lldp_neighbor **ret, const void *raw, size_t raw_size); +sd_lldp_neighbor *sd_lldp_neighbor_ref(sd_lldp_neighbor *n); +sd_lldp_neighbor *sd_lldp_neighbor_unref(sd_lldp_neighbor *n); + +/* Access to LLDP frame metadata */ +int sd_lldp_neighbor_get_source_address(sd_lldp_neighbor *n, struct ether_addr* address); +int sd_lldp_neighbor_get_destination_address(sd_lldp_neighbor *n, struct ether_addr* address); +int sd_lldp_neighbor_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size); + +/* High-level, direct, parsed out field access. These fields exist at most once, hence may be queried directly. */ +int sd_lldp_neighbor_get_chassis_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size); +int sd_lldp_neighbor_get_chassis_id_as_string(sd_lldp_neighbor *n, const char **ret); +int sd_lldp_neighbor_get_port_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size); +int sd_lldp_neighbor_get_port_id_as_string(sd_lldp_neighbor *n, const char **ret); +int sd_lldp_neighbor_get_ttl(sd_lldp_neighbor *n, uint16_t *ret); +int sd_lldp_neighbor_get_system_name(sd_lldp_neighbor *n, const char **ret); +int sd_lldp_neighbor_get_system_description(sd_lldp_neighbor *n, const char **ret); +int sd_lldp_neighbor_get_port_description(sd_lldp_neighbor *n, const char **ret); +int sd_lldp_neighbor_get_system_capabilities(sd_lldp_neighbor *n, uint16_t *ret); +int sd_lldp_neighbor_get_enabled_capabilities(sd_lldp_neighbor *n, uint16_t *ret); + +/* Low-level, iterative TLV access. This is for evertyhing else, it iteratively goes through all available TLVs + * (including the ones covered with the calls above), and allows multiple TLVs for the same fields. */ +int sd_lldp_neighbor_tlv_rewind(sd_lldp_neighbor *n); +int sd_lldp_neighbor_tlv_next(sd_lldp_neighbor *n); +int sd_lldp_neighbor_tlv_get_type(sd_lldp_neighbor *n, uint8_t *type); +int sd_lldp_neighbor_tlv_is_type(sd_lldp_neighbor *n, uint8_t type); +int sd_lldp_neighbor_tlv_get_oui(sd_lldp_neighbor *n, uint8_t oui[3], uint8_t *subtype); +int sd_lldp_neighbor_tlv_is_oui(sd_lldp_neighbor *n, const uint8_t oui[3], uint8_t subtype); +int sd_lldp_neighbor_tlv_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_lldp, sd_lldp_unref); -_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_lldp_packet, sd_lldp_packet_unref); +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_lldp_neighbor, sd_lldp_neighbor_unref); _SD_END_DECLARATIONS; diff --git a/src/systemd/src/systemd/sd-ndisc.h b/src/systemd/src/systemd/sd-ndisc.h index 76294753..29bcbe8e 100644 --- a/src/systemd/src/systemd/sd-ndisc.h +++ b/src/systemd/src/systemd/sd-ndisc.h @@ -52,7 +52,7 @@ int sd_ndisc_set_callback(sd_ndisc *nd, int sd_ndisc_set_index(sd_ndisc *nd, int interface_index); int sd_ndisc_set_mac(sd_ndisc *nd, const struct ether_addr *mac_addr); -int sd_ndisc_attach_event(sd_ndisc *nd, sd_event *event, int priority); +int sd_ndisc_attach_event(sd_ndisc *nd, sd_event *event, int64_t priority); int sd_ndisc_detach_event(sd_ndisc *nd); sd_event *sd_ndisc_get_event(sd_ndisc *nd); diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am index a3447fbf..597f477f 100644 --- a/src/tests/Makefile.am +++ b/src/tests/Makefile.am @@ -117,6 +117,7 @@ test_wired_defname_LDADD = \ test_systemd_CFLAGS = \ "-I$(srcdir)/../" \ "-I$(srcdir)/../platform" \ + "-I$(srcdir)/../systemd" \ "-I$(srcdir)/../systemd/src/systemd" test_systemd_SOURCES = \ diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in index 9d67063e..8be2e8ce 100644 --- a/src/tests/Makefile.in +++ b/src/tests/Makefile.in @@ -867,6 +867,7 @@ test_wired_defname_LDADD = \ test_systemd_CFLAGS = \ "-I$(srcdir)/../" \ "-I$(srcdir)/../platform" \ + "-I$(srcdir)/../systemd" \ "-I$(srcdir)/../systemd/src/systemd" test_systemd_SOURCES = \ diff --git a/src/tests/config/test-config.c b/src/tests/config/test-config.c index 19306df7..d83ff4b5 100644 --- a/src/tests/config/test-config.c +++ b/src/tests/config/test-config.c @@ -343,7 +343,7 @@ test_config_no_auto_default (void) g_assert (!nm_config_get_no_auto_default_for_device (config, dev3)); g_assert (nm_config_get_no_auto_default_for_device (config, dev4)); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*config: update * (no-auto-default)*"); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*config: update * (no-auto-default)*"); nm_config_set_no_auto_default_for_device (config, dev3); g_test_assert_expected_messages (); @@ -556,9 +556,9 @@ _set_values_user (NMConfig *config, config_data_before = g_object_ref (nm_config_get_data (config)); if (expected_changes != NM_CONFIG_CHANGE_NONE) - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*config: update *"); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*config: update *"); else - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*config: signal SIGHUP (no changes from disk)*"); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*config: signal SIGHUP (no changes from disk)*"); nm_config_reload (config, SIGHUP); @@ -600,7 +600,7 @@ _set_values_intern (NMConfig *config, &config_changed_data); if (expected_changes != NM_CONFIG_CHANGE_NONE) - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*config: update *"); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*config: update *"); nm_config_set_values (config, keyfile_intern, TRUE, FALSE); @@ -863,15 +863,15 @@ test_config_signal (void) &expected); expected = NM_CONFIG_CHANGE_SIGUSR1; - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*config: signal SIGUSR1"); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*config: signal SIGUSR1"); nm_config_reload (config, SIGUSR1); expected = NM_CONFIG_CHANGE_SIGUSR2; - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*config: signal SIGUSR2"); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*config: signal SIGUSR2"); nm_config_reload (config, SIGUSR2); expected = NM_CONFIG_CHANGE_SIGHUP; - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*config: signal SIGHUP (no changes from disk)*"); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*config: signal SIGHUP (no changes from disk)*"); nm_config_reload (config, SIGHUP); @@ -884,7 +884,7 @@ test_config_signal (void) G_CALLBACK (_test_signal_config_changed_cb2), &expected); expected = NM_CONFIG_CHANGE_SIGUSR2; - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*config: signal SIGUSR2"); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*config: signal SIGUSR2"); nm_config_reload (config, SIGUSR2); g_signal_handlers_disconnect_by_func (config, _test_signal_config_changed_cb2, &expected); diff --git a/src/tests/test-general-with-expect.c b/src/tests/test-general-with-expect.c index 43595c8d..64b47bd3 100644 --- a/src/tests/test-general-with-expect.c +++ b/src/tests/test-general-with-expect.c @@ -304,7 +304,7 @@ test_nm_utils_kill_child (void) test_nm_utils_kill_child_sync_do ("test-s-2", pid2s, SIGTERM, 3000, TRUE, &expected_exit_47); /* send invalid signal. */ - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*kill child process 'test-s-3-0' (*): failed to send Unexpected signal: Invalid argument (22)"); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*kill child process 'test-s-3-0' (*): failed to send Unexpected signal: Invalid argument (22)"); test_nm_utils_kill_child_sync_do ("test-s-3-0", pid3s, -1, 0, FALSE, NULL); /* really kill pid3s */ @@ -314,7 +314,7 @@ test_nm_utils_kill_child (void) /* pid3s should not be a valid process, hence the call should fail. Note, that there * is a race here. */ - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*kill child process 'test-s-3-2' (*): failed due to unexpected return value -1 by waitpid (No child processes, 10) after sending no signal (0)"); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*kill child process 'test-s-3-2' (*): failed due to unexpected return value -1 by waitpid (No child processes, 10) after sending no signal (0)"); test_nm_utils_kill_child_sync_do ("test-s-3-2", pid3s, 0, 0, FALSE, NULL); g_test_expect_message ("NetworkManager", G_LOG_LEVEL_DEBUG, "*kill child process 'test-s-4' (*): waiting up to 1 milliseconds for process to terminate normally after sending SIGTERM (15)..."); @@ -340,7 +340,7 @@ test_nm_utils_kill_child (void) g_test_expect_message ("NetworkManager", G_LOG_LEVEL_DEBUG, "*kill child process 'test-a-2' (*): invoke callback: terminated normally with status 47"); test_nm_utils_kill_child_async_do ("test-a-2", pid2a, SIGTERM, 3000, TRUE, &expected_exit_47); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*kill child process 'test-a-3-0' (*): unexpected error sending Unexpected signal: Invalid argument (22)"); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*kill child process 'test-a-3-0' (*): unexpected error sending Unexpected signal: Invalid argument (22)"); g_test_expect_message ("NetworkManager", G_LOG_LEVEL_DEBUG, "*kill child process 'test-a-3-0' (*): invoke callback: killing child failed"); /* coverity[negative_returns] */ test_nm_utils_kill_child_async_do ("test-a-3-0", pid3a, -1, 1000 / 2, FALSE, NULL); @@ -351,7 +351,7 @@ test_nm_utils_kill_child (void) /* pid3a should not be a valid process, hence the call should fail. Note, that there * is a race here. */ - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*kill child process 'test-a-3-2' (*): failed due to unexpected return value -1 by waitpid (No child processes, 10) after sending no signal (0)"); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*kill child process 'test-a-3-2' (*): failed due to unexpected return value -1 by waitpid (No child processes, 10) after sending no signal (0)"); g_test_expect_message ("NetworkManager", G_LOG_LEVEL_DEBUG, "*kill child process 'test-a-3-2' (*): invoke callback: killing child failed"); test_nm_utils_kill_child_async_do ("test-a-3-2", pid3a, 0, 0, FALSE, NULL); diff --git a/src/tests/test-general.c b/src/tests/test-general.c index b8a51f2a..b2512590 100644 --- a/src/tests/test-general.c +++ b/src/tests/test-general.c @@ -1221,7 +1221,31 @@ test_nm_utils_strbuf_append (void) } } -/*******************************************/ +/*****************************************************************************/ + +static void +test_duplicate_decl_specifier (void) +{ + /* have some static variables, so that the result is certainly not optimized out. */ + static const int v_const[1] = { 1 }; + static int v_result[1] = { }; + const const int v2 = 3; + + /* Test that we don't get a compiler warning about duplicate const specifier. + * C99 allows that and it can easily happen in macros. */ + +#define TEST_MAX(a, b) \ + ({ \ + const typeof(a) _a = (a); \ + const typeof(b) _b = (b); \ + \ + (_a > _b ? _a : _b); \ + }) + + v_result[0] = TEST_MAX (v_const[0], nmtst_get_rand_int () % 5) + v2; +} + +/*****************************************************************************/ NMTST_DEFINE (); @@ -1254,6 +1278,7 @@ main (int argc, char **argv) g_test_add_func ("/general/nm_match_spec_interface_name", test_nm_match_spec_interface_name); g_test_add_func ("/general/nm_match_spec_match_config", test_nm_match_spec_match_config); + g_test_add_func ("/general/duplicate_decl_specifier", test_duplicate_decl_specifier); return g_test_run (); } diff --git a/src/tests/test-route-manager.c b/src/tests/test-route-manager.c index 742f4ee5..b32775da 100644 --- a/src/tests/test-route-manager.c +++ b/src/tests/test-route-manager.c @@ -76,15 +76,16 @@ setup_dev1_ip4 (int ifindex) /* Add some route outside of route manager. The route manager * should get rid of it upon sync. */ - nm_platform_ip4_route_add (NM_PLATFORM_GET, - route.ifindex, - NM_IP_CONFIG_SOURCE_USER, - nmtst_inet4_from_string ("9.0.0.0"), - 8, - INADDR_ANY, - 0, - 10, - route.mss); + if (!nm_platform_ip4_route_add (NM_PLATFORM_GET, + route.ifindex, + NM_IP_CONFIG_SOURCE_USER, + nmtst_inet4_from_string ("9.0.0.0"), + 8, + INADDR_ANY, + 0, + 10, + route.mss)) + g_assert_not_reached (); route.source = NM_IP_CONFIG_SOURCE_USER; inet_pton (AF_INET, "6.6.6.0", &route.network); @@ -421,14 +422,15 @@ setup_dev1_ip6 (int ifindex) /* Add some route outside of route manager. The route manager * should get rid of it upon sync. */ - nm_platform_ip6_route_add (NM_PLATFORM_GET, - ifindex, - NM_IP_CONFIG_SOURCE_USER, - *nmtst_inet6_from_string ("2001:db8:8088::"), - 48, - in6addr_any, - 10, - 0); + if (!nm_platform_ip6_route_add (NM_PLATFORM_GET, + ifindex, + NM_IP_CONFIG_SOURCE_USER, + *nmtst_inet6_from_string ("2001:db8:8088::"), + 48, + in6addr_any, + 10, + 0)) + g_assert_not_reached (); route = nmtst_platform_ip6_route_full ("2001:db8:8086::", 48, diff --git a/src/tests/test-systemd.c b/src/tests/test-systemd.c index 84ad95ba..936bff20 100644 --- a/src/tests/test-systemd.c +++ b/src/tests/test-systemd.c @@ -19,7 +19,11 @@ #include "nm-default.h" +#include "nm-sd.h" + #include "sd-dhcp-client.h" +#include "sd-lldp.h" +#include "sd-event.h" #include "nm-test-utils.h" @@ -40,6 +44,87 @@ test_dhcp_create (void) /*****************************************************************************/ +static void +test_lldp_create (void) +{ + sd_lldp *lldp = NULL; + int ifindex = 1; + int r; + + r = sd_lldp_new (&lldp, ifindex); + g_assert (r == 0); + g_assert (lldp); + + sd_lldp_unref (lldp); +} + +/*****************************************************************************/ + +typedef struct { + GMainLoop *mainloop; + sd_event_source *event_source; +} TestSdEventData; + +static int +_test_sd_event_timeout_cb (sd_event_source *s, uint64_t usec, void *userdata) +{ + TestSdEventData *user_data = userdata; + + g_assert (user_data); + g_assert (user_data->mainloop); + g_assert (user_data->event_source); + + user_data->event_source = sd_event_source_unref (user_data->event_source); + g_main_loop_quit (user_data->mainloop); + return 0; +} + +static void +test_sd_event (void) +{ + int repeat; + + for (repeat = 0; repeat < 2; repeat++) { + guint sd_id = 0; + int r; + int i, n; + sd_event *other_events[3] = { NULL }, *event = NULL; + TestSdEventData user_data = { 0 }; + + g_assert_cmpint (sd_event_default (NULL), ==, 0); + + for (i = 0, n = (nmtst_get_rand_int () % (G_N_ELEMENTS (other_events) + 1)); i < n; i++) { + r = sd_event_default (&other_events[i]); + g_assert (r >= 0 && other_events[i]); + } + + sd_id = nm_sd_event_attach_default (); + + r = sd_event_default (&event); + g_assert (r >= 0 && event); + + r = sd_event_add_time (event, &user_data.event_source, CLOCK_MONOTONIC, 1, 0, _test_sd_event_timeout_cb, &user_data); + g_assert (r >= 0 && user_data.event_source); + + user_data.mainloop = g_main_loop_new (NULL, FALSE); + g_main_loop_run (user_data.mainloop); + g_main_loop_unref (user_data.mainloop); + + g_assert (!user_data.event_source); + + event = sd_event_unref (event); + for (i = 0, n = (nmtst_get_rand_int () % (G_N_ELEMENTS (other_events) + 1)); i < n; i++) + other_events[i] = sd_event_unref (other_events[i]); + nm_clear_g_source (&sd_id); + for (i = 0, n = G_N_ELEMENTS (other_events); i < n; i++) + other_events[i] = sd_event_unref (other_events[i]); + + g_assert_cmpint (sd_event_default (NULL), ==, 0); + } +} + +/*****************************************************************************/ + NMTST_DEFINE (); int @@ -48,6 +133,8 @@ main (int argc, char **argv) nmtst_init_assert_logging (&argc, &argv, "INFO", "ALL"); g_test_add_func ("/systemd/dhcp/create", test_dhcp_create); + g_test_add_func ("/systemd/lldp/create", test_lldp_create); + g_test_add_func ("/systemd/sd-event", test_sd_event); return g_test_run (); } diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c index 653b9972..cbc7c69d 100644 --- a/src/vpn-manager/nm-vpn-connection.c +++ b/src/vpn-manager/nm-vpn-connection.c @@ -196,7 +196,7 @@ __LOG_create_prefix (char *buf, NMVpnConnection *self) "]", _NMLOG_PREFIX_NAME, self, - con ? "," : "--", con ? str_if_set (nm_connection_get_uuid (con), "??") : "", + con ? "," : "--", con ? (nm_connection_get_uuid (con) ?: "??") : "", con ? "," : "", NM_PRINT_FMT_QUOTED (id, "\"", id, "\"", con ? "??" : ""), priv->ip_ifindex, priv->ip_iface ? ":" : "", NM_PRINT_FMT_QUOTED (priv->ip_iface, "(", priv->ip_iface, ")", "") @@ -319,14 +319,25 @@ _get_applied_connection (NMVpnConnection *connection) } static void +disconnect_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) +{ + g_dbus_proxy_call_finish (proxy, result, NULL); + g_object_unref (user_data); +} + +static void call_plugin_disconnect (NMVpnConnection *self) { NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self); - if (priv->proxy) { - g_dbus_proxy_call (priv->proxy, "Disconnect", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); - g_clear_object (&priv->proxy); - } + g_dbus_proxy_call (priv->proxy, + "Disconnect", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + priv->cancellable, + (GAsyncReadyCallback) disconnect_cb, + g_object_ref (self)); } static void @@ -1934,7 +1945,7 @@ nm_vpn_service_daemon_exec (NMVpnConnection *self, GError **error) if (success) { _LOGI ("Started the VPN service, PID %ld", (long int) pid); - priv->start_timeout = g_timeout_add_seconds (5, _daemon_exec_timeout, g_object_ref (self)); + priv->start_timeout = g_timeout_add_seconds (5, _daemon_exec_timeout, self); } else { g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, @@ -2224,8 +2235,8 @@ get_secrets_cb (NMSettingsConnection *connection, return; if (error && priv->secrets_idx >= SECRETS_REQ_NEW) { - _LOGE ("Failed to request VPN secrets #%d: (%d) %s", - priv->secrets_idx + 1, error->code, error->message); + _LOGE ("Failed to request VPN secrets #%d: %s", + priv->secrets_idx + 1, error->message); _set_vpn_state (self, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS, FALSE); return; } @@ -2390,6 +2401,8 @@ dispose (GObject *object) NMVpnConnection *self = NM_VPN_CONNECTION (object); NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self); + nm_clear_g_source (&priv->start_timeout); + g_clear_pointer (&priv->connect_hash, g_variant_unref); nm_clear_g_source (&priv->connect_timeout); |