summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2018-02-09 16:29:36 +0100
committerThomas Haller <thaller@redhat.com>2018-02-09 17:40:01 +0100
commit5c4f4b354033607ac04d002da600348f0562773e (patch)
treecbc67fcec00128b62a36f24016fa4d612239372e
parent86a18b2df2dafdd6cdb120e07509d473d498a591 (diff)
downloadNetworkManager-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.c23
-rw-r--r--src/ndisc/nm-ndisc.c7
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);