diff --git a/ChangeLog b/ChangeLog index 4f44c570f4..b09e66535f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +2008-08-07 Dan Williams + + * include/NetworkManager.h + - Add the DHCP4Config D-Bus interface + + * libnm-glib/Makefile.am + libnm-glib/nm-dhcp4-config.c + libnm-glib/nm-dhcp4-config.h + - Handle DHCP4 config objects exported by NM over D-Bus + + * libnm-glib/nm-device.c + libnm-glib/nm-device.h + - Add a 'dhcp4-config' property + + * libnm-glib/libnm-glib-test.c + - Print out DHCP4 config for devices + - Fix some crashes when no connections are active + + * src/nm-device-interface.c + src/nm-device.c + src/nm-dhcp4-config.c + src/nm-dhcp4-config.h + - Treat dhcp4-config object as an object path at the D-Bus interface so + that when it doesn't exist we can proxy it as "/" which dbus-glib + doesn't let us do when the property type is G_TYPE_OBJECT + 2008-08-07 Dan Williams * src/NetworkManager.c diff --git a/include/NetworkManager.h b/include/NetworkManager.h index e2ef802da1..5414337e5c 100644 --- a/include/NetworkManager.h +++ b/include/NetworkManager.h @@ -39,6 +39,7 @@ #define NM_DBUS_INTERFACE_CDMA_DEVICE NM_DBUS_INTERFACE_DEVICE ".Cdma" #define NM_DBUS_INTERFACE_ACTIVE_CONNECTION NM_DBUS_INTERFACE ".Connection.Active" #define NM_DBUS_INTERFACE_IP4_CONFIG NM_DBUS_INTERFACE ".IP4Config" +#define NM_DBUS_INTERFACE_DHCP4_CONFIG NM_DBUS_INTERFACE ".DHCP4Config" #define NM_DBUS_SERVICE_USER_SETTINGS "org.freedesktop.NetworkManagerUserSettings" diff --git a/libnm-glib/Makefile.am b/libnm-glib/Makefile.am index 3b2fd8d313..d3c73b61c2 100644 --- a/libnm-glib/Makefile.am +++ b/libnm-glib/Makefile.am @@ -16,7 +16,9 @@ BUILT_SOURCES = \ nm-settings-system-bindings.h \ nm-vpn-connection-bindings.h \ nm-vpn-plugin-glue.h \ - nm-active-connection-bindings.h + nm-active-connection-bindings.h \ + nm-ip4-config-bindings.h \ + nm-dhcp4-config-bindings.h lib_LTLIBRARIES = libnm_glib.la libnm_glib_vpn.la @@ -49,7 +51,8 @@ libnminclude_HEADERS = \ nm-active-connection.h \ nm-dbus-connection.h \ nm-dbus-settings.h \ - nm-dbus-settings-system.h + nm-dbus-settings-system.h \ + nm-dhcp4-config.h libnm_glib_la_SOURCES = \ libnm_glib.c \ @@ -76,7 +79,8 @@ libnm_glib_la_SOURCES = \ nm-active-connection.c \ nm-dbus-connection.c \ nm-dbus-settings.c \ - nm-dbus-settings-system.c + nm-dbus-settings-system.c \ + nm-dhcp4-config.c libnm_glib_la_LIBADD = \ $(top_builddir)/libnm-util/libnm-util.la \ @@ -138,6 +142,12 @@ nm-vpn-plugin-glue.h: $(top_srcdir)/introspection/nm-vpn-plugin.xml nm-active-connection-bindings.h: $(top_srcdir)/introspection/nm-active-connection.xml dbus-binding-tool --prefix=nm_active_connection --mode=glib-client --output=$@ $< +nm-ip4-config-bindings.h: $(top_srcdir)/introspection/nm-ip4-config.xml + dbus-binding-tool --prefix=nm_ip4_config --mode=glib-client --output=$@ $< + +nm-dhcp4-config-bindings.h: $(top_srcdir)/introspection/nm-dhcp4-config.xml + dbus-binding-tool --prefix=nm_dhcp4_config --mode=glib-client --output=$@ $< + pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libnm_glib.pc libnm_glib_vpn.pc diff --git a/libnm-glib/libnm-glib-test.c b/libnm-glib/libnm-glib-test.c index 80844f4950..3cfd69c6de 100644 --- a/libnm-glib/libnm-glib-test.c +++ b/libnm-glib/libnm-glib-test.c @@ -120,6 +120,30 @@ dump_ip4_config (NMIP4Config *cfg) } } +static void +print_one_dhcp4_option (gpointer key, gpointer data, gpointer user_data) +{ + const char *option = (const char *) key; + const char *value = (const char *) data; + + g_print (" %s: %s\n", option, value); +} + +static void +dump_dhcp4_config (NMDHCP4Config *config) +{ + GHashTable *options = NULL; + + if (!config) + return; + + g_print ("\nDHCP4 Options:\n"); + g_print ("-------------------------------------\n"); + + g_object_get (G_OBJECT (config), NM_DHCP4_CONFIG_OPTIONS, &options, NULL); + g_hash_table_foreach (options, print_one_dhcp4_option, NULL); +} + static void dump_access_point (NMAccessPoint *ap) { @@ -206,6 +230,8 @@ dump_device (NMDevice *device) dump_wired (NM_DEVICE_ETHERNET (device)); else if (NM_IS_DEVICE_WIFI (device)) dump_wireless (NM_DEVICE_WIFI (device)); + + dump_dhcp4_config (nm_device_get_dhcp4_config (device)); } static gboolean @@ -238,7 +264,7 @@ active_connections_changed (NMClient *client, GParamSpec *pspec, gpointer user_d g_print ("Active connections changed:\n"); connections = nm_client_get_active_connections (client); - for (i = 0; i < connections->len; i++) { + for (i = 0; connections && (i < connections->len); i++) { NMActiveConnection *connection; const GPtrArray *devices; @@ -266,7 +292,7 @@ test_get_active_connections (NMClient *client) g_print ("Active connections:\n"); connections = nm_client_get_active_connections (client); - for (i = 0; i < connections->len; i++) { + for (i = 0; connections && (i < connections->len); i++) { const GPtrArray *devices; g_print (" %s\n", nm_object_get_path (g_ptr_array_index (connections, i))); diff --git a/libnm-glib/nm-device.c b/libnm-glib/nm-device.c index 24ca876cfd..a379555dab 100644 --- a/libnm-glib/nm-device.c +++ b/libnm-glib/nm-device.c @@ -28,6 +28,8 @@ typedef struct { gboolean managed; NMIP4Config *ip4_config; gboolean null_ip4_config; + NMDHCP4Config *dhcp4_config; + gboolean null_dhcp4_config; NMDeviceState state; char *product; char *vendor; @@ -41,6 +43,7 @@ enum { PROP_CAPABILITIES, PROP_MANAGED, PROP_IP4_CONFIG, + PROP_DHCP4_CONFIG, PROP_STATE, PROP_PRODUCT, PROP_VENDOR, @@ -106,6 +109,46 @@ demarshal_ip4_config (NMObject *object, GParamSpec *pspec, GValue *value, gpoint return TRUE; } +static gboolean +demarshal_dhcp4_config (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object); + const char *path; + NMDHCP4Config *config = NULL; + DBusGConnection *connection; + + if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH)) + return FALSE; + + priv->null_dhcp4_config = FALSE; + + path = g_value_get_boxed (value); + if (path) { + if (!strcmp (path, "/")) + priv->null_dhcp4_config = TRUE; + else { + config = NM_DHCP4_CONFIG (nm_object_cache_get (path)); + if (config) + config = g_object_ref (config); + else { + connection = nm_object_get_connection (object); + config = NM_DHCP4_CONFIG (nm_dhcp4_config_new (connection, path)); + } + } + } + + if (priv->dhcp4_config) { + g_object_unref (priv->dhcp4_config); + priv->dhcp4_config = NULL; + } + + if (config) + priv->dhcp4_config = config; + + nm_object_queue_notify (object, NM_DEVICE_DHCP4_CONFIG); + return TRUE; +} + static void register_for_property_changed (NMDevice *device) { @@ -117,6 +160,7 @@ register_for_property_changed (NMDevice *device) { NM_DEVICE_CAPABILITIES, nm_object_demarshal_generic, &priv->capabilities }, { NM_DEVICE_MANAGED, nm_object_demarshal_generic, &priv->managed }, { NM_DEVICE_IP4_CONFIG, demarshal_ip4_config, &priv->ip4_config }, + { NM_DEVICE_DHCP4_CONFIG, demarshal_dhcp4_config, &priv->dhcp4_config }, { NULL }, }; @@ -198,6 +242,8 @@ dispose (GObject *object) g_object_unref (priv->proxy); if (priv->ip4_config) g_object_unref (priv->ip4_config); + if (priv->dhcp4_config) + g_object_unref (priv->dhcp4_config); G_OBJECT_CLASS (nm_device_parent_class)->dispose (object); } @@ -243,6 +289,9 @@ get_property (GObject *object, case PROP_IP4_CONFIG: g_value_set_object (value, nm_device_get_ip4_config (device)); break; + case PROP_DHCP4_CONFIG: + g_value_set_object (value, nm_device_get_dhcp4_config (device)); + break; case PROP_STATE: g_value_set_uint (value, nm_device_get_state (device)); break; @@ -320,6 +369,14 @@ nm_device_class_init (NMDeviceClass *device_class) NM_TYPE_IP4_CONFIG, G_PARAM_READABLE)); + g_object_class_install_property + (object_class, PROP_DHCP4_CONFIG, + g_param_spec_object (NM_DEVICE_DHCP4_CONFIG, + "DHCP4 Config", + "DHCP4 Config", + NM_TYPE_DHCP4_CONFIG, + G_PARAM_READABLE)); + g_object_class_install_property (object_class, PROP_STATE, g_param_spec_uint (NM_DEVICE_STATE, @@ -529,6 +586,32 @@ nm_device_get_ip4_config (NMDevice *device) return priv->ip4_config; } +NMDHCP4Config * +nm_device_get_dhcp4_config (NMDevice *device) +{ + NMDevicePrivate *priv; + char *path; + GValue value = { 0, }; + + g_return_val_if_fail (NM_IS_DEVICE (device), NULL); + + priv = NM_DEVICE_GET_PRIVATE (device); + if (priv->dhcp4_config) + return priv->dhcp4_config; + if (priv->null_dhcp4_config) + return NULL; + + path = nm_object_get_object_path_property (NM_OBJECT (device), NM_DBUS_INTERFACE_DEVICE, "Dhcp4Config"); + if (path) { + g_value_init (&value, DBUS_TYPE_G_OBJECT_PATH); + g_value_take_boxed (&value, path); + demarshal_dhcp4_config (NM_OBJECT (device), NULL, &value, &priv->dhcp4_config); + g_value_unset (&value); + } + + return priv->dhcp4_config; +} + NMDeviceState nm_device_get_state (NMDevice *device) { diff --git a/libnm-glib/nm-device.h b/libnm-glib/nm-device.h index 1b1214c5c3..f74d892c44 100644 --- a/libnm-glib/nm-device.h +++ b/libnm-glib/nm-device.h @@ -7,6 +7,7 @@ #include "nm-object.h" #include "NetworkManager.h" #include "nm-ip4-config.h" +#include "nm-dhcp4-config.h" #include "nm-connection.h" G_BEGIN_DECLS @@ -24,6 +25,7 @@ G_BEGIN_DECLS #define NM_DEVICE_CAPABILITIES "capabilities" #define NM_DEVICE_MANAGED "managed" #define NM_DEVICE_IP4_CONFIG "ip4-config" +#define NM_DEVICE_DHCP4_CONFIG "dhcp4-config" #define NM_DEVICE_STATE "state" #define NM_DEVICE_VENDOR "vendor" #define NM_DEVICE_PRODUCT "product" @@ -46,15 +48,16 @@ GType nm_device_get_type (void); GObject * nm_device_new (DBusGConnection *connection, const char *path); -const char * nm_device_get_iface (NMDevice *device); -const char * nm_device_get_udi (NMDevice *device); -const char * nm_device_get_driver (NMDevice *device); -guint32 nm_device_get_capabilities (NMDevice *device); -gboolean nm_device_get_managed (NMDevice *device); -NMIP4Config * nm_device_get_ip4_config (NMDevice *device); -NMDeviceState nm_device_get_state (NMDevice *device); -const char * nm_device_get_product (NMDevice *device); -const char * nm_device_get_vendor (NMDevice *device); +const char * nm_device_get_iface (NMDevice *device); +const char * nm_device_get_udi (NMDevice *device); +const char * nm_device_get_driver (NMDevice *device); +guint32 nm_device_get_capabilities (NMDevice *device); +gboolean nm_device_get_managed (NMDevice *device); +NMIP4Config * nm_device_get_ip4_config (NMDevice *device); +NMDHCP4Config * nm_device_get_dhcp4_config (NMDevice *device); +NMDeviceState nm_device_get_state (NMDevice *device); +const char * nm_device_get_product (NMDevice *device); +const char * nm_device_get_vendor (NMDevice *device); G_END_DECLS diff --git a/libnm-glib/nm-dhcp4-config.c b/libnm-glib/nm-dhcp4-config.c new file mode 100644 index 0000000000..9931461040 --- /dev/null +++ b/libnm-glib/nm-dhcp4-config.c @@ -0,0 +1,189 @@ +#include + +#include "nm-dhcp4-config.h" +#include "NetworkManager.h" +#include "nm-types-private.h" +#include "nm-object-private.h" +#include "nm-utils.h" + +G_DEFINE_TYPE (NMDHCP4Config, nm_dhcp4_config, NM_TYPE_OBJECT) + +#define NM_DHCP4_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DHCP4_CONFIG, NMDHCP4ConfigPrivate)) + +typedef struct { + DBusGProxy *proxy; + + GHashTable *options; +} NMDHCP4ConfigPrivate; + +enum { + PROP_0, + PROP_OPTIONS, + + LAST_PROP +}; + +static void +nm_dhcp4_config_init (NMDHCP4Config *config) +{ +} + +static void +copy_options (gpointer key, gpointer data, gpointer user_data) +{ + GHashTable *options = (GHashTable *) user_data; + GValue *value = (GValue *) data; + + g_hash_table_insert (options, g_strdup (key), g_value_dup_string (value)); +} + +static gboolean +demarshal_dhcp4_options (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field) +{ + NMDHCP4ConfigPrivate *priv = NM_DHCP4_CONFIG_GET_PRIVATE (object); + GHashTable *new_options; + + g_hash_table_remove_all (priv->options); + + new_options = g_value_get_boxed (value); + if (new_options) + g_hash_table_foreach (new_options, copy_options, priv->options); + + nm_object_queue_notify (object, NM_DHCP4_CONFIG_OPTIONS); + return TRUE; +} + +static void +register_for_property_changed (NMDHCP4Config *config) +{ + NMDHCP4ConfigPrivate *priv = NM_DHCP4_CONFIG_GET_PRIVATE (config); + const NMPropertiesChangedInfo property_changed_info[] = { + { NM_DHCP4_CONFIG_OPTIONS, demarshal_dhcp4_options, &priv->options }, + { NULL }, + }; + + nm_object_handle_properties_changed (NM_OBJECT (config), + priv->proxy, + property_changed_info); +} + +static GObject* +constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + NMObject *object; + DBusGConnection *connection; + NMDHCP4ConfigPrivate *priv; + + object = (NMObject *) G_OBJECT_CLASS (nm_dhcp4_config_parent_class)->constructor (type, + n_construct_params, + construct_params); + if (!object) + return NULL; + + priv = NM_DHCP4_CONFIG_GET_PRIVATE (object); + priv->options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + + connection = nm_object_get_connection (object); + + priv->proxy = dbus_g_proxy_new_for_name (connection, + NM_DBUS_SERVICE, + nm_object_get_path (object), + NM_DBUS_INTERFACE_DHCP4_CONFIG); + + register_for_property_changed (NM_DHCP4_CONFIG (object)); + + return G_OBJECT (object); +} + +static void +finalize (GObject *object) +{ + NMDHCP4ConfigPrivate *priv = NM_DHCP4_CONFIG_GET_PRIVATE (object); + + if (priv->options) + g_hash_table_destroy (priv->options); + + G_OBJECT_CLASS (nm_dhcp4_config_parent_class)->finalize (object); +} + +static GHashTable * +nm_dhcp4_config_get_options (NMDHCP4Config *self) +{ + NMDHCP4ConfigPrivate *priv = NM_DHCP4_CONFIG_GET_PRIVATE (self); + GValue value = { 0, }; + + if (g_hash_table_size (priv->options)) + return priv->options; + + if (!nm_object_get_property (NM_OBJECT (self), + "org.freedesktop.DBus.Properties", + "Options", + &value)) + goto out; + + demarshal_dhcp4_options (NM_OBJECT (self), NULL, &value, &priv->options); + g_value_unset (&value); + +out: + return priv->options; +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMDHCP4Config *self = NM_DHCP4_CONFIG (object); + + switch (prop_id) { + case PROP_OPTIONS: + g_value_set_boxed (value, nm_dhcp4_config_get_options (self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_dhcp4_config_class_init (NMDHCP4ConfigClass *config_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (config_class); + + g_type_class_add_private (config_class, sizeof (NMDHCP4ConfigPrivate)); + + /* virtual methods */ + object_class->constructor = constructor; + object_class->get_property = get_property; + object_class->finalize = finalize; + + /* properties */ + g_object_class_install_property + (object_class, PROP_OPTIONS, + g_param_spec_boxed (NM_DHCP4_CONFIG_OPTIONS, + "Options", + "Options", + G_TYPE_HASH_TABLE, + G_PARAM_READABLE)); +} + +GObject * +nm_dhcp4_config_new (DBusGConnection *connection, const char *object_path) +{ + return (GObject *) g_object_new (NM_TYPE_DHCP4_CONFIG, + NM_OBJECT_DBUS_CONNECTION, connection, + NM_OBJECT_DBUS_PATH, object_path, + NULL); +} + +const char * +nm_dhcp4_config_get_option (NMDHCP4Config *self, const char *option) +{ + g_return_val_if_fail (NM_IS_DHCP4_CONFIG (self), NULL); + + return g_hash_table_lookup (nm_dhcp4_config_get_options (self), option); +} + diff --git a/libnm-glib/nm-dhcp4-config.h b/libnm-glib/nm-dhcp4-config.h new file mode 100644 index 0000000000..2db55003d9 --- /dev/null +++ b/libnm-glib/nm-dhcp4-config.h @@ -0,0 +1,35 @@ +#ifndef NM_DHCP4_CONFIG_H +#define NM_DHCP4_CONFIG_H + +#include +#include +#include +#include "nm-object.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DHCP4_CONFIG (nm_dhcp4_config_get_type ()) +#define NM_DHCP4_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DHCP4_CONFIG, NMDHCP4Config)) +#define NM_DHCP4_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DHCP4_CONFIG, NMDHCP4ConfigClass)) +#define NM_IS_DHCP4_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DHCP4_CONFIG)) +#define NM_IS_DHCP4_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DHCP4_CONFIG)) + +typedef struct { + NMObject parent; +} NMDHCP4Config; + +typedef struct { + NMObjectClass parent; +} NMDHCP4ConfigClass; + +#define NM_DHCP4_CONFIG_OPTIONS "options" + +GType nm_dhcp4_config_get_type (void); + +GObject *nm_dhcp4_config_new (DBusGConnection *connection, const char *object_path); + +const char * nm_dhcp4_config_get_option (NMDHCP4Config *config, const char *option); + +G_END_DECLS + +#endif /* NM_DHCP4_CONFIG_H */ diff --git a/src/nm-device-interface.c b/src/nm-device-interface.c index 0ae1b974a5..c3d578c2e8 100644 --- a/src/nm-device-interface.c +++ b/src/nm-device-interface.c @@ -98,10 +98,10 @@ nm_device_interface_init (gpointer g_iface) g_object_interface_install_property (g_iface, - g_param_spec_object (NM_DEVICE_INTERFACE_DHCP4_CONFIG, + g_param_spec_boxed (NM_DEVICE_INTERFACE_DHCP4_CONFIG, "DHCP4 Config", "DHCP4 Config", - G_TYPE_OBJECT, + DBUS_TYPE_G_OBJECT_PATH, G_PARAM_READWRITE)); g_object_interface_install_property diff --git a/src/nm-device.c b/src/nm-device.c index a97986cd08..f50c9ee4d9 100644 --- a/src/nm-device.c +++ b/src/nm-device.c @@ -2062,9 +2062,9 @@ get_property (GObject *object, guint prop_id, case NM_DEVICE_INTERFACE_PROP_DHCP4_CONFIG: if ( ((state == NM_DEVICE_STATE_ACTIVATED) || (state == NM_DEVICE_STATE_IP_CONFIG)) && nm_device_get_use_dhcp (self)) - g_value_set_object (value, priv->dhcp4_config); + g_value_set_boxed (value, nm_dhcp4_config_get_dbus_path (priv->dhcp4_config)); else - g_value_set_object (value, NULL); + g_value_set_boxed (value, "/"); break; case NM_DEVICE_INTERFACE_PROP_STATE: g_value_set_uint (value, priv->state); diff --git a/src/nm-dhcp4-config.c b/src/nm-dhcp4-config.c index 334a1b0e57..2d5e23c975 100644 --- a/src/nm-dhcp4-config.c +++ b/src/nm-dhcp4-config.c @@ -105,6 +105,14 @@ nm_dhcp4_config_get_option (NMDHCP4Config *self, const char *key) return value ? g_value_get_string (value) : NULL; } +const char * +nm_dhcp4_config_get_dbus_path (NMDHCP4Config *self) +{ + g_return_val_if_fail (NM_IS_DHCP4_CONFIG (self), NULL); + + return NM_DHCP4_CONFIG_GET_PRIVATE (self)->dbus_path; +} + static void nm_gvalue_destroy (gpointer data) { diff --git a/src/nm-dhcp4-config.h b/src/nm-dhcp4-config.h index 8e6cb03013..dbe716a5cf 100644 --- a/src/nm-dhcp4-config.h +++ b/src/nm-dhcp4-config.h @@ -51,6 +51,8 @@ GType nm_dhcp4_config_get_type (void); NMDHCP4Config *nm_dhcp4_config_new (void); +const char *nm_dhcp4_config_get_dbus_path (NMDHCP4Config *config); + void nm_dhcp4_config_add_option (NMDHCP4Config *config, const char *key, const char *option);