ndisc: ensure proper lifetime of NMNDiscAddress in ndisc_set_router_config()

In ndisc_set_router_config(), we initialize NMNDiscAddress based on
NMPlatformIP6Address instances. Note that their handling of timestamps
is not entirely identical.

For convenience of the user, NMPlatformIP6Address allows to not specify
any timestamp. On the contrary, for convenience of implementation does
NMNDiscAddress always require fully specified timestamps.

Properly convert one representation into the other.

(cherry picked from commit 5c4f4b3540)
This commit is contained in:
Thomas Haller 2018-02-09 16:29:36 +01:00
parent 2ff8ece27e
commit 8389888e08
2 changed files with 25 additions and 5 deletions

View file

@ -2642,6 +2642,8 @@ ndisc_set_router_config (NMNDisc *ndisc, NMDevice *self)
nm_dedup_multi_iter_for_each (&ipconf_iter, head_entry) {
const NMPlatformIP6Address *addr = NMP_OBJECT_CAST_IP6_ADDRESS (ipconf_iter.current->obj);
NMNDiscAddress *ndisc_addr;
guint32 lifetime, preferred;
gint32 base;
if (IN6_IS_ADDR_LINKLOCAL (&addr->address))
continue;
@ -2653,12 +2655,27 @@ ndisc_set_router_config (NMNDisc *ndisc, NMDevice *self)
if (addr->plen != 64)
continue;
/* resolve the timestamps relative to a new base.
*
* Note that for convenience, platform @addr might have timestamp and/or
* lifetime unset. We don't allow that flexibility for ndisc and require
* well defined timestamps. */
if (addr->timestamp) {
nm_assert (addr->timestamp < G_MAXINT32);
base = addr->timestamp;
} else
base = now;
if (!nm_utils_lifetime_get (addr->timestamp, addr->lifetime, addr->preferred,
base, &lifetime, &preferred))
continue;
g_array_set_size (addresses, addresses->len+1);
ndisc_addr = &g_array_index (addresses, NMNDiscAddress, addresses->len-1);
ndisc_addr->address = addr->address;
ndisc_addr->timestamp = addr->timestamp;
ndisc_addr->lifetime = addr->lifetime;
ndisc_addr->preferred = addr->preferred;
ndisc_addr->timestamp = base;
ndisc_addr->lifetime = lifetime;
ndisc_addr->preferred = preferred;
}
len = nm_ip6_config_get_num_nameservers (priv->ip6_config);

View file

@ -349,6 +349,9 @@ nm_ndisc_add_address (NMNDisc *ndisc, const NMNDiscAddress *new)
NMNDiscDataInternal *rdata = &priv->rdata;
guint i;
nm_assert (new);
nm_assert (new->timestamp > 0 && new->timestamp < G_MAXINT32);
for (i = 0; i < rdata->addresses->len; i++) {
NMNDiscAddress *item = &g_array_index (rdata->addresses, NMNDiscAddress, i);
@ -936,7 +939,7 @@ _config_changed_log (NMNDisc *ndisc, NMNDiscConfigMap changed)
get_exp (str_exp, now_ns, gateway));
}
for (i = 0; i < rdata->addresses->len; i++) {
NMNDiscAddress *address = &g_array_index (rdata->addresses, NMNDiscAddress, i);
const NMNDiscAddress *address = &g_array_index (rdata->addresses, NMNDiscAddress, i);
inet_ntop (AF_INET6, &address->address, addrstr, sizeof (addrstr));
_LOGD (" address %s exp %s", addrstr,
@ -1003,7 +1006,7 @@ clean_addresses (NMNDisc *ndisc, gint32 now, NMNDiscConfigMap *changed, gint32 *
rdata = &NM_NDISC_GET_PRIVATE (ndisc)->rdata;
for (i = 0; i < rdata->addresses->len; ) {
NMNDiscAddress *item = &g_array_index (rdata->addresses, NMNDiscAddress, i);
const NMNDiscAddress *item = &g_array_index (rdata->addresses, NMNDiscAddress, i);
if (item->lifetime != NM_NDISC_INFINITY) {
gint32 expiry = get_expiry (item);