mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-03-28 13:20:41 +01:00
platform: merge branch 'th/bgo727382_platform_fix_addr_lifetime'
https://bugzilla.gnome.org/show_bug.cgi?id=727382 Signed-off-by: Thomas Haller <thaller@redhat.com>
This commit is contained in:
commit
fcc34ef77b
7 changed files with 306 additions and 47 deletions
|
|
@ -1050,6 +1050,33 @@ monotonic_timestamp_get (struct timespec *tp)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_utils_get_monotonic_timestamp_ns:
|
||||
*
|
||||
* Returns: a monotonically increasing time stamp in nanoseconds,
|
||||
* starting at an unspecified offset. See clock_gettime(), %CLOCK_BOOTTIME.
|
||||
*
|
||||
* The returned value will start counting at an undefined point
|
||||
* in the past and will always be positive.
|
||||
*
|
||||
* All the nm_utils_get_monotonic_timestamp_*s functions return the same
|
||||
* timestamp but in different scales (nsec, usec, msec, sec).
|
||||
**/
|
||||
gint64
|
||||
nm_utils_get_monotonic_timestamp_ns (void)
|
||||
{
|
||||
struct timespec tp;
|
||||
|
||||
monotonic_timestamp_get (&tp);
|
||||
|
||||
/* Although the result will always be positive, we return a signed
|
||||
* integer, which makes it easier to calculate time differences (when
|
||||
* you want to subtract signed values).
|
||||
**/
|
||||
return (((gint64) tp.tv_sec) + monotonic_timestamp_offset_sec) * NM_UTILS_NS_PER_SECOND +
|
||||
tp.tv_nsec;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_utils_get_monotonic_timestamp_us:
|
||||
*
|
||||
|
|
@ -1058,6 +1085,9 @@ monotonic_timestamp_get (struct timespec *tp)
|
|||
*
|
||||
* The returned value will start counting at an undefined point
|
||||
* in the past and will always be positive.
|
||||
*
|
||||
* All the nm_utils_get_monotonic_timestamp_*s functions return the same
|
||||
* timestamp but in different scales (nsec, usec, msec, sec).
|
||||
**/
|
||||
gint64
|
||||
nm_utils_get_monotonic_timestamp_us (void)
|
||||
|
|
@ -1082,6 +1112,9 @@ nm_utils_get_monotonic_timestamp_us (void)
|
|||
*
|
||||
* The returned value will start counting at an undefined point
|
||||
* in the past and will always be positive.
|
||||
*
|
||||
* All the nm_utils_get_monotonic_timestamp_*s functions return the same
|
||||
* timestamp but in different scales (nsec, usec, msec, sec).
|
||||
**/
|
||||
gint64
|
||||
nm_utils_get_monotonic_timestamp_ms (void)
|
||||
|
|
@ -1106,6 +1139,9 @@ nm_utils_get_monotonic_timestamp_ms (void)
|
|||
*
|
||||
* This value wraps after roughly 68 years which should be fine for any
|
||||
* practical purpose.
|
||||
*
|
||||
* All the nm_utils_get_monotonic_timestamp_*s functions return the same
|
||||
* timestamp but in different scales (nsec, usec, msec, sec).
|
||||
**/
|
||||
gint32
|
||||
nm_utils_get_monotonic_timestamp_s (void)
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ NMConnection *nm_utils_match_connection (GSList *connections,
|
|||
gint64 nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback);
|
||||
|
||||
#define NM_UTILS_NS_PER_SECOND ((gint64) 1000000000)
|
||||
gint64 nm_utils_get_monotonic_timestamp_ns (void);
|
||||
gint64 nm_utils_get_monotonic_timestamp_us (void);
|
||||
gint64 nm_utils_get_monotonic_timestamp_ms (void);
|
||||
gint32 nm_utils_get_monotonic_timestamp_s (void);
|
||||
|
|
|
|||
|
|
@ -3601,6 +3601,8 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *device
|
|||
address.timestamp = discovered_address->timestamp;
|
||||
address.lifetime = discovered_address->lifetime;
|
||||
address.preferred = discovered_address->preferred;
|
||||
if (address.preferred > address.lifetime)
|
||||
address.preferred = address.lifetime;
|
||||
address.source = NM_PLATFORM_SOURCE_RDISC;
|
||||
address.flags = ifa_flags;
|
||||
|
||||
|
|
|
|||
|
|
@ -136,6 +136,53 @@ _nl_has_capability (int capability)
|
|||
|
||||
/******************************************************************/
|
||||
|
||||
static guint32
|
||||
_get_expiry (guint32 now_s, guint32 lifetime_s)
|
||||
{
|
||||
gint64 t = ((gint64) now_s) + ((gint64) lifetime_s);
|
||||
|
||||
return MIN (t, NM_PLATFORM_LIFETIME_PERMANENT - 1);
|
||||
}
|
||||
|
||||
/* The rtnl_addr object contains relative lifetimes @valid and @preferred
|
||||
* that count in seconds, starting from the moment when the kernel constructed
|
||||
* the netlink message.
|
||||
*
|
||||
* There is also a field rtnl_addr_last_update_time(), which is the absolute
|
||||
* time in 1/100th of a second of clock_gettime (CLOCK_MONOTONIC) when the address
|
||||
* was modified (wrapping every 497 days).
|
||||
* Immediately at the time when the address was last modified, #NOW and @last_update_time
|
||||
* are the same, so (only) in that case @valid and @preferred are anchored at @last_update_time.
|
||||
* However, this is not true in general. As time goes by, whenever kernel sends a new address
|
||||
* via netlink, the lifetimes keep counting down.
|
||||
*
|
||||
* As we cache the rtnl_addr object we must know the absolute expiries.
|
||||
* As a hack, modify the relative timestamps valid and preferred into absolute
|
||||
* timestamps of scale nm_utils_get_monotonic_timestamp_s().
|
||||
**/
|
||||
static void
|
||||
_rtnl_addr_hack_lifetimes_rel_to_abs (struct rtnl_addr *rtnladdr)
|
||||
{
|
||||
guint32 a_valid = rtnl_addr_get_valid_lifetime (rtnladdr);
|
||||
guint32 a_preferred = rtnl_addr_get_preferred_lifetime (rtnladdr);
|
||||
guint32 now;
|
||||
|
||||
if (a_valid == NM_PLATFORM_LIFETIME_PERMANENT &&
|
||||
a_preferred == NM_PLATFORM_LIFETIME_PERMANENT)
|
||||
return;
|
||||
|
||||
now = (guint32) nm_utils_get_monotonic_timestamp_s ();
|
||||
|
||||
if (a_preferred > a_valid)
|
||||
a_preferred = a_valid;
|
||||
|
||||
if (a_valid != NM_PLATFORM_LIFETIME_PERMANENT)
|
||||
rtnl_addr_set_valid_lifetime (rtnladdr, _get_expiry (now, a_valid));
|
||||
rtnl_addr_set_preferred_lifetime (rtnladdr, _get_expiry (now, a_preferred));
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
/* libnl library workarounds and additions */
|
||||
|
||||
/* Automatic deallocation of local variables */
|
||||
|
|
@ -402,6 +449,9 @@ get_kernel_object (struct nl_sock *sock, struct nl_object *needle)
|
|||
|
||||
nl_cache_free (cache);
|
||||
|
||||
if (object && (type == OBJECT_TYPE_IP4_ADDRESS || type == OBJECT_TYPE_IP6_ADDRESS))
|
||||
_rtnl_addr_hack_lifetimes_rel_to_abs ((struct rtnl_addr *) object);
|
||||
|
||||
if (object)
|
||||
debug ("get_kernel_object for type %d returned %p", type, object);
|
||||
else
|
||||
|
|
@ -982,6 +1032,53 @@ hack_empty_master_iff_lower_up (NMPlatform *platform, struct nl_object *object)
|
|||
rtnl_link_unset_flags (rtnllink, IFF_LOWER_UP);
|
||||
}
|
||||
|
||||
static void
|
||||
_init_ip_address_lifetime (NMPlatformIPAddress *address, const struct rtnl_addr *rtnladdr)
|
||||
{
|
||||
guint32 a_valid = rtnl_addr_get_valid_lifetime ((struct rtnl_addr *) rtnladdr);
|
||||
guint32 a_preferred = rtnl_addr_get_preferred_lifetime ((struct rtnl_addr *) rtnladdr);
|
||||
|
||||
/* the meaning of the valid and preferred lifetimes is different from the
|
||||
* original meaning. See _rtnl_addr_hack_lifetimes_rel_to_abs().
|
||||
* Beware: this function expects hacked rtnl_addr objects.
|
||||
*/
|
||||
|
||||
if (a_valid == NM_PLATFORM_LIFETIME_PERMANENT &&
|
||||
a_preferred == NM_PLATFORM_LIFETIME_PERMANENT) {
|
||||
address->timestamp = 0;
|
||||
address->lifetime = NM_PLATFORM_LIFETIME_PERMANENT;
|
||||
address->preferred = NM_PLATFORM_LIFETIME_PERMANENT;
|
||||
return;
|
||||
}
|
||||
|
||||
/* The valies are hacked and absolute expiry times. They must
|
||||
* be positive and preferred<=valid. */
|
||||
g_assert (a_preferred <= a_valid &&
|
||||
a_valid > 0 &&
|
||||
a_preferred > 0);
|
||||
|
||||
/* The correct timestamp value would probably be rtnl_addr_get_last_update_time()
|
||||
* (after converting into the proper time scale).
|
||||
* But this is relatively complicated to convert and we don't actually need it.
|
||||
* Especially, because rtnl_addr_get_last_update_time() might be negative in
|
||||
* nm_utils_get_monotonic_timestamp_s() scale -- which we want to avoid.
|
||||
*
|
||||
* Remember: timestamp has no meaning, beyond anchoring the relative lifetimes
|
||||
* at some point in time. We choose this point to be "1 second".
|
||||
*/
|
||||
address->timestamp = 1;
|
||||
|
||||
/* account for the timestamp==1 by incrementing valid/preferred -- unless
|
||||
* it is NM_PLATFORM_LIFETIME_PERMANENT or already NM_PLATFORM_LIFETIME_PERMANENT-1
|
||||
* (i.e. the largest non-permanent lifetime). */
|
||||
if (a_valid < NM_PLATFORM_LIFETIME_PERMANENT - 1)
|
||||
a_valid += 1;
|
||||
if (a_preferred < NM_PLATFORM_LIFETIME_PERMANENT - 1)
|
||||
a_preferred += 1;
|
||||
address->lifetime = a_valid;
|
||||
address->preferred = a_preferred + 1;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
init_ip4_address (NMPlatformIP4Address *address, struct rtnl_addr *rtnladdr)
|
||||
{
|
||||
|
|
@ -993,11 +1090,10 @@ init_ip4_address (NMPlatformIP4Address *address, struct rtnl_addr *rtnladdr)
|
|||
|
||||
memset (address, 0, sizeof (*address));
|
||||
|
||||
address->source = NM_PLATFORM_SOURCE_KERNEL;
|
||||
address->ifindex = rtnl_addr_get_ifindex (rtnladdr);
|
||||
address->plen = rtnl_addr_get_prefixlen (rtnladdr);
|
||||
address->timestamp = nm_utils_get_monotonic_timestamp_s ();
|
||||
address->lifetime = rtnl_addr_get_valid_lifetime (rtnladdr);
|
||||
address->preferred = rtnl_addr_get_preferred_lifetime (rtnladdr);
|
||||
_init_ip_address_lifetime ((NMPlatformIPAddress *) address, rtnladdr);
|
||||
if (!nladdr || nl_addr_get_len (nladdr) != sizeof (address->address)) {
|
||||
g_return_val_if_reached (FALSE);
|
||||
return FALSE;
|
||||
|
|
@ -1026,11 +1122,10 @@ init_ip6_address (NMPlatformIP6Address *address, struct rtnl_addr *rtnladdr)
|
|||
|
||||
memset (address, 0, sizeof (*address));
|
||||
|
||||
address->source = NM_PLATFORM_SOURCE_KERNEL;
|
||||
address->ifindex = rtnl_addr_get_ifindex (rtnladdr);
|
||||
address->plen = rtnl_addr_get_prefixlen (rtnladdr);
|
||||
address->timestamp = nm_utils_get_monotonic_timestamp_s ();
|
||||
address->lifetime = rtnl_addr_get_valid_lifetime (rtnladdr);
|
||||
address->preferred = rtnl_addr_get_preferred_lifetime (rtnladdr);
|
||||
_init_ip_address_lifetime ((NMPlatformIPAddress *) address, rtnladdr);
|
||||
address->flags = rtnl_addr_get_flags (rtnladdr);
|
||||
if (!nladdr || nl_addr_get_len (nladdr) != sizeof (address->address)) {
|
||||
g_return_val_if_reached (FALSE);
|
||||
|
|
@ -1610,6 +1705,22 @@ ref_object (struct nl_object *obj, void *data)
|
|||
*out = obj;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_rtnl_addr_timestamps_equal_fuzzy (guint32 ts1, guint32 ts2)
|
||||
{
|
||||
guint32 diff;
|
||||
|
||||
if (ts1 == ts2)
|
||||
return TRUE;
|
||||
if (ts1 == NM_PLATFORM_LIFETIME_PERMANENT ||
|
||||
ts2 == NM_PLATFORM_LIFETIME_PERMANENT)
|
||||
return FALSE;
|
||||
|
||||
/** accept the timestamps as equal if they are within two seconds. */
|
||||
diff = ts1 > ts2 ? ts1 - ts2 : ts2 - ts1;
|
||||
return diff <= 2;
|
||||
}
|
||||
|
||||
/* This function does all the magic to avoid race conditions caused
|
||||
* by concurrent usage of synchronous commands and an asynchronous cache. This
|
||||
* might be a nice future addition to libnl but it requires to do all operations
|
||||
|
|
@ -1627,6 +1738,7 @@ event_notification (struct nl_msg *msg, gpointer user_data)
|
|||
auto_nl_object struct nl_object *kernel_object = NULL;
|
||||
int event;
|
||||
int nle;
|
||||
ObjectType type;
|
||||
|
||||
event = nlmsg_hdr (msg)->nlmsg_type;
|
||||
|
||||
|
|
@ -1640,8 +1752,10 @@ event_notification (struct nl_msg *msg, gpointer user_data)
|
|||
nl_msg_parse (msg, ref_object, &object);
|
||||
g_return_val_if_fail (object, NL_OK);
|
||||
|
||||
type = object_type_from_nl_object (object);
|
||||
|
||||
if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) {
|
||||
if (object_type_from_nl_object (object) == OBJECT_TYPE_LINK) {
|
||||
if (type == OBJECT_TYPE_LINK) {
|
||||
const char *name = rtnl_link_get_name ((struct rtnl_link *) object);
|
||||
|
||||
debug ("netlink event (type %d) for link: %s (%d, family %d)",
|
||||
|
|
@ -1652,7 +1766,7 @@ event_notification (struct nl_msg *msg, gpointer user_data)
|
|||
debug ("netlink event (type %d)", event);
|
||||
}
|
||||
|
||||
cache = choose_cache (platform, object);
|
||||
cache = choose_cache_by_type (platform, type);
|
||||
cached_object = nm_nl_cache_search (cache, object);
|
||||
kernel_object = get_kernel_object (priv->nlh, object);
|
||||
|
||||
|
|
@ -1712,8 +1826,24 @@ event_notification (struct nl_msg *msg, gpointer user_data)
|
|||
* This also catches notifications for internal addition or change, unless
|
||||
* another action occured very soon after it.
|
||||
*/
|
||||
if (!nl_object_diff (kernel_object, cached_object))
|
||||
return NL_OK;
|
||||
if (!nl_object_diff (kernel_object, cached_object)) {
|
||||
if (type == OBJECT_TYPE_IP4_ADDRESS || type == OBJECT_TYPE_IP6_ADDRESS) {
|
||||
struct rtnl_addr *c = (struct rtnl_addr *) cached_object;
|
||||
struct rtnl_addr *k = (struct rtnl_addr *) kernel_object;
|
||||
|
||||
/* libnl nl_object_diff() ignores differences in timestamp. Let's care about
|
||||
* them (if they are large enough).
|
||||
*
|
||||
* Note that these valid and preferred timestamps are absolute, after
|
||||
* _rtnl_addr_hack_lifetimes_rel_to_abs(). */
|
||||
if ( _rtnl_addr_timestamps_equal_fuzzy (rtnl_addr_get_preferred_lifetime (c),
|
||||
rtnl_addr_get_preferred_lifetime (k))
|
||||
&& _rtnl_addr_timestamps_equal_fuzzy (rtnl_addr_get_valid_lifetime (c),
|
||||
rtnl_addr_get_valid_lifetime (k)))
|
||||
return NL_OK;
|
||||
} else
|
||||
return NL_OK;
|
||||
}
|
||||
/* Handle external change */
|
||||
nl_cache_remove (cached_object);
|
||||
nle = nl_cache_add (cache, kernel_object);
|
||||
|
|
@ -3086,10 +3216,8 @@ ip4_address_get_all (NMPlatform *platform, int ifindex)
|
|||
|
||||
for (object = nl_cache_get_first (priv->address_cache); object; object = nl_cache_get_next (object)) {
|
||||
if (_address_match ((struct rtnl_addr *) object, AF_INET, ifindex)) {
|
||||
if (init_ip4_address (&address, (struct rtnl_addr *) object)) {
|
||||
address.source = NM_PLATFORM_SOURCE_KERNEL;
|
||||
if (init_ip4_address (&address, (struct rtnl_addr *) object))
|
||||
g_array_append_val (addresses, address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3108,10 +3236,8 @@ ip6_address_get_all (NMPlatform *platform, int ifindex)
|
|||
|
||||
for (object = nl_cache_get_first (priv->address_cache); object; object = nl_cache_get_next (object)) {
|
||||
if (_address_match ((struct rtnl_addr *) object, AF_INET6, ifindex)) {
|
||||
if (init_ip6_address (&address, (struct rtnl_addr *) object)) {
|
||||
address.source = NM_PLATFORM_SOURCE_KERNEL;
|
||||
if (init_ip6_address (&address, (struct rtnl_addr *) object))
|
||||
g_array_append_val (addresses, address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3180,6 +3306,12 @@ build_rtnl_addr (int family,
|
|||
|
||||
rtnl_addr_set_prefixlen (rtnladdr, plen);
|
||||
if (lifetime) {
|
||||
/* note that here we set the relative timestamps (ticking from *now*).
|
||||
* Contrary to the rtnl_addr objects from our cache, which have absolute
|
||||
* timestamps (see _rtnl_addr_hack_lifetimes_rel_to_abs()).
|
||||
*
|
||||
* This is correct, because we only use build_rtnl_addr() for
|
||||
* add_object(), delete_object() and cache search (ip_address_exists). */
|
||||
rtnl_addr_set_valid_lifetime (rtnladdr, lifetime);
|
||||
rtnl_addr_set_preferred_lifetime (rtnladdr, preferred);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1425,6 +1425,7 @@ nm_platform_ip4_address_add (int ifindex,
|
|||
g_return_val_if_fail (ifindex > 0, FALSE);
|
||||
g_return_val_if_fail (plen > 0, FALSE);
|
||||
g_return_val_if_fail (lifetime > 0, FALSE);
|
||||
g_return_val_if_fail (preferred <= lifetime, FALSE);
|
||||
g_return_val_if_fail (klass->ip4_address_add, FALSE);
|
||||
g_return_val_if_fail (!label || strlen (label) < sizeof (((NMPlatformIP4Address *) NULL)->label), FALSE);
|
||||
|
||||
|
|
@ -1459,6 +1460,7 @@ nm_platform_ip6_address_add (int ifindex,
|
|||
g_return_val_if_fail (ifindex > 0, FALSE);
|
||||
g_return_val_if_fail (plen > 0, FALSE);
|
||||
g_return_val_if_fail (lifetime > 0, FALSE);
|
||||
g_return_val_if_fail (preferred <= lifetime, FALSE);
|
||||
g_return_val_if_fail (klass->ip6_address_add, FALSE);
|
||||
|
||||
if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) {
|
||||
|
|
@ -1557,14 +1559,53 @@ array_contains_ip6_address (const GArray *addresses, const NMPlatformIP6Address
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/* Compute (a - b) in an overflow-safe manner. */
|
||||
/**
|
||||
* Takes a pair @timestamp and @duration, and returns the remaining duration based
|
||||
* on the new timestamp @now.
|
||||
*/
|
||||
static guint32
|
||||
subtract_guint32 (guint32 a, guint32 b)
|
||||
_rebase_relative_time_on_now (guint32 timestamp, guint32 duration, guint32 now)
|
||||
{
|
||||
if (a == G_MAXUINT32)
|
||||
return G_MAXUINT32;
|
||||
gint64 t;
|
||||
|
||||
return a > b ? a - b : 0;
|
||||
if (duration == NM_PLATFORM_LIFETIME_PERMANENT)
|
||||
return NM_PLATFORM_LIFETIME_PERMANENT;
|
||||
|
||||
/* For timestamp>now, just accept it and calculate the expected(?) result. */
|
||||
t = (gint64) timestamp + (gint64) duration - (gint64) now;
|
||||
|
||||
/* Pad the timestamp by 5 seconds to avoid potential races. */
|
||||
t += 5;
|
||||
|
||||
if (t <= 0)
|
||||
return 0;
|
||||
if (t >= NM_PLATFORM_LIFETIME_PERMANENT)
|
||||
return NM_PLATFORM_LIFETIME_PERMANENT - 1;
|
||||
return t;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_address_get_lifetime (const NMPlatformIPAddress *address, guint32 now, guint32 *out_lifetime, guint32 *out_preferred)
|
||||
{
|
||||
gint32 lifetime, preferred;
|
||||
|
||||
if (address->lifetime == 0) {
|
||||
*out_lifetime = NM_PLATFORM_LIFETIME_PERMANENT;
|
||||
*out_preferred = NM_PLATFORM_LIFETIME_PERMANENT;
|
||||
} else {
|
||||
lifetime = _rebase_relative_time_on_now (address->timestamp, address->lifetime, now);
|
||||
if (!lifetime)
|
||||
return FALSE;
|
||||
preferred = _rebase_relative_time_on_now (address->timestamp, address->preferred, now);
|
||||
if (preferred > lifetime) {
|
||||
g_warn_if_reached ();
|
||||
preferred = lifetime;
|
||||
}
|
||||
|
||||
*out_lifetime = lifetime;
|
||||
*out_preferred = preferred;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1604,14 +1645,8 @@ nm_platform_ip4_address_sync (int ifindex, const GArray *known_addresses)
|
|||
const NMPlatformIP4Address *known_address = &g_array_index (known_addresses, NMPlatformIP4Address, i);
|
||||
guint32 lifetime, preferred;
|
||||
|
||||
if (known_address->lifetime) {
|
||||
/* Pad the timestamp by 5 seconds to avoid potential races. */
|
||||
guint32 shift = subtract_guint32 (now, known_address->timestamp + 5);
|
||||
|
||||
lifetime = subtract_guint32 (known_address->lifetime, shift);
|
||||
preferred = subtract_guint32 (known_address->lifetime, shift);
|
||||
} else
|
||||
lifetime = preferred = NM_PLATFORM_LIFETIME_PERMANENT;
|
||||
if (!_address_get_lifetime ((NMPlatformIPAddress *) known_address, now, &lifetime, &preferred))
|
||||
continue;
|
||||
|
||||
if (!nm_platform_ip4_address_add (ifindex, known_address->address, known_address->peer_address, known_address->plen, lifetime, preferred, known_address->label))
|
||||
return FALSE;
|
||||
|
|
@ -1661,14 +1696,8 @@ nm_platform_ip6_address_sync (int ifindex, const GArray *known_addresses)
|
|||
const NMPlatformIP6Address *known_address = &g_array_index (known_addresses, NMPlatformIP6Address, i);
|
||||
guint32 lifetime, preferred;
|
||||
|
||||
if (known_address->lifetime) {
|
||||
/* Pad the timestamp by 5 seconds to avoid potential races. */
|
||||
guint32 shift = subtract_guint32 (now, known_address->timestamp + 5);
|
||||
|
||||
lifetime = subtract_guint32 (known_address->lifetime, shift);
|
||||
preferred = subtract_guint32 (known_address->lifetime, shift);
|
||||
} else
|
||||
lifetime = preferred = NM_PLATFORM_LIFETIME_PERMANENT;
|
||||
if (!_address_get_lifetime ((NMPlatformIPAddress *) known_address, now, &lifetime, &preferred))
|
||||
continue;
|
||||
|
||||
if (!nm_platform_ip6_address_add (ifindex, known_address->address,
|
||||
known_address->peer_address, known_address->plen,
|
||||
|
|
@ -2043,6 +2072,32 @@ _to_string_dev (int ifindex, char *buf, size_t size)
|
|||
buf[0] = 0;
|
||||
}
|
||||
|
||||
static const char *
|
||||
_lifetime_to_string (guint32 timestamp, guint32 lifetime, gint32 now, char *buf, size_t buf_size)
|
||||
{
|
||||
if (lifetime == NM_PLATFORM_LIFETIME_PERMANENT)
|
||||
return "forever";
|
||||
|
||||
g_snprintf (buf, buf_size, "%dsec",
|
||||
_rebase_relative_time_on_now (timestamp, lifetime, now));
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
static const char *
|
||||
_lifetime_summary_to_string (gint32 now, guint32 timestamp, guint32 preferred, guint32 lifetime, char *buf, size_t buf_size)
|
||||
{
|
||||
if (timestamp == 0) {
|
||||
if (preferred == NM_PLATFORM_LIFETIME_PERMANENT && lifetime == NM_PLATFORM_LIFETIME_PERMANENT)
|
||||
return "";
|
||||
if (preferred == 0 && lifetime == 0)
|
||||
return " lifetime unset";
|
||||
}
|
||||
g_snprintf (buf, buf_size, " lifetime %d-%u[%u,%u]",
|
||||
(signed) now, (unsigned) timestamp, (unsigned) preferred, (unsigned) lifetime);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static char to_string_buffer[256];
|
||||
|
||||
const char *
|
||||
|
|
@ -2110,7 +2165,10 @@ nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address)
|
|||
char s_peer[INET_ADDRSTRLEN];
|
||||
char str_dev[TO_STRING_DEV_BUF_SIZE];
|
||||
char str_label[32];
|
||||
char str_lft[30], str_pref[30], str_time[50];
|
||||
char *str_peer = NULL;
|
||||
const char *str_lft_p, *str_pref_p, *str_time_p;
|
||||
gint32 now = nm_utils_get_monotonic_timestamp_s ();
|
||||
|
||||
g_return_val_if_fail (address, "(unknown)");
|
||||
|
||||
|
|
@ -2128,9 +2186,18 @@ nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address)
|
|||
else
|
||||
str_label[0] = 0;
|
||||
|
||||
g_snprintf (to_string_buffer, sizeof (to_string_buffer), "%s/%d lft %u pref %u time %u%s%s%s src %s",
|
||||
s_address, address->plen, (guint)address->lifetime, (guint)address->preferred,
|
||||
(guint)address->timestamp,
|
||||
str_lft_p = _lifetime_to_string (address->timestamp,
|
||||
address->lifetime ? address->lifetime : NM_PLATFORM_LIFETIME_PERMANENT,
|
||||
now, str_lft, sizeof (str_lft)),
|
||||
str_pref_p = (address->lifetime == address->preferred)
|
||||
? str_lft_p
|
||||
: ( _lifetime_to_string (address->timestamp,
|
||||
address->lifetime ? MIN (address->preferred, address->lifetime) : NM_PLATFORM_LIFETIME_PERMANENT,
|
||||
now, str_pref, sizeof (str_pref)) );
|
||||
str_time_p = _lifetime_summary_to_string (now, address->timestamp, address->preferred, address->lifetime, str_time, sizeof (str_time));
|
||||
|
||||
g_snprintf (to_string_buffer, sizeof (to_string_buffer), "%s/%d lft %s pref %s%s%s%s%s src %s",
|
||||
s_address, address->plen, str_lft_p, str_pref_p, str_time_p,
|
||||
str_peer ? str_peer : "",
|
||||
str_dev,
|
||||
str_label,
|
||||
|
|
@ -2181,9 +2248,12 @@ nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address)
|
|||
char s_flags[256];
|
||||
char s_address[INET6_ADDRSTRLEN];
|
||||
char s_peer[INET6_ADDRSTRLEN];
|
||||
char *str_flags;
|
||||
char str_lft[30], str_pref[30], str_time[50];
|
||||
char str_dev[TO_STRING_DEV_BUF_SIZE];
|
||||
char *str_flags;
|
||||
char *str_peer = NULL;
|
||||
const char *str_lft_p, *str_pref_p, *str_time_p;
|
||||
gint32 now = nm_utils_get_monotonic_timestamp_s ();
|
||||
|
||||
g_return_val_if_fail (address, "(unknown)");
|
||||
|
||||
|
|
@ -2200,9 +2270,18 @@ nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address)
|
|||
|
||||
str_flags = s_flags[0] ? g_strconcat (" flags ", s_flags, NULL) : NULL;
|
||||
|
||||
g_snprintf (to_string_buffer, sizeof (to_string_buffer), "%s/%d lft %u pref %u time %u%s%s%s src %s",
|
||||
s_address, address->plen, (guint)address->lifetime, (guint)address->preferred,
|
||||
(guint)address->timestamp,
|
||||
str_lft_p = _lifetime_to_string (address->timestamp,
|
||||
address->lifetime ? address->lifetime : NM_PLATFORM_LIFETIME_PERMANENT,
|
||||
now, str_lft, sizeof (str_lft)),
|
||||
str_pref_p = (address->lifetime == address->preferred)
|
||||
? str_lft_p
|
||||
: ( _lifetime_to_string (address->timestamp,
|
||||
address->lifetime ? MIN (address->preferred, address->lifetime) : NM_PLATFORM_LIFETIME_PERMANENT,
|
||||
now, str_pref, sizeof (str_pref)) );
|
||||
str_time_p = _lifetime_summary_to_string (now, address->timestamp, address->preferred, address->lifetime, str_time, sizeof (str_time));
|
||||
|
||||
g_snprintf (to_string_buffer, sizeof (to_string_buffer), "%s/%d lft %s pref %s%s%s%s%s src %s",
|
||||
s_address, address->plen, str_lft_p, str_pref_p, str_time_p,
|
||||
str_peer ? str_peer : "",
|
||||
str_dev,
|
||||
str_flags ? str_flags : "",
|
||||
|
|
|
|||
|
|
@ -165,9 +165,16 @@ typedef struct {
|
|||
#define __NMPlatformIPAddress_COMMON \
|
||||
__NMPlatformObject_COMMON; \
|
||||
NMPlatformSource source; \
|
||||
guint32 timestamp; /* nm_utils_get_monotonic_timestamp_s() */ \
|
||||
guint32 lifetime; /* seconds */ \
|
||||
guint32 preferred; /* seconds */ \
|
||||
\
|
||||
/* 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 is set to 1.
|
||||
* For permanent addresses it is mostly set to 0.
|
||||
*/ \
|
||||
guint32 timestamp; \
|
||||
guint32 lifetime; /* seconds since timestamp */ \
|
||||
guint32 preferred; /* seconds since timestamp */ \
|
||||
int plen; \
|
||||
;
|
||||
|
||||
|
|
|
|||
|
|
@ -547,6 +547,8 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
|||
address.timestamp = now;
|
||||
address.lifetime = ndp_msg_opt_prefix_valid_time (msg, offset);
|
||||
address.preferred = ndp_msg_opt_prefix_preferred_time (msg, offset);
|
||||
if (address.preferred > address.lifetime)
|
||||
address.preferred = address.lifetime;
|
||||
|
||||
fill_address_from_mac (&address.address, lladdr);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue