diff --git a/libnm-util/libnm-util.ver b/libnm-util/libnm-util.ver index bc86e0818f..f7354a6933 100644 --- a/libnm-util/libnm-util.ver +++ b/libnm-util/libnm-util.ver @@ -132,6 +132,7 @@ global: nm_setting_ip4_config_get_ignore_auto_dns; nm_setting_ip4_config_get_dhcp_client_id; nm_setting_ip4_config_get_dhcp_hostname; + nm_setting_ip4_config_get_dhcp_send_hostname; nm_setting_ip4_config_get_never_default; nm_setting_need_secrets; nm_setting_ppp_error_get_type; diff --git a/libnm-util/nm-setting-ip4-config.c b/libnm-util/nm-setting-ip4-config.c index 7808bbef69..c1fc1fc67f 100644 --- a/libnm-util/nm-setting-ip4-config.c +++ b/libnm-util/nm-setting-ip4-config.c @@ -80,6 +80,7 @@ typedef struct { gboolean ignore_auto_routes; gboolean ignore_auto_dns; char *dhcp_client_id; + gboolean dhcp_send_hostname; char *dhcp_hostname; gboolean never_default; } NMSettingIP4ConfigPrivate; @@ -94,6 +95,7 @@ enum { PROP_IGNORE_AUTO_ROUTES, PROP_IGNORE_AUTO_DNS, PROP_DHCP_CLIENT_ID, + PROP_DHCP_SEND_HOSTNAME, PROP_DHCP_HOSTNAME, PROP_NEVER_DEFAULT, @@ -412,6 +414,14 @@ nm_setting_ip4_config_get_dhcp_client_id (NMSettingIP4Config *setting) return NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->dhcp_client_id; } +gboolean +nm_setting_ip4_config_get_dhcp_send_hostname (NMSettingIP4Config *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), FALSE); + + return NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->dhcp_send_hostname; +} + const char * nm_setting_ip4_config_get_dhcp_hostname (NMSettingIP4Config *setting) { @@ -617,9 +627,15 @@ set_property (GObject *object, guint prop_id, g_free (priv->dhcp_client_id); priv->dhcp_client_id = g_value_dup_string (value); break; + case PROP_DHCP_SEND_HOSTNAME: + priv->dhcp_send_hostname = g_value_get_boolean (value); + break; case PROP_DHCP_HOSTNAME: g_free (priv->dhcp_hostname); priv->dhcp_hostname = g_value_dup_string (value); + /* FIXME: Is this a good idea? */ + if (priv->dhcp_hostname) + priv->dhcp_send_hostname = TRUE; break; case PROP_NEVER_DEFAULT: priv->never_default = g_value_get_boolean (value); @@ -662,6 +678,9 @@ get_property (GObject *object, guint prop_id, case PROP_DHCP_CLIENT_ID: g_value_set_string (value, nm_setting_ip4_config_get_dhcp_client_id (setting)); break; + case PROP_DHCP_SEND_HOSTNAME: + g_value_set_boolean (value, nm_setting_ip4_config_get_dhcp_send_hostname (setting)); + break; case PROP_DHCP_HOSTNAME: g_value_set_string (value, nm_setting_ip4_config_get_dhcp_hostname (setting)); break; @@ -753,6 +772,14 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *setting_class) NULL, G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + g_object_class_install_property + (object_class, PROP_DHCP_SEND_HOSTNAME, + g_param_spec_boolean (NM_SETTING_IP4_CONFIG_DHCP_SEND_HOSTNAME, + "Send DHCP hostname", + "Send the hostname to DHCP server", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + g_object_class_install_property (object_class, PROP_DHCP_HOSTNAME, g_param_spec_string (NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME, diff --git a/libnm-util/nm-setting-ip4-config.h b/libnm-util/nm-setting-ip4-config.h index 91a1c69b4b..5094d6de5c 100644 --- a/libnm-util/nm-setting-ip4-config.h +++ b/libnm-util/nm-setting-ip4-config.h @@ -61,6 +61,7 @@ GQuark nm_setting_ip4_config_error_quark (void); #define NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES "ignore-auto-routes" #define NM_SETTING_IP4_CONFIG_IGNORE_AUTO_DNS "ignore-auto-dns" #define NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID "dhcp-client-id" +#define NM_SETTING_IP4_CONFIG_DHCP_SEND_HOSTNAME "dhcp-send-hostname" #define NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME "dhcp-hostname" #define NM_SETTING_IP4_CONFIG_NEVER_DEFAULT "never-default" @@ -69,7 +70,6 @@ GQuark nm_setting_ip4_config_error_quark (void); #define NM_SETTING_IP4_CONFIG_METHOD_MANUAL "manual" #define NM_SETTING_IP4_CONFIG_METHOD_SHARED "shared" - typedef struct NMIP4Address NMIP4Address; NMIP4Address * nm_ip4_address_new (void); @@ -157,6 +157,7 @@ void nm_setting_ip4_config_clear_routes (NMSettingIP4Config * gboolean nm_setting_ip4_config_get_ignore_auto_routes (NMSettingIP4Config *setting); gboolean nm_setting_ip4_config_get_ignore_auto_dns (NMSettingIP4Config *setting); const char * nm_setting_ip4_config_get_dhcp_client_id (NMSettingIP4Config *setting); +gboolean nm_setting_ip4_config_get_dhcp_send_hostname (NMSettingIP4Config *setting); const char * nm_setting_ip4_config_get_dhcp_hostname (NMSettingIP4Config *setting); gboolean nm_setting_ip4_config_get_never_default (NMSettingIP4Config *setting); diff --git a/src/Makefile.am b/src/Makefile.am index 335ee14f54..fe40711d93 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -30,6 +30,7 @@ noinst_LTLIBRARIES = libtest-dhcp.la libtest_dhcp_la_SOURCES = \ nm-ip4-config.c \ + nm-hostname-provider.c \ nm-dbus-manager.c libtest_dhcp_la_CPPFLAGS = \ @@ -68,6 +69,8 @@ NetworkManager_SOURCES = \ nm-dbus-manager.c \ nm-hal-manager.c \ nm-hal-manager.h \ + nm-hostname-provider.c \ + nm-hostname-provider.h \ nm-ip4-config.c \ nm-ip4-config.h \ nm-active-connection.h \ diff --git a/src/NetworkManager.c b/src/NetworkManager.c index 5aa1b15301..2656794df0 100644 --- a/src/NetworkManager.c +++ b/src/NetworkManager.c @@ -48,6 +48,7 @@ #include "nm-dbus-manager.h" #include "nm-supplicant-manager.h" #include "nm-dhcp-manager.h" +#include "nm-hostname-provider.h" #include "nm-netlink-monitor.h" #include "nm-vpn-manager.h" #include "nm-logging.h" @@ -378,6 +379,8 @@ main (int argc, char *argv[]) goto done; } + nm_dhcp_manager_set_hostname_provider (dhcp_mgr, NM_HOSTNAME_PROVIDER (manager)); + /* Start our DBus service */ if (!nm_dbus_manager_start_service (dbus_mgr)) { nm_warning ("Failed to start the dbus service."); diff --git a/src/dhcp-manager/nm-dhcp-manager.c b/src/dhcp-manager/nm-dhcp-manager.c index b2e352d1b6..f7c1095afd 100644 --- a/src/dhcp-manager/nm-dhcp-manager.c +++ b/src/dhcp-manager/nm-dhcp-manager.c @@ -40,6 +40,7 @@ #include "nm-marshal.h" #include "nm-utils.h" #include "nm-dbus-manager.h" +#include "nm-hostname-provider.h" #include "nm-dbus-glib-types.h" #include "nm-glib-compat.h" @@ -52,6 +53,7 @@ typedef struct { NMDBusManager * dbus_mgr; GHashTable * devices; DBusGProxy * proxy; + NMHostnameProvider *hostname_provider; } NMDHCPManagerPrivate; @@ -71,6 +73,8 @@ static NMDHCPManager *nm_dhcp_manager_new (void); static void nm_dhcp_manager_cancel_transaction_real (NMDHCPDevice *device); +static void hostname_provider_destroyed (gpointer data, GObject *destroyed_object); + NMDHCPManager * nm_dhcp_manager_get (void) { @@ -95,6 +99,11 @@ finalize (GObject *object) { NMDHCPManagerPrivate *priv = NM_DHCP_MANAGER_GET_PRIVATE (object); + if (priv->hostname_provider) { + g_object_weak_unref (G_OBJECT (priv->hostname_provider), hostname_provider_destroyed, object); + priv->hostname_provider = NULL; + } + g_hash_table_destroy (priv->devices); g_object_unref (priv->proxy); g_object_unref (priv->dbus_mgr); @@ -582,6 +591,7 @@ nm_dhcp_manager_begin_transaction (NMDHCPManager *manager, { NMDHCPManagerPrivate *priv; NMDHCPDevice *device; + NMSettingIP4Config *setting; g_return_val_if_fail (NM_IS_DHCP_MANAGER (manager), FALSE); g_return_val_if_fail (iface != NULL, FALSE); @@ -597,9 +607,29 @@ nm_dhcp_manager_begin_transaction (NMDHCPManager *manager, nm_dhcp_manager_cancel_transaction_real (device); } - nm_info ("Activation (%s) Beginning DHCP transaction.", iface); + if (s_ip4 && + nm_setting_ip4_config_get_dhcp_send_hostname (s_ip4) && + nm_setting_ip4_config_get_dhcp_hostname (s_ip4) == NULL && + priv->hostname_provider != NULL) { + /* We're asked to send the hostname to DHCP server, + the hostname isn't specified, + and a hostname provider is registered: use that */ + + setting = NM_SETTING_IP4_CONFIG (nm_setting_duplicate (NM_SETTING (s_ip4))); + g_object_set (G_OBJECT (setting), + NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME, + nm_hostname_provider_get_hostname (priv->hostname_provider), + NULL); + } else { + setting = s_ip4 ? g_object_ref (s_ip4) : NULL; + } + + nm_info ("Activation (%s) Beginning DHCP transaction.", iface); + device->pid = nm_dhcp_client_start (device, setting); + + if (setting) + g_object_unref (setting); - device->pid = nm_dhcp_client_start (device, s_ip4); if (device->pid == 0) return FALSE; @@ -1033,3 +1063,29 @@ nm_dhcp_manager_foreach_dhcp4_option (NMDHCPManager *self, return TRUE; } +static void +hostname_provider_destroyed (gpointer data, GObject *destroyed_object) +{ + NM_DHCP_MANAGER_GET_PRIVATE (data)->hostname_provider = NULL; +} + +void +nm_dhcp_manager_set_hostname_provider (NMDHCPManager *manager, + NMHostnameProvider *provider) +{ + NMDHCPManagerPrivate *priv; + + g_return_if_fail (NM_IS_DHCP_MANAGER (manager)); + + priv = NM_DHCP_MANAGER_GET_PRIVATE (manager); + + if (priv->hostname_provider) { + g_object_weak_unref (G_OBJECT (priv->hostname_provider), hostname_provider_destroyed, manager); + priv->hostname_provider = NULL; + } + + if (provider) { + priv->hostname_provider = provider; + g_object_weak_ref (G_OBJECT (provider), hostname_provider_destroyed, manager); + } +} diff --git a/src/dhcp-manager/nm-dhcp-manager.h b/src/dhcp-manager/nm-dhcp-manager.h index c3527387ec..f91a8ee002 100644 --- a/src/dhcp-manager/nm-dhcp-manager.h +++ b/src/dhcp-manager/nm-dhcp-manager.h @@ -29,6 +29,7 @@ #include "nm-ip4-config.h" #include "nm-dhcp4-config.h" +#include "nm-hostname-provider.h" #define NM_DHCP_MANAGER_RUN_DIR LOCALSTATEDIR "/run" @@ -87,6 +88,9 @@ typedef struct { GType nm_dhcp_manager_get_type (void); NMDHCPManager *nm_dhcp_manager_get (void); +void nm_dhcp_manager_set_hostname_provider(NMDHCPManager *manager, + NMHostnameProvider *provider); + gboolean nm_dhcp_manager_begin_transaction (NMDHCPManager *manager, const char *iface, NMSettingIP4Config *s_ip4, diff --git a/src/nm-hostname-provider.c b/src/nm-hostname-provider.c new file mode 100644 index 0000000000..19498efcf3 --- /dev/null +++ b/src/nm-hostname-provider.c @@ -0,0 +1,36 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +#include "nm-hostname-provider.h" + +const char * +nm_hostname_provider_get_hostname (NMHostnameProvider *self) +{ + g_return_val_if_fail (NM_IS_HOSTNAME_PROVIDER (self), NULL); + + return NM_HOSTNAME_PROVIDER_GET_INTERFACE (self)->get_hostname (self); +} + +GType +nm_hostname_provider_get_type (void) +{ + static GType type = 0; + + if (!G_UNLIKELY (type)) { + const GTypeInfo type_info = { + sizeof (NMHostnameProvider), /* class_size */ + NULL, /* base_init */ + NULL, /* base_finalize */ + NULL, + NULL, /* class_finalize */ + NULL, /* class_data */ + 0, + 0, /* n_preallocs */ + NULL + }; + + type = g_type_register_static (G_TYPE_INTERFACE, "NMHostnameProvider", &type_info, 0); + g_type_interface_add_prerequisite (type, G_TYPE_OBJECT); + } + + return type; +} diff --git a/src/nm-hostname-provider.h b/src/nm-hostname-provider.h new file mode 100644 index 0000000000..5cfb373583 --- /dev/null +++ b/src/nm-hostname-provider.h @@ -0,0 +1,26 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +#ifndef NM_HOSTNAME_PROVIDER_H +#define NM_HOSTNAME_PROVIDER_H + +#include + +#define NM_TYPE_HOSTNAME_PROVIDER (nm_hostname_provider_get_type ()) +#define NM_HOSTNAME_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_HOSTNAME_PROVIDER, NMHostnameProvider)) +#define NM_IS_HOSTNAME_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_HOSTNAME_PROVIDER)) +#define NM_HOSTNAME_PROVIDER_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_HOSTNAME_PROVIDER, NMHostnameProvider)) + +typedef struct _NMHostnameProvider NMHostnameProvider; + +struct _NMHostnameProvider { + GTypeInterface g_iface; + + /* Methods */ + const char *(*get_hostname) (NMHostnameProvider *self); +}; + +GType nm_hostname_provider_get_type (void); + +const char *nm_hostname_provider_get_hostname (NMHostnameProvider *self); + +#endif /* NM_HOSTNAME_PROVIDER_H */ diff --git a/src/nm-manager.c b/src/nm-manager.c index a7ff5a74c6..b6a8a275fb 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -42,6 +42,7 @@ #include "nm-marshal.h" #include "nm-dbus-glib-types.h" #include "nm-hal-manager.h" +#include "nm-hostname-provider.h" #define NM_AUTOIP_DBUS_SERVICE "org.freedesktop.nm_avahi_autoipd" #define NM_AUTOIP_DBUS_IFACE "org.freedesktop.nm_avahi_autoipd" @@ -102,6 +103,8 @@ static void system_settings_properties_changed_cb (DBusGProxy *proxy, static void add_device (NMManager *self, NMDevice *device); static void remove_one_device (NMManager *manager, NMDevice *device); +static void hostname_provider_init (NMHostnameProvider *provider_class); + #define SSD_POKE_INTERVAL 120 #define ORIGDEV_TAG "originating-device" @@ -152,7 +155,9 @@ typedef struct { #define NM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MANAGER, NMManagerPrivate)) -G_DEFINE_TYPE (NMManager, nm_manager, G_TYPE_OBJECT) +G_DEFINE_TYPE_EXTENDED (NMManager, nm_manager, G_TYPE_OBJECT, 0, + G_IMPLEMENT_INTERFACE (NM_TYPE_HOSTNAME_PROVIDER, + hostname_provider_init)) enum { DEVICE_ADDED, @@ -321,6 +326,18 @@ aipd_handle_event (DBusGProxy *proxy, nm_warning ("Unhandled avahi-autoipd event for '%s'", iface); } +static const char * +hostname_provider_get_hostname (NMHostnameProvider *provider) +{ + return NM_MANAGER_GET_PRIVATE (provider)->hostname; +} + +static void +hostname_provider_init (NMHostnameProvider *provider_class) +{ + provider_class->get_hostname = hostname_provider_get_hostname; +} + static void nm_manager_init (NMManager *manager) {