mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-24 19:30:07 +01:00
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.
This commit is contained in:
parent
8f36727ac8
commit
7f6e39ec6e
7 changed files with 88 additions and 204 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
<!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;
|
||||
NMDhcpListenerPrivate *priv = NM_DHCP_LISTENER_GET_PRIVATE (self);
|
||||
guint id;
|
||||
|
||||
/* 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);
|
||||
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)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue