diff options
author | Thomas Haller <thaller@redhat.com> | 2018-02-09 16:29:36 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2018-02-09 17:40:01 +0100 |
commit | 5c4f4b354033607ac04d002da600348f0562773e (patch) | |
tree | cbc67fcec00128b62a36f24016fa4d612239372e | |
parent | 86a18b2df2dafdd6cdb120e07509d473d498a591 (diff) | |
download | NetworkManager-5c4f4b354033607ac04d002da600348f0562773e.tar.gz |
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.
-rw-r--r-- | src/devices/nm-device.c | 23 | ||||
-rw-r--r-- | 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 ea2c426e19..55252d58b3 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -2816,6 +2816,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; @@ -2827,12 +2829,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); |