core: Use tokenized identifiers when constructing an address

We trigger a new solicitation upon seeing the new token. Kernel triggers one
too, but that one is of no use to us, since the advertisement might arrive sooner
than we learn about the token change.
This commit is contained in:
Lubomir Rintel 2014-09-27 09:04:46 +02:00
parent db5603e615
commit 24e7ea7860
3 changed files with 42 additions and 6 deletions

View file

@ -1208,6 +1208,7 @@ device_link_changed (NMDevice *self, NMPlatformLink *info)
{
NMDeviceClass *klass = NM_DEVICE_GET_CLASS (self);
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
NMUtilsIPv6IfaceId token_iid;
gboolean ip_ifname_changed = FALSE;
if (info->udi && g_strcmp0 (info->udi, priv->udi)) {
@ -1254,6 +1255,12 @@ device_link_changed (NMDevice *self, NMPlatformLink *info)
nm_device_enslave_slave (priv->master, self, NULL);
}
if (priv->rdisc && nm_platform_link_get_ipv6_token (priv->ifindex, &token_iid)) {
_LOGD (LOGD_DEVICE, "IPv6 tokenized identifier present on device %s", priv->iface);
if (nm_rdisc_set_iid (priv->rdisc, token_iid))
nm_rdisc_start (priv->rdisc);
}
if (klass->link_changed)
klass->link_changed (self, info);
@ -4244,11 +4251,12 @@ addrconf6_start_with_link_ready (NMDevice *self)
g_assert (priv->rdisc);
if (!nm_device_get_ip_iface_identifier (self, &iid)) {
if (nm_platform_link_get_ipv6_token (priv->ifindex, &iid)) {
_LOGD (LOGD_DEVICE, "IPv6 tokenized identifier present on device %s", priv->iface);
} else if (!nm_device_get_ip_iface_identifier (self, &iid)) {
_LOGW (LOGD_IP6, "failed to get interface identifier; IPv6 cannot continue");
return FALSE;
}
nm_rdisc_set_iid (priv->rdisc, iid);
/* Apply any manual configuration before starting RA */
if (!ip6_config_merge_and_apply (self, TRUE, NULL))
@ -4267,6 +4275,8 @@ addrconf6_start_with_link_ready (NMDevice *self)
NM_RDISC_RA_TIMEOUT,
G_CALLBACK (rdisc_ra_timeout),
self);
nm_rdisc_set_iid (priv->rdisc, iid);
nm_rdisc_start (priv->rdisc);
return TRUE;
}

View file

@ -42,12 +42,38 @@ static guint signals[LAST_SIGNAL] = { 0 };
/******************************************************************/
void
/**
* nm_rdisc_set_iid:
* @rdisc: the #NMRDisc
* @iid: the new interface ID
*
* Sets the "Modified EUI-64" interface ID to be used when generating
* IPv6 addresses using received prefixes. Identifiers are either generated
* from the hardware addresses or manually set by the operator with
* "ip token" command.
*
* Upon token change (or initial setting) all addresses generated using
* the old identifier are removed. The caller should ensure the addresses
* will be reset by soliciting router advertisements.
*
* Returns: %TRUE if the token was changed, %FALSE otherwise.
**/
gboolean
nm_rdisc_set_iid (NMRDisc *rdisc, const NMUtilsIPv6IfaceId iid)
{
g_return_if_fail (NM_IS_RDISC (rdisc));
g_return_val_if_fail (NM_IS_RDISC (rdisc), FALSE);
rdisc->iid = iid;
if (rdisc->iid.id != iid.id) {
rdisc->iid = iid;
if (rdisc->addresses->len) {
debug ("(%s) IPv6 interface identifier changed, flushing addresses", rdisc->ifname);
g_array_remove_range (rdisc->addresses, 0, rdisc->addresses->len);
g_signal_emit_by_name (rdisc, NM_RDISC_CONFIG_CHANGED, NM_RDISC_CONFIG_ADDRESSES);
}
return TRUE;
}
return FALSE;
}
void

View file

@ -139,7 +139,7 @@ typedef struct {
GType nm_rdisc_get_type (void);
void nm_rdisc_set_iid (NMRDisc *rdisc, const NMUtilsIPv6IfaceId iid);
gboolean nm_rdisc_set_iid (NMRDisc *rdisc, const NMUtilsIPv6IfaceId iid);
void nm_rdisc_start (NMRDisc *rdisc);
#endif /* __NETWORKMANAGER_RDISC_H__ */