Commit 7f6e39ec authored by Dan Winship's avatar Dan Winship

dhcp-manager: port to gdbus

The existing code was somewhat confusing because it used
string->GValue hash tables in some places, and string->string hash
tables in other places. In the new version, the string->GValue hash
tables become GVariants, but the string->string hash tables stay as
hash tables, so you can tell them apart more easily.
parent 8f36727a
......@@ -12,15 +12,3 @@ nm_dhcp_helper_CPPFLAGS = \
-DNMRUNDIR=\"$(nmrundir)\"
nm_dhcp_helper_LDADD = $(GLIB_LIBS)
# FIXME: remove when dbus-glib >= 0.100 or GDBus is required
dhcp_helper_conf = nm-dhcp-helper.conf
if !HAVE_DBUS_GLIB_100
dbusservicedir = $(DBUS_SYS_DIR)
dbusservice_DATA = $(dhcp_helper_conf)
endif
EXTRA_DIST = $(dhcp_helper_conf)
......@@ -31,7 +31,6 @@
#include "nm-default.h"
#include "NetworkManagerUtils.h"
#include "nm-utils.h"
#include "nm-dbus-glib-types.h"
#include "nm-dhcp-client.h"
#include "nm-dhcp-utils.h"
#include "nm-platform.h"
......@@ -648,21 +647,25 @@ nm_dhcp_client_stop (NMDhcpClient *self, gboolean release)
/********************************************/
static char *
garray_to_string (GArray *array, const char *key)
bytearray_variant_to_string (GVariant *value, const char *key)
{
const guint8 *array;
gsize length;
GString *str;
int i;
unsigned char c;
char *converted = NULL;
g_return_val_if_fail (array != NULL, NULL);
g_return_val_if_fail (value != NULL, NULL);
array = g_variant_get_fixed_array (value, &length, 1);
/* Since the DHCP options come through environment variables, they should
* already be UTF-8 safe, but just make sure.
*/
str = g_string_sized_new (array->len);
for (i = 0; i < array->len; i++) {
c = array->data[i];
str = g_string_sized_new (length);
for (i = 0; i < length; i++) {
c = array[i];
/* Convert NULLs to spaces and non-ASCII characters to ? */
if (c == '\0')
......@@ -684,11 +687,10 @@ garray_to_string (GArray *array, const char *key)
#define NEW_TAG "new_"
static void
copy_option (const char * key,
GValue *value,
gpointer user_data)
maybe_add_option (GHashTable *hash,
const char *key,
GVariant *value)
{
GHashTable *hash = user_data;
char *str_value = NULL;
const char **p;
static const char *ignored_keys[] = {
......@@ -699,10 +701,7 @@ copy_option (const char * key,
NULL
};
if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_UCHAR_ARRAY)) {
nm_log_warn (LOGD_DHCP, "key %s value type was not DBUS_TYPE_G_UCHAR_ARRAY", key);
return;
}
g_return_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE_BYTESTRING));
if (g_str_has_prefix (key, OLD_TAG))
return;
......@@ -718,7 +717,7 @@ copy_option (const char * key,
if (!key[0])
return;
str_value = garray_to_string ((GArray *) g_value_get_boxed (value), key);
str_value = bytearray_variant_to_string (value, key);
if (str_value)
g_hash_table_insert (hash, g_strdup (key), str_value);
}
......@@ -727,7 +726,7 @@ gboolean
nm_dhcp_client_handle_event (gpointer unused,
const char *iface,
gint pid,
GHashTable *options,
GVariant *options,
const char *reason,
NMDhcpClient *self)
{
......@@ -740,7 +739,7 @@ nm_dhcp_client_handle_event (gpointer unused,
g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), FALSE);
g_return_val_if_fail (iface != NULL, FALSE);
g_return_val_if_fail (pid > 0, FALSE);
g_return_val_if_fail (options != NULL, FALSE);
g_return_val_if_fail (g_variant_is_of_type (options, G_VARIANT_TYPE_VARDICT), FALSE);
g_return_val_if_fail (reason != NULL, FALSE);
priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
......@@ -756,9 +755,17 @@ nm_dhcp_client_handle_event (gpointer unused,
iface, reason, state_to_string (new_state));
if (new_state == NM_DHCP_STATE_BOUND) {
GVariantIter iter;
const char *name;
GVariant *value;
/* Copy options */
str_options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
g_hash_table_foreach (options, (GHFunc) copy_option, str_options);
g_variant_iter_init (&iter, options);
while (g_variant_iter_next (&iter, "{&sv}", &name, &value)) {
maybe_add_option (str_options, name, value);
g_variant_unref (value);
}
/* Create the IP config */
g_warn_if_fail (g_hash_table_size (str_options));
......
......@@ -159,7 +159,7 @@ void nm_dhcp_client_set_state (NMDhcpClient *self,
gboolean nm_dhcp_client_handle_event (gpointer unused,
const char *iface,
gint pid,
GHashTable *options,
GVariant *options,
const char *reason,
NMDhcpClient *self);
......
......@@ -75,69 +75,6 @@ build_signal_parameters (void)
return g_variant_new ("(a{sv})", &builder);
}
#if !HAVE_DBUS_GLIB_100
/* It doesn't matter that nm-dhcp-helper doesn't use dbus-glib itself; the
* workaround code is for if the daemon is built with old dbus-glib.
*/
static gboolean ever_acquired = FALSE;
static void
on_name_acquired (GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
GMainLoop *loop = user_data;
ever_acquired = TRUE;
g_main_loop_quit (loop);
}
static void
on_name_lost (GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
if (ever_acquired) {
g_print ("Lost D-Bus name: exiting\n");
exit (0);
} else {
g_printerr ("Error: Could not acquire the NM DHCP client service.\n");
exit (1);
}
}
static GDBusConnection *
shared_connection_init (void)
{
GDBusConnection *connection;
GError *error = NULL;
GMainLoop *loop;
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
if (!connection) {
g_dbus_error_strip_remote_error (error);
g_printerr ("Error: could not get the system bus. Make sure "
"the message bus daemon is running! Message: %s\n",
error->message);
g_error_free (error);
return NULL;
}
loop = g_main_loop_new (NULL, FALSE);
g_bus_own_name_on_connection (connection,
"org.freedesktop.nm_dhcp_client",
0,
on_name_acquired,
on_name_lost,
loop, NULL);
g_main_loop_run (loop);
g_main_loop_unref (loop);
return connection;
}
#endif
static void
fatal_error (void)
{
......@@ -164,16 +101,11 @@ main (int argc, char *argv[])
G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
NULL, NULL, &error);
if (!connection) {
#if !HAVE_DBUS_GLIB_100
connection = shared_connection_init ();
#endif
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 ();
}
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 ();
}
if (!g_dbus_connection_emit_signal (connection,
......
<!DOCTYPE busconfig PUBLIC
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<policy user="root">
<allow own="org.freedesktop.nm_dhcp_client"/>
</policy>
<policy context="default">
<deny own="org.freedesktop.nm_dhcp_client"/>
<deny send_destination="org.freedesktop.nm_dhcp_client"/>
</policy>
</busconfig>
......@@ -19,7 +19,6 @@
#include "config.h"
#include <dbus/dbus.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <signal.h>
......@@ -32,7 +31,6 @@
#include "nm-dhcp-listener.h"
#include "nm-core-internal.h"
#include "nm-bus-manager.h"
#include "nm-dbus-glib-types.h"
#include "NetworkManagerUtils.h"
#define NM_DHCP_CLIENT_DBUS_IFACE "org.freedesktop.nm_dhcp_client"
......@@ -43,8 +41,7 @@ typedef struct {
NMBusManager * dbus_mgr;
guint new_conn_id;
guint dis_conn_id;
GHashTable * proxies;
DBusGProxy * proxy;
GHashTable * signal_handlers;
} NMDhcpListenerPrivate;
#define NM_DHCP_LISTENER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DHCP_LISTENER, NMDhcpListenerPrivate))
......@@ -60,61 +57,44 @@ static guint signals[LAST_SIGNAL] = { 0 };
/***************************************************/
static char *
garray_to_string (GArray *array, const char *key)
get_option (GVariant *options, const char *key)
{
GString *str;
int i;
unsigned char c;
char *converted = NULL;
GVariant *value;
const guchar *bytes, *s;
gsize len;
char *converted, *d;
g_return_val_if_fail (array != NULL, NULL);
if (!g_variant_lookup (options, key, "@ay", &value))
return NULL;
bytes = g_variant_get_fixed_array (value, &len, 1);
/* Since the DHCP options come through environment variables, they should
* already be UTF-8 safe, but just make sure.
*/
str = g_string_sized_new (array->len);
for (i = 0; i < array->len; i++) {
c = array->data[i];
converted = g_malloc (len + 1);
for (s = bytes, d = converted; s < bytes + len; s++, d++) {
/* Convert NULLs to spaces and non-ASCII characters to ? */
if (c == '\0')
c = ' ';
else if (c > 127)
c = '?';
str = g_string_append_c (str, c);
if (*s == '\0')
*d = ' ';
else if (*s > 127)
*d = '?';
else
*d = *s;
}
str = g_string_append_c (str, '\0');
*d = '\0';
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);
g_string_free (str, FALSE);
return converted;
}
static char *
get_option (GHashTable *hash, const char *key)
{
GValue *value;
value = g_hash_table_lookup (hash, key);
if (value == NULL)
return NULL;
if (G_VALUE_TYPE (value) != DBUS_TYPE_G_UCHAR_ARRAY) {
nm_log_warn (LOGD_DHCP, "unexpected key %s value type was not "
"DBUS_TYPE_G_UCHAR_ARRAY",
(char *) key);
return NULL;
}
return garray_to_string ((GArray *) g_value_get_boxed (value), key);
}
static void
handle_event (DBusGProxy *proxy,
GHashTable *options,
gpointer user_data)
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)
{
NMDhcpListener *self = NM_DHCP_LISTENER (user_data);
char *iface = NULL;
......@@ -122,6 +102,12 @@ handle_event (DBusGProxy *proxy,
char *reason = NULL;
gint pid;
gboolean handled = FALSE;
GVariant *options;
if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(a{sv})")))
return;
g_variant_get (parameters, "(@a{sv})", &options);
iface = get_option (options, "interface");
if (iface == NULL) {
......@@ -155,39 +141,42 @@ out:
g_free (iface);
g_free (pid_str);
g_free (reason);
g_variant_unref (options);
}
#if HAVE_DBUS_GLIB_100
static void
new_connection_cb (NMBusManager *mgr,
DBusGConnection *connection,
GDBusConnection *connection,
NMDhcpListener *self)
{
DBusGProxy *proxy;
/* Create a new proxy for the client */
proxy = dbus_g_proxy_new_for_peer (connection, "/", NM_DHCP_CLIENT_DBUS_IFACE);
dbus_g_proxy_add_signal (proxy, "Event", DBUS_TYPE_G_MAP_OF_VARIANT, G_TYPE_INVALID);
dbus_g_proxy_connect_signal (proxy, "Event", G_CALLBACK (handle_event), self, NULL);
g_hash_table_insert (NM_DHCP_LISTENER_GET_PRIVATE (self)->proxies, connection, proxy);
NMDhcpListenerPrivate *priv = NM_DHCP_LISTENER_GET_PRIVATE (self);
guint id;
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));
}
static void
dis_connection_cb (NMBusManager *mgr,
DBusGConnection *connection,
GDBusConnection *connection,
NMDhcpListener *self)
{
NMDhcpListenerPrivate *priv = NM_DHCP_LISTENER_GET_PRIVATE (self);
DBusGProxy *proxy;
guint id;
proxy = g_hash_table_lookup (priv->proxies, connection);
if (proxy) {
dbus_g_proxy_disconnect_signal (proxy, "Event", G_CALLBACK (handle_event), self);
g_hash_table_remove (priv->proxies, connection);
id = GPOINTER_TO_UINT (g_hash_table_lookup (priv->signal_handlers, connection));
if (id) {
g_dbus_connection_signal_unsubscribe (connection, id);
g_hash_table_remove (priv->signal_handlers, connection);
}
}
#endif
/***************************************************/
......@@ -197,16 +186,12 @@ static void
nm_dhcp_listener_init (NMDhcpListener *self)
{
NMDhcpListenerPrivate *priv = NM_DHCP_LISTENER_GET_PRIVATE (self);
#if !HAVE_DBUS_GLIB_100
DBusGConnection *g_connection;
#endif
/* Maps DBusGConnection :: DBusGProxy */
priv->proxies = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
/* Maps GDBusConnection :: GDBusProxy */
priv->signal_handlers = g_hash_table_new (NULL, NULL);
priv->dbus_mgr = nm_bus_manager_get ();
#if HAVE_DBUS_GLIB_100
/* Register the socket our DHCP clients will return lease info on */
nm_bus_manager_private_server_register (priv->dbus_mgr, PRIV_SOCK_PATH, PRIV_SOCK_TAG);
priv->new_conn_id = g_signal_connect (priv->dbus_mgr,
......@@ -217,16 +202,6 @@ nm_dhcp_listener_init (NMDhcpListener *self)
NM_BUS_MANAGER_PRIVATE_CONNECTION_DISCONNECTED "::" PRIV_SOCK_TAG,
G_CALLBACK (dis_connection_cb),
self);
#else
g_connection = nm_dbus_manager_get_connection (priv->dbus_mgr);
priv->proxy = dbus_g_proxy_new_for_name (g_connection,
"org.freedesktop.nm_dhcp_client",
"/",
NM_DHCP_CLIENT_DBUS_IFACE);
g_assert (priv->proxy);
dbus_g_proxy_add_signal (priv->proxy, "Event", DBUS_TYPE_G_MAP_OF_VARIANT, G_TYPE_INVALID);
dbus_g_proxy_connect_signal (priv->proxy, "Event", G_CALLBACK (handle_event), self, NULL);
#endif
}
static void
......@@ -244,11 +219,7 @@ dispose (GObject *object)
}
priv->dbus_mgr = NULL;
if (priv->proxies) {
g_hash_table_destroy (priv->proxies);
priv->proxies = NULL;
}
g_clear_object (&priv->proxy);
g_clear_pointer (&priv->signal_handlers, g_hash_table_destroy);
G_OBJECT_CLASS (nm_dhcp_listener_parent_class)->dispose (object);
}
......@@ -274,6 +245,6 @@ nm_dhcp_listener_class_init (NMDhcpListenerClass *listener_class)
4,
G_TYPE_STRING, /* iface */
G_TYPE_INT, /* pid */
G_TYPE_HASH_TABLE, /* options */
G_TYPE_VARIANT, /* options */
G_TYPE_STRING); /* reason */
}
......@@ -38,7 +38,6 @@
#include "nm-dhcp-dhcpcd.h"
#include "nm-dhcp-systemd.h"
#include "nm-config.h"
#include "nm-dbus-glib-types.h"
#include "NetworkManagerUtils.h"
#define DHCP_TIMEOUT 45 /* default DHCP timeout, in seconds */
......@@ -180,7 +179,7 @@ get_client_type (const char *client, GError **error)
static void client_state_changed (NMDhcpClient *client,
NMDhcpState state,
GObject *ip_config,
GHashTable *options,
GVariant *options,
NMDhcpManager *self);
static void
......@@ -200,7 +199,7 @@ static void
client_state_changed (NMDhcpClient *client,
NMDhcpState state,
GObject *ip_config,
GHashTable *options,
GVariant *options,
NMDhcpManager *self)
{
if (state >= NM_DHCP_STATE_TIMEOUT)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment