From 1f383bc53fc5d8d3a34e51f1023b29e7436d83c0 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 28 Jan 2014 21:25:34 +0100 Subject: [PATCH] core: support renaming of NMDevice (changes of ifname) https://bugzilla.gnome.org/show_bug.cgi?id=726177 https://bugzilla.redhat.com/show_bug.cgi?id=907836 Signed-off-by: Thomas Haller --- src/devices/nm-device-private.h | 1 + src/devices/nm-device.c | 128 +++++++++++++++++++++++++++----- 2 files changed, 110 insertions(+), 19 deletions(-) diff --git a/src/devices/nm-device-private.h b/src/devices/nm-device-private.h index e5c9942b3..8dae02e0b 100644 --- a/src/devices/nm-device-private.h +++ b/src/devices/nm-device-private.h @@ -79,6 +79,7 @@ void nm_device_set_dhcp_timeout (NMDevice *device, guint32 timeout); void nm_device_set_dhcp_anycast_address (NMDevice *device, guint8 *addr); gboolean nm_device_dhcp4_renew (NMDevice *device, gboolean release); +gboolean nm_device_dhcp6_renew (NMDevice *device, gboolean release); void nm_device_recheck_available_connections (NMDevice *device); diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index fb37c968d..20970d122 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -339,6 +339,7 @@ static gboolean spec_match_list (NMDevice *device, const GSList *specs); static void _clear_available_connections (NMDevice *device, gboolean do_signal); static void dhcp4_cleanup (NMDevice *self, gboolean stop, gboolean release); +static void dhcp6_cleanup (NMDevice *self, gboolean stop, gboolean release); static const char *reason_to_string (NMDeviceStateReason reason); @@ -1121,32 +1122,96 @@ link_changed_cb (NMPlatform *platform, int ifindex, NMPlatformLink *info, NMPlat { NMDeviceClass *klass = NM_DEVICE_GET_CLASS (device); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + int my_ifindex = nm_device_get_ifindex (device); + gboolean change_ip_ifname = FALSE; /* Ignore other devices. */ - if (ifindex != nm_device_get_ifindex (device)) - return; + if (ifindex == my_ifindex) { - /* We don't filter by 'reason' because we are interested in *all* link - * changes. For example a call to nm_platform_link_set_up() may result - * in an internal carrier change (i.e. we ask the kernel to set IFF_UP - * and it results in also setting IFF_LOWER_UP. - */ + /* We don't filter by 'reason' because we are interested in *all* link + * changes. For example a call to nm_platform_link_set_up() may result + * in an internal carrier change (i.e. we ask the kernel to set IFF_UP + * and it results in also setting IFF_LOWER_UP. + */ - if (info->udi && g_strcmp0 (info->udi, priv->udi)) { - /* Update UDI to what udev gives us */ - g_free (priv->udi); - priv->udi = g_strdup (info->udi); - g_object_notify (G_OBJECT (device), NM_DEVICE_UDI); + if (info->udi && g_strcmp0 (info->udi, priv->udi)) { + /* Update UDI to what udev gives us */ + g_free (priv->udi); + priv->udi = g_strdup (info->udi); + g_object_notify (G_OBJECT (device), NM_DEVICE_UDI); + } + + /* Update MTU if it has changed. */ + if (priv->mtu != info->mtu) { + priv->mtu = info->mtu; + g_object_notify (G_OBJECT (device), NM_DEVICE_MTU); + } + + if (info->name[0] && strcmp (priv->iface, info->name) != 0) { + nm_log_info (LOGD_DEVICE, "(%s): interface index %d renamed iface from '%s' to '%s'", + priv->iface, my_ifindex, priv->iface, info->name); + g_free (priv->iface); + priv->iface = g_strdup (info->name); + + change_ip_ifname = !priv->ip_iface; + if (change_ip_ifname) + g_hash_table_remove_all (priv->ip6_saved_properties); + + g_object_notify (G_OBJECT (device), NM_DEVICE_IFACE); + if (change_ip_ifname) + g_object_notify (G_OBJECT (device), NM_DEVICE_IP_IFACE); + + /* Re-match available connections against the new interface name */ + nm_device_recheck_available_connections (device); + + /* Let any connections that use the new interface name have a chance + * to auto-activate on the device. + */ + nm_device_emit_recheck_auto_activate (device); + } + + if (klass->link_changed) + klass->link_changed (device, info); + + } else if (priv->ip_iface && ifindex == nm_device_get_ip_ifindex (device)) { + if (info->name[0] && strcmp (priv->ip_iface, info->name)) { + nm_log_info (LOGD_DEVICE, "(%s): interface index %d renamed ip_iface (%d) from '%s' to '%s'", + priv->iface, my_ifindex, nm_device_get_ip_ifindex (device), + priv->ip_iface, info->name); + g_free (priv->ip_iface); + priv->ip_iface = g_strdup (info->name); + + g_hash_table_remove_all (priv->ip6_saved_properties); + + g_object_notify (G_OBJECT (device), NM_DEVICE_IP_IFACE); + change_ip_ifname = TRUE; + } } - /* Update MTU if it has changed. */ - if (priv->mtu != info->mtu) { - priv->mtu = info->mtu; - g_object_notify (G_OBJECT (device), NM_DEVICE_MTU); + if (change_ip_ifname) { + if (priv->dhcp4_client) { + if (!nm_device_dhcp4_renew (device, FALSE)) { + nm_device_state_changed (device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_DHCP_FAILED); + return; + } + } + if (priv->dhcp6_client) { + if (!nm_device_dhcp6_renew (device, FALSE)) { + nm_device_state_changed (device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_DHCP_FAILED); + return; + } + } + if (priv->rdisc) { + /* FIXME: todo */ + } + if (priv->dnsmasq_manager) { + /* FIXME: todo */ + } } - - if (klass->link_changed) - klass->link_changed (device, info); } static void @@ -3167,6 +3232,31 @@ dhcp6_start (NMDevice *self, return ret; } +gboolean +nm_device_dhcp6_renew (NMDevice *self, gboolean release) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMActStageReturn ret; + NMDeviceStateReason reason; + NMConnection *connection; + + g_return_val_if_fail (priv->dhcp6_client != NULL, FALSE); + + nm_log_info (LOGD_DHCP6, "(%s): DHCPv6 lease renewal requested", + nm_device_get_iface (self)); + + /* Terminate old DHCP instance and release the old lease */ + dhcp6_cleanup (self, TRUE, release); + + connection = nm_device_get_connection (self); + g_assert (connection); + + /* Start DHCP again on the interface */ + ret = dhcp6_start (self, connection, priv->dhcp6_mode, &reason); + + return (ret != NM_ACT_STAGE_RETURN_FAILURE); +} + /******************************************/ static gboolean