From 8389888e08c0a71cb8fbf86487d9984efddacc29 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 9 Feb 2018 16:29:36 +0100 Subject: [PATCH] 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 5c4f4b354033607ac04d002da600348f0562773e) --- src/devices/nm-device.c | 23 ++++++++++++++++++++--- src/ndisc/nm-ndisc.c | 7 +++++-- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index e2747e8c6e..908f8000b7 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -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); diff --git a/src/ndisc/nm-ndisc.c b/src/ndisc/nm-ndisc.c index a02e4b7692..8269537798 100644 --- a/src/ndisc/nm-ndisc.c +++ b/src/ndisc/nm-ndisc.c @@ -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);