summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/devices/nm-device.c33
-rw-r--r--src/dhcp-manager/nm-dhcp-client.c21
-rw-r--r--src/dhcp-manager/nm-dhcp-manager.c2
-rw-r--r--src/nm-iface-helper.c1
4 files changed, 48 insertions, 9 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index d983d7a5ed..f6ed4c2979 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -326,6 +326,8 @@ typedef struct {
NMDhcp6Config * dhcp6_config;
/* IP6 config from DHCP */
NMIP6Config * dhcp6_ip6_config;
+ /* Event ID of the current IP6 config from DHCP */
+ char * dhcp6_event_id;
/* allow autoconnect feature */
gboolean autoconnect;
@@ -3628,6 +3630,7 @@ dhcp4_state_changed (NMDhcpClient *client,
NMDhcpState state,
NMIP4Config *ip4_config,
GHashTable *options,
+ const char *event_id,
gpointer user_data)
{
NMDevice *self = NM_DEVICE (user_data);
@@ -4007,6 +4010,7 @@ dhcp6_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release)
priv->dhcp6_mode = NM_RDISC_DHCP_LEVEL_NONE;
g_clear_object (&priv->dhcp6_ip6_config);
+ g_clear_pointer (&priv->dhcp6_event_id, g_free);
if (priv->dhcp6_client) {
if (priv->dhcp6_state_sigid) {
@@ -4269,10 +4273,12 @@ dhcp6_state_changed (NMDhcpClient *client,
NMDhcpState state,
NMIP6Config *ip6_config,
GHashTable *options,
+ const char *event_id,
gpointer user_data)
{
NMDevice *self = NM_DEVICE (user_data);
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+ guint i;
g_return_if_fail (nm_dhcp_client_get_ipv6 (client) == TRUE);
g_return_if_fail (!ip6_config || NM_IS_IP6_CONFIG (ip6_config));
@@ -4281,11 +4287,27 @@ dhcp6_state_changed (NMDhcpClient *client,
switch (state) {
case NM_DHCP_STATE_BOUND:
- g_clear_object (&priv->dhcp6_ip6_config);
- if (ip6_config) {
- priv->dhcp6_ip6_config = g_object_ref (ip6_config);
- nm_dhcp6_config_set_options (priv->dhcp6_config, options);
- g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP6_CONFIG);
+ /* If the server sends multiple IPv6 addresses, we receive a state
+ * changed event for each of them. Use the event ID to merge IPv6
+ * addresses from the same transaction into a single configuration.
+ */
+ if ( ip6_config
+ && event_id
+ && priv->dhcp6_event_id
+ && !strcmp (event_id, priv->dhcp6_event_id)) {
+ for (i = 0; i < nm_ip6_config_get_num_addresses (ip6_config); i++) {
+ nm_ip6_config_add_address (priv->dhcp6_ip6_config,
+ nm_ip6_config_get_address (ip6_config, i));
+ }
+ } else {
+ g_clear_object (&priv->dhcp6_ip6_config);
+ g_clear_pointer (&priv->dhcp6_event_id, g_free);
+ if (ip6_config) {
+ priv->dhcp6_ip6_config = g_object_ref (ip6_config);
+ priv->dhcp6_event_id = g_strdup (event_id);
+ nm_dhcp6_config_set_options (priv->dhcp6_config, options);
+ g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP6_CONFIG);
+ }
}
if (priv->ip6_state == IP_CONF) {
@@ -4378,6 +4400,7 @@ dhcp6_start (NMDevice *self, gboolean wait_for_ll, NMDeviceStateReason *reason)
g_warn_if_fail (priv->dhcp6_ip6_config == NULL);
g_clear_object (&priv->dhcp6_ip6_config);
+ g_clear_pointer (&priv->dhcp6_event_id, g_free);
connection = nm_device_get_connection (self);
g_assert (connection);
diff --git a/src/dhcp-manager/nm-dhcp-client.c b/src/dhcp-manager/nm-dhcp-client.c
index c00782f963..caeba85b60 100644
--- a/src/dhcp-manager/nm-dhcp-client.c
+++ b/src/dhcp-manager/nm-dhcp-client.c
@@ -36,6 +36,7 @@
#include "nm-dhcp-client.h"
#include "nm-dhcp-utils.h"
#include "nm-platform.h"
+#include "gsystem-local-alloc.h"
typedef struct {
char * iface;
@@ -284,6 +285,7 @@ nm_dhcp_client_set_state (NMDhcpClient *self,
GHashTable *options)
{
NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
+ gs_free char *event_id = NULL;
if (new_state >= NM_DHCP_STATE_BOUND)
timeout_cleanup (self);
@@ -308,19 +310,30 @@ nm_dhcp_client_set_state (NMDhcpClient *self,
if ((priv->state == new_state) && (new_state != NM_DHCP_STATE_BOUND))
return;
+ if (priv->ipv6 && new_state == NM_DHCP_STATE_BOUND) {
+ char *start, *iaid;
+
+ iaid = g_hash_table_lookup (options, "iaid");
+ start = g_hash_table_lookup (options, "life_starts");
+ if (iaid && start)
+ event_id = g_strdup_printf ("%s|%s", iaid, start);
+ }
+
nm_log_info (priv->ipv6 ? LOGD_DHCP6 : LOGD_DHCP4,
- "(%s): DHCPv%c state changed %s -> %s",
+ "(%s): DHCPv%c state changed %s -> %s%s%s%s",
priv->iface,
priv->ipv6 ? '6' : '4',
state_to_string (priv->state),
- state_to_string (new_state));
+ state_to_string (new_state),
+ NM_PRINT_FMT_QUOTED (event_id, ", event ID=\"", event_id, "\"", ""));
priv->state = new_state;
g_signal_emit (G_OBJECT (self),
signals[SIGNAL_STATE_CHANGED], 0,
new_state,
ip_config,
- options);
+ options,
+ event_id);
}
static gboolean
@@ -979,6 +992,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, 3, G_TYPE_UINT, G_TYPE_OBJECT, G_TYPE_HASH_TABLE);
+ G_TYPE_NONE, 4, G_TYPE_UINT, G_TYPE_OBJECT, G_TYPE_HASH_TABLE, G_TYPE_STRING);
}
diff --git a/src/dhcp-manager/nm-dhcp-manager.c b/src/dhcp-manager/nm-dhcp-manager.c
index 0f2b8faeb3..cb349fc418 100644
--- a/src/dhcp-manager/nm-dhcp-manager.c
+++ b/src/dhcp-manager/nm-dhcp-manager.c
@@ -183,6 +183,7 @@ static void client_state_changed (NMDhcpClient *client,
NMDhcpState state,
GObject *ip_config,
GHashTable *options,
+ const char *event_id,
NMDhcpManager *self);
static void
@@ -203,6 +204,7 @@ client_state_changed (NMDhcpClient *client,
NMDhcpState state,
GObject *ip_config,
GHashTable *options,
+ const char *event_id,
NMDhcpManager *self)
{
if (state >= NM_DHCP_STATE_TIMEOUT)
diff --git a/src/nm-iface-helper.c b/src/nm-iface-helper.c
index a35d0d7c04..fac16d105d 100644
--- a/src/nm-iface-helper.c
+++ b/src/nm-iface-helper.c
@@ -88,6 +88,7 @@ dhcp4_state_changed (NMDhcpClient *client,
NMDhcpState state,
NMIP4Config *ip4_config,
GHashTable *options,
+ const char *event_id,
gpointer user_data)
{
static NMIP4Config *last_config = NULL;