dhcp: pass DHCP options with BOUND state change

The options hash is never used except for BOUND events, so don't
bother caching it in the DHCP client object.  Just pass it along
with the BOUND state change, like the IP configuration object.
This commit is contained in:
Dan Williams 2014-07-01 12:30:29 -05:00
parent aff6a70c52
commit 6ffcde08dd
4 changed files with 94 additions and 106 deletions

View file

@ -2603,12 +2603,6 @@ dhcp4_cleanup (NMDevice *self, gboolean stop, gboolean release)
}
}
static void
dhcp4_add_option_cb (const char *key, const char *value, gpointer user_data)
{
nm_dhcp4_config_add_option (NM_DHCP4_CONFIG (user_data), key, value);
}
static gboolean
ip4_config_merge_and_apply (NMDevice *self,
NMIP4Config *config,
@ -2687,10 +2681,27 @@ dhcp4_fail (NMDevice *device, gboolean timeout)
nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED);
}
static void
dhcp4_update_config (NMDevice *self, NMDHCP4Config *config, GHashTable *options)
{
GHashTableIter iter;
const char *key, *value;
/* Update the DHCP4 config object with new DHCP options */
nm_dhcp4_config_reset (config);
g_hash_table_iter_init (&iter, options);
while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value))
nm_dhcp4_config_add_option (config, key, value);
g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP4_CONFIG);
}
static void
dhcp4_state_changed (NMDHCPClient *client,
NMDhcpState state,
NMIP4Config *ip4_config,
GHashTable *options,
gpointer user_data)
{
NMDevice *device = NM_DEVICE (user_data);
@ -2713,12 +2724,7 @@ dhcp4_state_changed (NMDHCPClient *client,
break;
}
/* Update the DHCP4 config object with new DHCP options */
nm_dhcp4_config_reset (priv->dhcp4_config);
nm_dhcp_client_foreach_option (priv->dhcp4_client,
dhcp4_add_option_cb,
priv->dhcp4_config);
g_object_notify (G_OBJECT (device), NM_DEVICE_DHCP4_CONFIG);
dhcp4_update_config (device, priv->dhcp4_config, options);
if (priv->ip4_state == IP_CONF)
nm_device_activate_schedule_ip4_config_result (device, ip4_config);
@ -3020,12 +3026,6 @@ dhcp6_cleanup (NMDevice *self, gboolean stop, gboolean release)
}
}
static void
dhcp6_add_option_cb (const char *key, const char *value, gpointer user_data)
{
nm_dhcp6_config_add_option (NM_DHCP6_CONFIG (user_data), key, value);
}
static gboolean
ip6_config_merge_and_apply (NMDevice *self,
gboolean commit,
@ -3123,10 +3123,27 @@ dhcp6_timeout (NMDevice *self, NMDHCPClient *client)
}
}
static void
dhcp6_update_config (NMDevice *self, NMDHCP6Config *config, GHashTable *options)
{
GHashTableIter iter;
const char *key, *value;
/* Update the DHCP6 config object with new DHCP options */
nm_dhcp6_config_reset (config);
g_hash_table_iter_init (&iter, options);
while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value))
nm_dhcp6_config_add_option (config, key, value);
g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP6_CONFIG);
}
static void
dhcp6_state_changed (NMDHCPClient *client,
NMDhcpState state,
NMIP6Config *ip6_config,
GHashTable *options,
gpointer user_data)
{
NMDevice *device = NM_DEVICE (user_data);
@ -3143,15 +3160,7 @@ dhcp6_state_changed (NMDHCPClient *client,
g_clear_object (&priv->dhcp6_ip6_config);
if (ip6_config) {
priv->dhcp6_ip6_config = g_object_ref (ip6_config);
/* Update the DHCP6 config object with new DHCP options */
nm_dhcp6_config_reset (priv->dhcp6_config);
if (priv->dhcp6_ip6_config) {
nm_dhcp_client_foreach_option (priv->dhcp6_client,
dhcp6_add_option_cb,
priv->dhcp6_config);
}
g_object_notify (G_OBJECT (device), NM_DEVICE_DHCP6_CONFIG);
dhcp6_update_config (device, priv->dhcp6_config, options);
}
if (priv->ip6_state == IP_CONF) {

View file

@ -49,7 +49,6 @@ typedef struct {
pid_t pid;
guint timeout_id;
guint watch_id;
GHashTable * options;
gboolean info_only;
} NMDHCPClientPrivate;
@ -173,35 +172,32 @@ stop (NMDHCPClient *self, gboolean release, const GByteArray *duid)
}
void
nm_dhcp_client_set_state (NMDHCPClient *self, NMDhcpState state)
nm_dhcp_client_set_state (NMDHCPClient *self,
NMDhcpState state,
GObject *ip_config,
GHashTable *options)
{
NMDHCPClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
NMIP4Config *ip4_config = NULL;
NMIP6Config *ip6_config = NULL;
priv->state = state;
if (priv->state == NM_DHCP_STATE_BOUND && g_hash_table_size (priv->options)) {
if (priv->ipv6) {
ip6_config = nm_dhcp_utils_ip6_config_from_options (priv->iface,
priv->options,
priv->priority,
priv->info_only);
g_warn_if_fail (ip6_config != NULL);
} else {
ip4_config = nm_dhcp_utils_ip4_config_from_options (priv->iface,
priv->options,
priv->priority);
g_warn_if_fail (ip4_config != NULL);
}
if (state == NM_DHCP_STATE_BOUND) {
/* Cancel the timeout if the DHCP client is now bound */
timeout_cleanup (self);
g_assert ( (priv->ipv6 && NM_IS_IP6_CONFIG (ip_config))
|| (!priv->ipv6 && NM_IS_IP4_CONFIG (ip_config)));
g_assert (options);
g_assert_cmpint (g_hash_table_size (options), >, 0);
} else {
g_assert (ip_config == NULL);
g_assert (options == NULL);
}
priv->state = state;
g_signal_emit (G_OBJECT (self),
signals[SIGNAL_STATE_CHANGED], 0,
state,
ip6_config ? (GObject *) ip6_config : (GObject *) ip4_config);
g_clear_object (&ip4_config);
g_clear_object (&ip6_config);
ip_config,
options);
}
static gboolean
@ -215,7 +211,7 @@ daemon_timeout (gpointer user_data)
"(%s): DHCPv%c request timed out.",
priv->iface,
priv->ipv6 ? '6' : '4');
nm_dhcp_client_set_state (self, NM_DHCP_STATE_TIMEOUT);
nm_dhcp_client_set_state (self, NM_DHCP_STATE_TIMEOUT, NULL, NULL);
return G_SOURCE_REMOVE;
}
@ -246,7 +242,7 @@ daemon_watch_cb (GPid pid, gint status, gpointer user_data)
timeout_cleanup (self);
priv->pid = -1;
nm_dhcp_client_set_state (self, new_state);
nm_dhcp_client_set_state (self, new_state, NULL, NULL);
}
void
@ -514,11 +510,10 @@ nm_dhcp_client_stop (NMDHCPClient *self, gboolean release)
g_assert (priv->pid == -1);
/* And clean stuff up */
g_hash_table_remove_all (priv->options);
timeout_cleanup (self);
watch_cleanup (self);
nm_dhcp_client_set_state (self, NM_DHCP_STATE_DONE);
nm_dhcp_client_set_state (self, NM_DHCP_STATE_DONE, NULL, NULL);
}
/********************************************/
@ -647,6 +642,8 @@ nm_dhcp_client_new_options (NMDHCPClient *self,
NMDHCPClientPrivate *priv;
guint32 old_state;
guint32 new_state;
GHashTable *str_options = NULL;
GObject *ip_config = NULL;
g_return_if_fail (NM_IS_DHCP_CLIENT (self));
g_return_if_fail (options != NULL);
@ -656,10 +653,6 @@ nm_dhcp_client_new_options (NMDHCPClient *self,
old_state = priv->state;
new_state = reason_to_state (priv->iface, reason);
/* Clear old and save new DHCP options */
g_hash_table_remove_all (priv->options);
g_hash_table_foreach (options, (GHFunc) copy_option, priv->options);
/* dhclient sends same-state transitions for RENEW/REBIND events, but
* the lease may have changed, so handle same-state transitions for
* these events. Ignore same-state transitions for other events since
@ -668,11 +661,6 @@ nm_dhcp_client_new_options (NMDHCPClient *self,
if ((old_state == new_state) && (new_state != NM_DHCP_STATE_BOUND))
return;
if (new_state == NM_DHCP_STATE_BOUND) {
/* Cancel the timeout if the DHCP client is now bound */
timeout_cleanup (self);
}
nm_log_info (priv->ipv6 ? LOGD_DHCP6 : LOGD_DHCP4,
"(%s): DHCPv%c state changed %s -> %s",
priv->iface,
@ -680,35 +668,33 @@ nm_dhcp_client_new_options (NMDHCPClient *self,
state_to_string (old_state),
state_to_string (new_state));
nm_dhcp_client_set_state (self, new_state);
}
if (new_state == NM_DHCP_STATE_BOUND) {
/* 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);
gboolean
nm_dhcp_client_foreach_option (NMDHCPClient *self,
NMDhcpClientForeachFunc callback,
gpointer user_data)
{
NMDHCPClientPrivate *priv;
GHashTableIter iter;
const char *key, *value;
g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), FALSE);
g_return_val_if_fail (callback != NULL, FALSE);
priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
if (priv->state != NM_DHCP_STATE_BOUND) {
nm_log_warn (priv->ipv6 ? LOGD_DHCP6 : LOGD_DHCP4,
"(%s): DHCPv%c client didn't bind to a lease.",
priv->iface,
priv->ipv6 ? '6' : '4');
/* Create the IP config */
g_warn_if_fail (g_hash_table_size (str_options));
if (g_hash_table_size (str_options)) {
if (priv->ipv6) {
ip_config = (GObject *) nm_dhcp_utils_ip6_config_from_options (priv->iface,
str_options,
priv->priority,
priv->info_only);
} else {
ip_config = (GObject *) nm_dhcp_utils_ip4_config_from_options (priv->iface,
str_options,
priv->priority);
}
g_warn_if_fail (ip_config != NULL);
}
}
g_hash_table_iter_init (&iter, priv->options);
while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value))
callback (key, value, user_data);
nm_dhcp_client_set_state (self, new_state, ip_config, str_options);
return TRUE;
if (str_options)
g_hash_table_destroy (str_options);
g_clear_object (&ip_config);
}
/********************************************/
@ -716,10 +702,7 @@ nm_dhcp_client_foreach_option (NMDHCPClient *self,
static void
nm_dhcp_client_init (NMDHCPClient *self)
{
NMDHCPClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
priv->options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
priv->pid = -1;
NM_DHCP_CLIENT_GET_PRIVATE (self)->pid = -1;
}
static void
@ -811,10 +794,6 @@ dispose (GObject *object)
watch_cleanup (self);
timeout_cleanup (self);
if (priv->options) {
g_hash_table_destroy (priv->options);
priv->options = NULL;
}
g_clear_pointer (&priv->iface, g_free);
if (priv->hwaddr) {
@ -900,6 +879,6 @@ nm_dhcp_client_class_init (NMDHCPClientClass *client_class)
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMDHCPClientClass, state_changed),
NULL, NULL, NULL,
G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_OBJECT);
G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_OBJECT, G_TYPE_HASH_TABLE);
}

View file

@ -90,7 +90,10 @@ typedef struct {
GByteArray * (*get_duid) (NMDHCPClient *self);
/* Signals */
void (*state_changed) (NMDHCPClient *self, NMDhcpState state, GObject *ip_config);
void (*state_changed) (NMDHCPClient *self,
NMDhcpState state,
GObject *ip_config,
GHashTable *options);
} NMDHCPClientClass;
GType nm_dhcp_client_get_type (void);
@ -121,14 +124,6 @@ void nm_dhcp_client_new_options (NMDHCPClient *self,
GHashTable *options,
const char *reason);
typedef void (*NMDhcpClientForeachFunc) (const char *key,
const char *value,
gpointer user_data);
gboolean nm_dhcp_client_foreach_option (NMDHCPClient *self,
NMDhcpClientForeachFunc callback,
gpointer user_data);
/* Backend helpers for subclasses */
void nm_dhcp_client_stop_existing (const char *pid_file, const char *binary_name);
@ -136,7 +131,10 @@ void nm_dhcp_client_stop_pid (pid_t pid, const char *iface);
void nm_dhcp_client_watch_child (NMDHCPClient *self, pid_t pid);
void nm_dhcp_client_set_state (NMDHCPClient *self, NMDhcpState state);
void nm_dhcp_client_set_state (NMDHCPClient *self,
NMDhcpState state,
GObject *ip_config, /* NMIP4Config or NMIP6Config */
GHashTable *options); /* str:str hash */
#endif /* NM_DHCP_CLIENT_H */

View file

@ -340,6 +340,7 @@ get_client_type (const char *client, GError **error)
static void client_state_changed (NMDHCPClient *client,
NMDhcpState state,
GObject *ip_config,
GHashTable *options,
NMDHCPManager *self);
static void
@ -359,6 +360,7 @@ static void
client_state_changed (NMDHCPClient *client,
NMDhcpState state,
GObject *ip_config,
GHashTable *options,
NMDHCPManager *self)
{
if (state >= NM_DHCP_STATE_TIMEOUT)