platform: handle unset address timestamp as *now* in to_string()

When printing an address in nm_platform_ip4_address_to_string()
and nm_platform_ip6_address_to_string() treat an unset @timestamp
as counting from @now.

This is useful, if you just have the remaining lifetime at hand
and want to print an address. In general it is not a good idea to
leave the timestamp not anchored to an absolute @timestamp.

Signed-off-by: Thomas Haller <thaller@redhat.com>
This commit is contained in:
Thomas Haller 2014-06-09 10:03:01 +02:00 committed by Dan Williams
parent 2d37fedcd3
commit 1184cadc7d
2 changed files with 39 additions and 10 deletions

View file

@ -1436,6 +1436,7 @@ nm_platform_ip4_address_add (int ifindex,
addr.address = address;
addr.peer_address = peer_address;
addr.plen = plen;
addr.timestamp = 0; /* set it at zero, which to_string will treat as *now* */
addr.lifetime = lifetime;
addr.preferred = preferred;
if (label)
@ -1470,6 +1471,7 @@ nm_platform_ip6_address_add (int ifindex,
addr.address = address;
addr.peer_address = peer_address;
addr.plen = plen;
addr.timestamp = 0; /* set it to zero, which to_string will treat as *now* */
addr.lifetime = lifetime;
addr.preferred = preferred;
addr.flags = flags;
@ -1571,6 +1573,17 @@ _rebase_relative_time_on_now (guint32 timestamp, guint32 duration, guint32 now,
if (duration == NM_PLATFORM_LIFETIME_PERMANENT)
return NM_PLATFORM_LIFETIME_PERMANENT;
if (timestamp == 0) {
/* if the @timestamp is zero, assume it was just left unset and that the relative
* @duration starts counting from @now. This is convenient to construct an address
* and print it in nm_platform_ip4_address_to_string().
*
* In general it does not make sense to set the @duration without anchoring at
* @timestamp because you don't know the absolute expiration time when looking
* at the address at a later moment. */
timestamp = now;
}
/* For timestamp > now, just accept it and calculate the expected(?) result. */
t = (gint64) timestamp + (gint64) duration - (gint64) now;
@ -1597,13 +1610,18 @@ _address_get_lifetime (const NMPlatformIPAddress *address, guint32 now, guint32
if (!lifetime)
return FALSE;
preferred = _rebase_relative_time_on_now (address->timestamp, address->preferred, now, padding);
if (preferred > lifetime) {
g_warn_if_reached ();
preferred = lifetime;
}
*out_lifetime = lifetime;
*out_preferred = preferred;
*out_preferred = MIN (preferred, lifetime);
/* Assert that non-permanent addresses have a (positive) @timestamp. _rebase_relative_time_on_now()
* treats addresses with timestamp 0 as *now*. Addresses passed to _address_get_lifetime() always
* should have a valid @timestamp, otherwise on every re-sync, their lifetime will be extended anew.
*/
g_return_val_if_fail ( address->timestamp != 0
|| ( address->lifetime == NM_PLATFORM_LIFETIME_PERMANENT
&& address->preferred == NM_PLATFORM_LIFETIME_PERMANENT), TRUE);
g_return_val_if_fail (preferred <= lifetime, TRUE);
}
return TRUE;
}

View file

@ -167,11 +167,22 @@ typedef struct {
NMPlatformSource source; \
\
/* Timestamp in seconds in the reference system of nm_utils_get_monotonic_timestamp_*().
* This value is mainly used to anchor the relative lifetime and preferred values.
* For addresses originating from DHCP it might be set to nm_utils_get_monotonic_timestamp_s()
* of when the lease was received. For addresses from platform/kernel it might be set to
* when the address was last modified. For permanent addresses it is mostly set to 0.
* For non-permanent addresses it should not be 0 (because 0 is not a valid timestamp).
*
* The rules are:
* 1 @lifetime==0: @timestamp and @preferred is irrelevant (but mostly set to 0 too). Such addresses
* are permanent. This rule is so that unset addresses (calloc) are permanent by default.
* 2 @lifetime==@preferred==NM_PLATFORM_LIFETIME_PERMANENT: @timestamp is irrelevant (but mostly
* set to 0). Such addresses are permanent.
* 3 Non permanent addreses should (almost) always have @timestamp > 0. 0 is not a valid timestamp
* and never returned by nm_utils_get_monotonic_timestamp_s(). In this case @valid/@preferred
* is anchored at @timestamp.
* 4 Non permanent addresses with @timestamp == 0 are implicitely anchored at *now*, thus the time
* moves as time goes by. This is usually not useful, except e.g. nm_platform_ip[46]_address_add().
*
* Non permanent addresses from DHCP/RA might have the @timestamp set to the moment of when the
* lease was received. Addresses from kernel might have the @timestamp based on the last modification
* time of the addresses. But don't rely on this behaviour, the @timestamp is only defined for anchoring
* @lifetime and @preferred.
*/ \
guint32 timestamp; \
guint32 lifetime; /* seconds since timestamp */ \