mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-08 08:20:28 +01:00
ndisc: only generate address interface identifer after checking existing prefix
RFC4862 5.5.3, points d) and e) make it clear, that the list of
addresses should be compared based on the prefix.
d) If the prefix advertised is not equal to the prefix of an
address configured by stateless autoconfiguration already in the
list of addresses associated with the interface (where "equal"
means the two prefix lengths are the same and the first prefix-
length bits of the prefixes are identical), and if the Valid
Lifetime is not 0, form an address (and add it to the list) by
combining the advertised prefix with an interface identifier of
the link as follows:
That means, we should not initialize the interface identifier first
(via complete_address()) and then search for the full address.
See-also: https://tools.ietf.org/search/rfc4862#section-5.5.3
(cherry picked from commit 23c417854a)
(cherry picked from commit ac5669633c)
(cherry picked from commit b2f084a8ae)
This commit is contained in:
parent
aeca2fb4b1
commit
d4b67b9441
2 changed files with 43 additions and 22 deletions
|
|
@ -40,7 +40,7 @@ void nm_ndisc_ra_received (NMNDisc *ndisc, gint32 now, NMNDiscConfigMap changed)
|
|||
void nm_ndisc_rs_received (NMNDisc *ndisc);
|
||||
|
||||
gboolean nm_ndisc_add_gateway (NMNDisc *ndisc, const NMNDiscGateway *new);
|
||||
gboolean nm_ndisc_complete_and_add_address (NMNDisc *ndisc, NMNDiscAddress *new);
|
||||
gboolean nm_ndisc_complete_and_add_address (NMNDisc *ndisc, const NMNDiscAddress *new);
|
||||
gboolean nm_ndisc_add_route (NMNDisc *ndisc, const NMNDiscRoute *new);
|
||||
gboolean nm_ndisc_add_dns_server (NMNDisc *ndisc, const NMNDiscDNSServer *new);
|
||||
gboolean nm_ndisc_add_dns_domain (NMNDisc *ndisc, const NMNDiscDNSDomain *new);
|
||||
|
|
|
|||
|
|
@ -406,10 +406,11 @@ complete_address (NMNDisc *ndisc, NMNDiscAddress *addr)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
nm_ndisc_add_address (NMNDisc *ndisc, const NMNDiscAddress *new)
|
||||
nm_ndisc_add_address (NMNDisc *ndisc, const NMNDiscAddress *new, gboolean from_ra)
|
||||
{
|
||||
NMNDiscPrivate *priv = NM_NDISC_GET_PRIVATE (ndisc);
|
||||
NMNDiscDataInternal *rdata = &priv->rdata;
|
||||
NMNDiscAddress new2;
|
||||
guint i;
|
||||
|
||||
nm_assert (new);
|
||||
|
|
@ -421,20 +422,33 @@ nm_ndisc_add_address (NMNDisc *ndisc, const NMNDiscAddress *new)
|
|||
for (i = 0; i < rdata->addresses->len; i++) {
|
||||
NMNDiscAddress *item = &g_array_index (rdata->addresses, NMNDiscAddress, i);
|
||||
|
||||
if (IN6_ARE_ADDR_EQUAL (&item->address, &new->address)) {
|
||||
if (new->lifetime == 0) {
|
||||
g_array_remove_index (rdata->addresses, i);
|
||||
return TRUE;
|
||||
}
|
||||
if (from_ra) {
|
||||
/* RFC4862 5.5.3.d, we find an existing address with the same prefix.
|
||||
* (note that all prefixes at this point have implicity length /64). */
|
||||
if (memcmp (&item->address, &new->address, 8) != 0)
|
||||
continue;
|
||||
} else {
|
||||
if (!IN6_ARE_ADDR_EQUAL (&item->address, &new->address))
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( item->dad_counter == new->dad_counter
|
||||
&& get_expiry (item) == get_expiry (new)
|
||||
&& get_expiry_preferred (item) == get_expiry_preferred (new))
|
||||
return FALSE;
|
||||
|
||||
*item = *new;
|
||||
if (new->lifetime == 0) {
|
||||
g_array_remove_index (rdata->addresses, i);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if ( get_expiry (item) == get_expiry (new)
|
||||
&& get_expiry_preferred (item) == get_expiry_preferred (new)
|
||||
&& ( from_ra
|
||||
|| item->dad_counter == new->dad_counter))
|
||||
return FALSE;
|
||||
|
||||
if (!from_ra)
|
||||
item->dad_counter = new->dad_counter;
|
||||
item->timestamp = new->timestamp;
|
||||
item->lifetime = new->lifetime;
|
||||
item->preferred = new->preferred;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* we create at most max_addresses autoconf addresses. This is different from
|
||||
|
|
@ -445,18 +459,25 @@ nm_ndisc_add_address (NMNDisc *ndisc, const NMNDiscAddress *new)
|
|||
&& rdata->addresses->len >= priv->max_addresses)
|
||||
return FALSE;
|
||||
|
||||
if (new->lifetime)
|
||||
g_array_append_val (rdata->addresses, *new);
|
||||
return !!new->lifetime;
|
||||
if (new->lifetime == 0)
|
||||
return FALSE;
|
||||
|
||||
if (from_ra) {
|
||||
new2 = *new;
|
||||
new2.dad_counter = 0;
|
||||
if (!complete_address (ndisc, &new2))
|
||||
return FALSE;
|
||||
new = &new2;
|
||||
}
|
||||
|
||||
g_array_append_val (rdata->addresses, *new);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_ndisc_complete_and_add_address (NMNDisc *ndisc, NMNDiscAddress *new)
|
||||
nm_ndisc_complete_and_add_address (NMNDisc *ndisc, const NMNDiscAddress *new)
|
||||
{
|
||||
if (!complete_address (ndisc, new))
|
||||
return FALSE;
|
||||
|
||||
return nm_ndisc_add_address (ndisc, new);
|
||||
return nm_ndisc_add_address (ndisc, new, TRUE);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
|
@ -754,7 +775,7 @@ nm_ndisc_set_config (NMNDisc *ndisc,
|
|||
guint i;
|
||||
|
||||
for (i = 0; i < addresses->len; i++) {
|
||||
if (nm_ndisc_add_address (ndisc, &g_array_index (addresses, NMNDiscAddress, i)))
|
||||
if (nm_ndisc_add_address (ndisc, &g_array_index (addresses, NMNDiscAddress, i), FALSE))
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue