summary refs log tree commit diff
path: root/src/dhcp-manager
diff options
context:
space:
mode:
Diffstat (limited to 'src/dhcp-manager')
-rw-r--r--src/dhcp-manager/Makefile.am5
-rw-r--r--src/dhcp-manager/Makefile.in8
-rw-r--r--src/dhcp-manager/nm-dhcp-helper-api.h36
-rw-r--r--src/dhcp-manager/nm-dhcp-helper.c149
-rw-r--r--src/dhcp-manager/nm-dhcp-listener.c192
-rw-r--r--src/dhcp-manager/nm-dhcp-listener.h4
-rw-r--r--src/dhcp-manager/tests/Makefile.in2
7 files changed, 305 insertions, 91 deletions
diff --git a/src/dhcp-manager/Makefile.am b/src/dhcp-manager/Makefile.am
index b4590b4b..42954127 100644
--- a/src/dhcp-manager/Makefile.am
+++ b/src/dhcp-manager/Makefile.am
@@ -1,6 +1,9 @@
 libexec_PROGRAMS = nm-dhcp-helper
 
-nm_dhcp_helper_SOURCES = nm-dhcp-helper.c
+nm_dhcp_helper_SOURCES = \
+	nm-dhcp-helper.c \
+	nm-dhcp-helper-api.h \
+	$(NULL)
 
 nm_dhcp_helper_CPPFLAGS = \
 	$(GLIB_CFLAGS) \
diff --git a/src/dhcp-manager/Makefile.in b/src/dhcp-manager/Makefile.in
index dcb45183..5309cde6 100644
--- a/src/dhcp-manager/Makefile.in
+++ b/src/dhcp-manager/Makefile.in
@@ -94,7 +94,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \
 	$(top_srcdir)/m4/ax_lib_readline.m4 \
 	$(top_srcdir)/m4/compiler_options.m4 \
-	$(top_srcdir)/m4/gettext.m4 \
+	$(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \
 	$(top_srcdir)/m4/gnome-code-coverage.m4 \
 	$(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \
 	$(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \
@@ -456,7 +456,11 @@ with_dhcpcd = @with_dhcpcd@
 with_netconfig = @with_netconfig@
 with_resolvconf = @with_resolvconf@
 with_valgrind = @with_valgrind@
-nm_dhcp_helper_SOURCES = nm-dhcp-helper.c
+nm_dhcp_helper_SOURCES = \
+	nm-dhcp-helper.c \
+	nm-dhcp-helper-api.h \
+	$(NULL)
+
 nm_dhcp_helper_CPPFLAGS = \
 	$(GLIB_CFLAGS) \
 	-I$(top_srcdir)/shared \
diff --git a/src/dhcp-manager/nm-dhcp-helper-api.h b/src/dhcp-manager/nm-dhcp-helper-api.h
new file mode 100644
index 00000000..a3eb171d
--- /dev/null
+++ b/src/dhcp-manager/nm-dhcp-helper-api.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2016 Red Hat, Inc.
+ */
+
+#ifndef __NM_DHCP_HELPER_API_H__
+#define __NM_DHCP_HELPER_API_H__
+
+/******************************************************************************/
+
+#define NM_DHCP_CLIENT_DBUS_IFACE "org.freedesktop.nm_dhcp_client"
+
+#define NM_DHCP_HELPER_SERVER_BUS_NAME          "org.freedesktop.nm_dhcp_server"
+#define NM_DHCP_HELPER_SERVER_OBJECT_PATH       "/org/freedesktop/nm_dhcp_server"
+#define NM_DHCP_HELPER_SERVER_INTERFACE_NAME    "org.freedesktop.nm_dhcp_server"
+#define NM_DHCP_HELPER_SERVER_METHOD_NOTIFY     "Notify"
+
+/******************************************************************************/
+
+#endif /* __NM_DHCP_HELPER_API_H__ */
diff --git a/src/dhcp-manager/nm-dhcp-helper.c b/src/dhcp-manager/nm-dhcp-helper.c
index 7667084d..9c6f69b8 100644
--- a/src/dhcp-manager/nm-dhcp-helper.c
+++ b/src/dhcp-manager/nm-dhcp-helper.c
@@ -25,7 +25,42 @@
 #include <string.h>
 #include <signal.h>
 
-#define NM_DHCP_CLIENT_DBUS_IFACE   "org.freedesktop.nm_dhcp_client"
+#include "nm-utils/nm-vpn-plugin-macros.h"
+
+#include "nm-dhcp-helper-api.h"
+
+/*****************************************************************************/
+
+#ifdef NM_MORE_LOGGING
+#define _NMLOG_ENABLED(level) TRUE
+#else
+#define _NMLOG_ENABLED(level) ((level) <= LOG_ERR)
+#endif
+
+#define _NMLOG(always_enabled, level, ...) \
+	G_STMT_START { \
+		if ((always_enabled) || _NMLOG_ENABLED (level)) { \
+			GTimeVal _tv; \
+			\
+			g_get_current_time (&_tv); \
+			g_print ("nm-dhcp-helper[%ld] %-7s [%ld.%04ld] " _NM_UTILS_MACRO_FIRST (__VA_ARGS__) "\n", \
+			         (long) getpid (), \
+			         nm_utils_syslog_to_str (level), \
+			         _tv.tv_sec, _tv.tv_usec / 100 \
+			         _NM_UTILS_MACRO_REST (__VA_ARGS__)); \
+		} \
+	} G_STMT_END
+
+#define _LOGD(...) _NMLOG(TRUE,  LOG_INFO,    __VA_ARGS__)
+#define _LOGI(...) _NMLOG(TRUE,  LOG_NOTICE,  __VA_ARGS__)
+#define _LOGW(...) _NMLOG(TRUE,  LOG_WARNING, __VA_ARGS__)
+#define _LOGE(...) _NMLOG(TRUE,  LOG_ERR,     __VA_ARGS__)
+
+#define _LOGd(...) _NMLOG(FALSE, LOG_INFO,    __VA_ARGS__)
+#define _LOGi(...) _NMLOG(FALSE, LOG_NOTICE,  __VA_ARGS__)
+#define _LOGw(...) _NMLOG(FALSE, LOG_WARNING, __VA_ARGS__)
+
+/*****************************************************************************/
 
 static const char * ignore[] = {"PATH", "SHLVL", "_", "PWD", "dhc_dbus", NULL};
 
@@ -70,30 +105,34 @@ build_signal_parameters (void)
 		g_free (name);
 	}
 
-	return g_variant_new ("(a{sv})", &builder);
+	return g_variant_ref_sink (g_variant_new ("(a{sv})", &builder));
 }
 
 static void
-fatal_error (void)
+kill_pid (void)
 {
-	const char *pid_str = getenv ("pid");
-	int pid = 0;
+	const char *pid_str;
+	pid_t pid = 0;
 
+	pid_str = getenv ("pid");
 	if (pid_str)
 		pid = strtol (pid_str, NULL, 10);
 	if (pid) {
-		g_printerr ("Fatal error occured, killing dhclient instance with pid %d.\n", pid);
+		_LOGI ("a fatal error occured, kill dhclient instance with pid %d\n", pid);
 		kill (pid, SIGTERM);
 	}
-
-	exit (1);
 }
 
 int
 main (int argc, char *argv[])
 {
-	GDBusConnection *connection;
-	GError *error = NULL;
+	gs_unref_object GDBusConnection *connection = NULL;
+	gs_free_error GError *error = NULL;
+	gs_unref_variant GVariant *parameters = NULL;
+	gs_unref_variant GVariant *result = NULL;
+	gboolean success = FALSE;
+	guint try_count = 0;
+	gint64 time_end;
 
 	nm_g_type_init ();
 
@@ -102,33 +141,81 @@ main (int argc, char *argv[])
 	                                                     NULL, NULL, &error);
 	if (!connection) {
 		g_dbus_error_strip_remote_error (error);
-		g_printerr ("Error: could not connect to NetworkManager D-Bus socket: %s\n",
-		            error->message);
-		g_error_free (error);
-		fatal_error ();
+		_LOGE ("could not connect to NetworkManager D-Bus socket: %s",
+		       error->message);
+		goto out;
 	}
 
-	if (!g_dbus_connection_emit_signal (connection,
-	                                    NULL,
-	                                    "/",
-	                                    NM_DHCP_CLIENT_DBUS_IFACE,
-	                                    "Event",
-	                                    build_signal_parameters (),
-	                                    &error)) {
-		g_dbus_error_strip_remote_error (error);
-		g_printerr ("Error: Could not send DHCP Event signal: %s\n", error->message);
-		g_error_free (error);
-		fatal_error ();
-	}
+	parameters = build_signal_parameters ();
+
+	time_end = g_get_monotonic_time () + (200 * 1000L); /* retry for at most 200 milliseconds */
+
+do_notify:
+	try_count++;
+	result = g_dbus_connection_call_sync (connection,
+	                                      NULL,
+	                                      NM_DHCP_HELPER_SERVER_OBJECT_PATH,
+	                                      NM_DHCP_HELPER_SERVER_INTERFACE_NAME,
+	                                      NM_DHCP_HELPER_SERVER_METHOD_NOTIFY,
+	                                      parameters,
+	                                      NULL,
+	                                      G_DBUS_CALL_FLAGS_NONE,
+	                                      1000,
+	                                      NULL,
+	                                      &error);
+
+	if (!result) {
+		gs_free char *s_err = NULL;
+
+		s_err = g_dbus_error_get_remote_error (error);
+		if (NM_IN_STRSET (s_err, "org.freedesktop.DBus.Error.UnknownMethod")) {
+			gint64 remaining_time = time_end - g_get_monotonic_time ();
+
+			/* I am not sure that a race can actually happen, as we register the object
+			 * on the server side during GDBusServer:new-connection signal.
+			 *
+			 * However, there was also a race for subscribing to an event, so let's just
+			 * do some retry. */
+			if (remaining_time > 0) {
+				_LOGi ("failure to call notify: %s (retry %u)", error->message, try_count);
+				g_usleep (NM_MIN (NM_CLAMP ((gint64) (100L * (1L << try_count)), 5000, 25000), remaining_time));
+				g_clear_error (&error);
+				goto do_notify;
+			}
+		}
+		_LOGW ("failure to call notify: %s (try signal via Event)", error->message);
+		g_clear_error (&error);
+
+		/* for backward compatibilty, try to emit the signal. There is no stable
+		 * API between the dhcp-helper and NetworkManager. However, while upgrading
+		 * the NetworkManager package, a newer helper might want to notify an
+		 * older server, which still uses the "Event". */
+		if (!g_dbus_connection_emit_signal (connection,
+		                                    NULL,
+		                                    "/",
+		                                    NM_DHCP_CLIENT_DBUS_IFACE,
+		                                    "Event",
+		                                    parameters,
+		                                    &error)) {
+			g_dbus_error_strip_remote_error (error);
+			_LOGE ("could not send DHCP Event signal: %s", error->message);
+			goto out;
+		}
+		/* We were able to send the asynchronous Event. Consider that a success. */
+		success = TRUE;
+	} else
+		success = TRUE;
 
 	if (!g_dbus_connection_flush_sync (connection, NULL, &error)) {
 		g_dbus_error_strip_remote_error (error);
-		g_printerr ("Error: Could not flush D-Bus connection: %s\n", error->message);
-		g_error_free (error);
-		fatal_error ();
+		_LOGE ("could not flush D-Bus connection: %s", error->message);
+		success = FALSE;
+		goto out;
 	}
 
-	g_object_unref (connection);
-	return 0;
+out:
+	if (!success)
+		kill_pid ();
+	return success ? EXIT_SUCCESS : EXIT_FAILURE;
 }
 
diff --git a/src/dhcp-manager/nm-dhcp-listener.c b/src/dhcp-manager/nm-dhcp-listener.c
index eadff3ec..0df41973 100644
--- a/src/dhcp-manager/nm-dhcp-listener.c
+++ b/src/dhcp-manager/nm-dhcp-listener.c
@@ -13,12 +13,14 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- * Copyright 2014 Red Hat, Inc.
+ * Copyright 2014 - 2016 Red Hat, Inc.
  *
  */
 
 #include "nm-default.h"
 
+#include "nm-dhcp-listener.h"
+
 #include <sys/socket.h>
 #include <sys/wait.h>
 #include <signal.h>
@@ -27,25 +29,31 @@
 #include <errno.h>
 #include <unistd.h>
 
-#include "nm-dhcp-listener.h"
+#include "nm-dhcp-helper-api.h"
 #include "nm-core-internal.h"
 #include "nm-bus-manager.h"
 #include "NetworkManagerUtils.h"
 
-#define NM_DHCP_CLIENT_DBUS_IFACE "org.freedesktop.nm_dhcp_client"
 #define PRIV_SOCK_PATH            NMRUNDIR "/private-dhcp"
 #define PRIV_SOCK_TAG             "dhcp"
 
+/*****************************************************************************/
+
 typedef struct {
 	NMBusManager *      dbus_mgr;
 	gulong              new_conn_id;
 	gulong              dis_conn_id;
-	GHashTable *        signal_handlers;
+	GHashTable *        connections;
 } NMDhcpListenerPrivate;
 
-#define NM_DHCP_LISTENER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DHCP_LISTENER, NMDhcpListenerPrivate))
+struct _NMDhcpListener {
+	GObject parent;
+	NMDhcpListenerPrivate _priv;
+};
 
-G_DEFINE_TYPE (NMDhcpListener, nm_dhcp_listener, G_TYPE_OBJECT)
+struct _NMDhcpListenerClass {
+	GObjectClass parent_class;
+};
 
 enum {
 	EVENT,
@@ -53,7 +61,30 @@ enum {
 };
 static guint signals[LAST_SIGNAL] = { 0 };
 
-/***************************************************/
+G_DEFINE_TYPE (NMDhcpListener, nm_dhcp_listener, G_TYPE_OBJECT)
+
+#define NM_DHCP_LISTENER_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMDhcpListener, NM_IS_DHCP_LISTENER)
+
+NM_DEFINE_SINGLETON_GETTER (NMDhcpListener, nm_dhcp_listener_get, NM_TYPE_DHCP_LISTENER);
+
+/*****************************************************************************/
+
+#define _NMLOG_PREFIX_NAME    "dhcp-listener"
+#define _NMLOG_DOMAIN         LOGD_DHCP
+#define _NMLOG(level, ...) \
+    G_STMT_START { \
+        const NMDhcpListener *_self = (self); \
+        char _prefix[64]; \
+        \
+        nm_log ((level), (_NMLOG_DOMAIN), \
+                "%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
+                (_self != singleton_instance \
+                    ? nm_sprintf_buf (_prefix, "%s[%p]", _NMLOG_PREFIX_NAME, _self) \
+                    : _NMLOG_PREFIX_NAME )\
+                _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
+    } G_STMT_END
+
+/*****************************************************************************/
 
 static char *
 get_option (GVariant *options, const char *key)
@@ -88,13 +119,14 @@ get_option (GVariant *options, const char *key)
 }
 
 static void
-handle_event (GDBusConnection  *connection,
-              const char       *sender_name,
-              const char       *object_path,
-              const char       *interface_name,
-              const char       *signal_name,
-              GVariant         *parameters,
-              gpointer          user_data)
+_method_call (GDBusConnection *connection,
+              const char *sender,
+              const char *object_path,
+              const char *interface_name,
+              const char *method_name,
+              GVariant *parameters,
+              GDBusMethodInvocation *invocation,
+              gpointer user_data)
 {
 	NMDhcpListener *self = NM_DHCP_LISTENER (user_data);
 	char *iface = NULL;
@@ -104,27 +136,31 @@ handle_event (GDBusConnection  *connection,
 	gboolean handled = FALSE;
 	GVariant *options;
 
+	if (!nm_streq0 (interface_name, NM_DHCP_HELPER_SERVER_INTERFACE_NAME))
+		g_return_if_reached ();
+	if (!nm_streq0 (method_name, NM_DHCP_HELPER_SERVER_METHOD_NOTIFY))
+		g_return_if_reached ();
 	if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(a{sv})")))
-		return;
+		g_return_if_reached ();
 
 	g_variant_get (parameters, "(@a{sv})", &options);
 
 	iface = get_option (options, "interface");
 	if (iface == NULL) {
-		nm_log_warn (LOGD_DHCP, "dhcp-event: didn't have associated interface.");
+		_LOGW ("dhcp-event: didn't have associated interface.");
 		goto out;
 	}
 
 	pid_str = get_option (options, "pid");
 	pid = _nm_utils_ascii_str_to_int64 (pid_str, 10, 0, G_MAXINT32, -1);
 	if (pid == -1) {
-		nm_log_warn (LOGD_DHCP, "dhcp-event: couldn't convert PID '%s' to an integer", pid_str ? pid_str : "(null)");
+		_LOGW ("dhcp-event: couldn't convert PID '%s' to an integer", pid_str ? pid_str : "(null)");
 		goto out;
 	}
 
 	reason = get_option (options, "reason");
 	if (reason == NULL) {
-		nm_log_warn (LOGD_DHCP, "dhcp-event: (pid %d) DHCP event didn't have a reason", pid);
+		_LOGW ("dhcp-event: (pid %d) DHCP event didn't have a reason", pid);
 		goto out;
 	}
 
@@ -132,9 +168,9 @@ handle_event (GDBusConnection  *connection,
 	if (!handled) {
 		if (g_ascii_strcasecmp (reason, "RELEASE") == 0) {
 			/* Ignore event when the dhcp client gets killed and we receive its last message */
-			nm_log_dbg (LOGD_DHCP, "dhcp-event: (pid %d) unhandled RELEASE DHCP event for interface %s", pid, iface);
+			_LOGD ("dhcp-event: (pid %d) unhandled RELEASE DHCP event for interface %s", pid, iface);
 		} else
-			nm_log_warn (LOGD_DHCP, "dhcp-event: (pid %d) unhandled DHCP event for interface %s", pid, iface);
+			_LOGW ("dhcp-event: (pid %d) unhandled DHCP event for interface %s", pid, iface);
 	}
 
 out:
@@ -142,6 +178,57 @@ out:
 	g_free (pid_str);
 	g_free (reason);
 	g_variant_unref (options);
+	g_dbus_method_invocation_return_value (invocation, NULL);
+}
+
+static guint
+_dbus_connection_register_object (NMDhcpListener *self,
+                                  GDBusConnection *connection,
+                                  GError **error)
+{
+	static GDBusArgInfo arg_info_notify_in = {
+		.ref_count = -1,
+		.name = "data",
+		.signature = "a{sv}",
+		.annotations = NULL,
+	};
+	static GDBusArgInfo *arg_infos_notify[] = {
+		&arg_info_notify_in,
+		NULL,
+	};
+	static GDBusMethodInfo method_info_notify = {
+		.ref_count = -1,
+		.name = NM_DHCP_HELPER_SERVER_METHOD_NOTIFY,
+		.in_args = arg_infos_notify,
+		.out_args = NULL,
+		.annotations = NULL,
+	};
+	static GDBusMethodInfo *method_infos[] = {
+		&method_info_notify,
+		NULL,
+	};
+	static GDBusInterfaceInfo interface_info = {
+		.ref_count = -1,
+		.name = NM_DHCP_HELPER_SERVER_INTERFACE_NAME,
+		.methods = method_infos,
+		.signals = NULL,
+		.properties = NULL,
+		.annotations = NULL,
+	};
+
+	static GDBusInterfaceVTable interface_vtable = {
+		.method_call = _method_call,
+		.get_property = NULL,
+		.set_property = NULL,
+	};
+
+	return g_dbus_connection_register_object (connection,
+	                                          NM_DHCP_HELPER_SERVER_OBJECT_PATH,
+	                                          &interface_info,
+	                                          &interface_vtable,
+	                                          self,
+	                                          NULL,
+	                                          error);
 }
 
 static void
@@ -151,17 +238,20 @@ new_connection_cb (NMBusManager *mgr,
                    NMDhcpListener *self)
 {
 	NMDhcpListenerPrivate *priv = NM_DHCP_LISTENER_GET_PRIVATE (self);
-	guint id;
+	guint registration_id;
+	GError *error = NULL;
+
+	/* it is important to register the object during the new-connection signal,
+	 * as this avoids races with the connecting object. */
+	registration_id = _dbus_connection_register_object (self, connection, &error);
+	if (!registration_id) {
+		_LOGE ("failure to register %s for connection %p: %s",
+		       NM_DHCP_HELPER_SERVER_OBJECT_PATH, connection, error->message);
+		g_error_free (error);
+		return;
+	}
 
-	id = g_dbus_connection_signal_subscribe (connection,
-	                                         NULL,
-	                                         NM_DHCP_CLIENT_DBUS_IFACE,
-	                                         "Event",
-	                                         NULL,
-	                                         NULL,
-	                                         G_DBUS_SIGNAL_FLAGS_NONE,
-	                                         handle_event, self, NULL);
-	g_hash_table_insert (priv->signal_handlers, connection, GUINT_TO_POINTER (id));
+	g_hash_table_insert (priv->connections, connection, GUINT_TO_POINTER (registration_id));
 }
 
 static void
@@ -172,24 +262,22 @@ dis_connection_cb (NMBusManager *mgr,
 	NMDhcpListenerPrivate *priv = NM_DHCP_LISTENER_GET_PRIVATE (self);
 	guint id;
 
-	id = GPOINTER_TO_UINT (g_hash_table_lookup (priv->signal_handlers, connection));
+	id = GPOINTER_TO_UINT (g_hash_table_lookup (priv->connections, connection));
 	if (id) {
-		g_dbus_connection_signal_unsubscribe (connection, id);
-		g_hash_table_remove (priv->signal_handlers, connection);
+		g_dbus_connection_unregister_object (connection, id);
+		g_hash_table_remove (priv->connections, connection);
 	}
 }
 
 /***************************************************/
 
-NM_DEFINE_SINGLETON_GETTER (NMDhcpListener, nm_dhcp_listener_get, NM_TYPE_DHCP_LISTENER);
-
 static void
 nm_dhcp_listener_init (NMDhcpListener *self)
 {
 	NMDhcpListenerPrivate *priv = NM_DHCP_LISTENER_GET_PRIVATE (self);
 
-	/* Maps GDBusConnection :: GDBusProxy */
-	priv->signal_handlers = g_hash_table_new (NULL, NULL);
+	/* Maps GDBusConnection :: signal-id */
+	priv->connections = g_hash_table_new (NULL, NULL);
 
 	priv->dbus_mgr = nm_bus_manager_get ();
 
@@ -208,13 +296,13 @@ nm_dhcp_listener_init (NMDhcpListener *self)
 static void
 dispose (GObject *object)
 {
-	NMDhcpListenerPrivate *priv = NM_DHCP_LISTENER_GET_PRIVATE (object);
+	NMDhcpListenerPrivate *priv = NM_DHCP_LISTENER_GET_PRIVATE ((NMDhcpListener *) object);
 
 	nm_clear_g_signal_handler (priv->dbus_mgr, &priv->new_conn_id);
 	nm_clear_g_signal_handler (priv->dbus_mgr, &priv->dis_conn_id);
 	priv->dbus_mgr = NULL;
 
-	g_clear_pointer (&priv->signal_handlers, g_hash_table_destroy);
+	g_clear_pointer (&priv->connections, g_hash_table_destroy);
 
 	G_OBJECT_CLASS (nm_dhcp_listener_parent_class)->dispose (object);
 }
@@ -224,22 +312,18 @@ nm_dhcp_listener_class_init (NMDhcpListenerClass *listener_class)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (listener_class);
 
-	g_type_class_add_private (listener_class, sizeof (NMDhcpListenerPrivate));
-
-	/* virtual methods */
 	object_class->dispose = dispose;
 
-	/* signals */
 	signals[EVENT] =
-		g_signal_new (NM_DHCP_LISTENER_EVENT,
-		              G_OBJECT_CLASS_TYPE (object_class),
-		              G_SIGNAL_RUN_LAST, 0,
-		              g_signal_accumulator_true_handled,
-		              NULL, NULL,
-		              G_TYPE_BOOLEAN,     /* listeners return TRUE if handled */
-		              4,
-		              G_TYPE_STRING,      /* iface */
-		              G_TYPE_INT,         /* pid */
-		              G_TYPE_VARIANT,     /* options */
-		              G_TYPE_STRING);     /* reason */
+	    g_signal_new (NM_DHCP_LISTENER_EVENT,
+	                  G_OBJECT_CLASS_TYPE (object_class),
+	                  G_SIGNAL_RUN_LAST, 0,
+	                  g_signal_accumulator_true_handled,
+	                  NULL, NULL,
+	                  G_TYPE_BOOLEAN,     /* listeners return TRUE if handled */
+	                  4,
+	                  G_TYPE_STRING,      /* iface */
+	                  G_TYPE_INT,         /* pid */
+	                  G_TYPE_VARIANT,     /* options */
+	                  G_TYPE_STRING);     /* reason */
 }
diff --git a/src/dhcp-manager/nm-dhcp-listener.h b/src/dhcp-manager/nm-dhcp-listener.h
index ff31fe34..3018b97a 100644
--- a/src/dhcp-manager/nm-dhcp-listener.h
+++ b/src/dhcp-manager/nm-dhcp-listener.h
@@ -26,8 +26,8 @@
 
 #define NM_DHCP_LISTENER_EVENT "event"
 
-typedef GObject NMDhcpListener;
-typedef GObjectClass NMDhcpListenerClass;
+typedef struct _NMDhcpListener NMDhcpListener;
+typedef struct _NMDhcpListenerClass NMDhcpListenerClass;
 
 GType nm_dhcp_listener_get_type (void);
 
diff --git a/src/dhcp-manager/tests/Makefile.in b/src/dhcp-manager/tests/Makefile.in
index 1ce288ba..3f5f1466 100644
--- a/src/dhcp-manager/tests/Makefile.in
+++ b/src/dhcp-manager/tests/Makefile.in
@@ -95,7 +95,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \
 	$(top_srcdir)/m4/ax_lib_readline.m4 \
 	$(top_srcdir)/m4/compiler_options.m4 \
-	$(top_srcdir)/m4/gettext.m4 \
+	$(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \
 	$(top_srcdir)/m4/gnome-code-coverage.m4 \
 	$(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \
 	$(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \