platform/trivial: move code

This commit is contained in:
Thomas Haller 2015-10-13 17:53:23 +02:00
parent a0229badd8
commit f5171089af

View file

@ -127,6 +127,334 @@ static void cache_pre_hook (NMPCache *cache, const NMPObject *old, const NMPObje
static gboolean event_handler_read_netlink_all (NMPlatform *platform, gboolean wait_for_acks); static gboolean event_handler_read_netlink_all (NMPlatform *platform, gboolean wait_for_acks);
static NMPCacheOpsType cache_remove_netlink (NMPlatform *platform, const NMPObject *obj_needle, NMPObject **out_obj_cache, gboolean *out_was_visible, NMPlatformReason reason); static NMPCacheOpsType cache_remove_netlink (NMPlatform *platform, const NMPObject *obj_needle, NMPObject **out_obj_cache, gboolean *out_was_visible, NMPlatformReason reason);
/******************************************************************
* Support IFLA_INET6_ADDR_GEN_MODE
******************************************************************/
#if HAVE_LIBNL_INET6_ADDR_GEN_MODE
static int _support_user_ipv6ll = 0;
#define _support_user_ipv6ll_still_undecided() (G_UNLIKELY (_support_user_ipv6ll == 0))
#else
#define _support_user_ipv6ll_still_undecided() (FALSE)
#endif
static gboolean
_support_user_ipv6ll_get (void)
{
#if HAVE_LIBNL_INET6_ADDR_GEN_MODE
if (_support_user_ipv6ll_still_undecided ()) {
_support_user_ipv6ll = -1;
_LOG2W ("kernel support for IFLA_INET6_ADDR_GEN_MODE %s", "failed to detect; assume no support");
} else
return _support_user_ipv6ll > 0;
#endif
return FALSE;
}
static void
_support_user_ipv6ll_detect (const struct rtnl_link *rtnl_link)
{
#if HAVE_LIBNL_INET6_ADDR_GEN_MODE
/* If we ever see a link with valid IPv6 link-local address
* generation modes, the kernel supports it.
*/
if (_support_user_ipv6ll_still_undecided ()) {
uint8_t mode;
if (rtnl_link_inet6_get_addr_gen_mode ((struct rtnl_link *) rtnl_link, &mode) == 0) {
_support_user_ipv6ll = 1;
_LOG2D ("kernel support for IFLA_INET6_ADDR_GEN_MODE %s", "detected");
} else {
_support_user_ipv6ll = -1;
_LOG2D ("kernel support for IFLA_INET6_ADDR_GEN_MODE %s", "not detected");
}
}
#endif
}
/******************************************************************
* Various utilities
******************************************************************/
static guint
_nm_ip_config_source_to_rtprot (NMIPConfigSource source)
{
switch (source) {
case NM_IP_CONFIG_SOURCE_UNKNOWN:
return RTPROT_UNSPEC;
case NM_IP_CONFIG_SOURCE_KERNEL:
case NM_IP_CONFIG_SOURCE_RTPROT_KERNEL:
return RTPROT_KERNEL;
case NM_IP_CONFIG_SOURCE_DHCP:
return RTPROT_DHCP;
case NM_IP_CONFIG_SOURCE_RDISC:
return RTPROT_RA;
default:
return RTPROT_STATIC;
}
}
static NMIPConfigSource
_nm_ip_config_source_from_rtprot (guint rtprot)
{
switch (rtprot) {
case RTPROT_UNSPEC:
return NM_IP_CONFIG_SOURCE_UNKNOWN;
case RTPROT_KERNEL:
return NM_IP_CONFIG_SOURCE_RTPROT_KERNEL;
case RTPROT_REDIRECT:
return NM_IP_CONFIG_SOURCE_KERNEL;
case RTPROT_RA:
return NM_IP_CONFIG_SOURCE_RDISC;
case RTPROT_DHCP:
return NM_IP_CONFIG_SOURCE_DHCP;
default:
return NM_IP_CONFIG_SOURCE_USER;
}
}
static void
clear_host_address (int family, const void *network, int plen, void *dst)
{
g_return_if_fail (plen == (guint8)plen);
g_return_if_fail (network);
switch (family) {
case AF_INET:
*((in_addr_t *) dst) = nm_utils_ip4_address_clear_host_address (*((in_addr_t *) network), plen);
break;
case AF_INET6:
nm_utils_ip6_address_clear_host_address ((struct in6_addr *) dst, (const struct in6_addr *) network, plen);
break;
default:
g_assert_not_reached ();
}
}
/******************************************************************
* NMLinkType functions
******************************************************************/
typedef struct {
const NMLinkType nm_type;
const char *type_string;
/* IFLA_INFO_KIND / rtnl_link_get_type() where applicable; the rtnl type
* should only be specified if the device type can be created without
* additional parameters, and if the device type can be determined from
* the rtnl_type. eg, tun/tap should not be specified since both
* tun and tap devices use "tun", and InfiniBand should not be
* specified because a PKey is required at creation. Drivers set this
* value from their 'struct rtnl_link_ops' structure.
*/
const char *rtnl_type;
/* uevent DEVTYPE where applicable, from /sys/class/net/<ifname>/uevent;
* drivers set this value from their SET_NETDEV_DEV() call and the
* 'struct device_type' name member.
*/
const char *devtype;
} LinkDesc;
static const LinkDesc linktypes[] = {
{ NM_LINK_TYPE_NONE, "none", NULL, NULL },
{ NM_LINK_TYPE_UNKNOWN, "unknown", NULL, NULL },
{ NM_LINK_TYPE_ETHERNET, "ethernet", NULL, NULL },
{ NM_LINK_TYPE_INFINIBAND, "infiniband", NULL, NULL },
{ NM_LINK_TYPE_OLPC_MESH, "olpc-mesh", NULL, NULL },
{ NM_LINK_TYPE_WIFI, "wifi", NULL, "wlan" },
{ NM_LINK_TYPE_WWAN_ETHERNET, "wwan", NULL, "wwan" },
{ NM_LINK_TYPE_WIMAX, "wimax", "wimax", "wimax" },
{ NM_LINK_TYPE_DUMMY, "dummy", "dummy", NULL },
{ NM_LINK_TYPE_GRE, "gre", "gre", NULL },
{ NM_LINK_TYPE_GRETAP, "gretap", "gretap", NULL },
{ NM_LINK_TYPE_IFB, "ifb", "ifb", NULL },
{ NM_LINK_TYPE_LOOPBACK, "loopback", NULL, NULL },
{ NM_LINK_TYPE_MACVLAN, "macvlan", "macvlan", NULL },
{ NM_LINK_TYPE_MACVTAP, "macvtap", "macvtap", NULL },
{ NM_LINK_TYPE_OPENVSWITCH, "openvswitch", "openvswitch", NULL },
{ NM_LINK_TYPE_TAP, "tap", NULL, NULL },
{ NM_LINK_TYPE_TUN, "tun", NULL, NULL },
{ NM_LINK_TYPE_VETH, "veth", "veth", NULL },
{ NM_LINK_TYPE_VLAN, "vlan", "vlan", "vlan" },
{ NM_LINK_TYPE_VXLAN, "vxlan", "vxlan", "vxlan" },
{ NM_LINK_TYPE_BNEP, "bluetooth", NULL, "bluetooth" },
{ NM_LINK_TYPE_BRIDGE, "bridge", "bridge", "bridge" },
{ NM_LINK_TYPE_BOND, "bond", "bond", "bond" },
{ NM_LINK_TYPE_TEAM, "team", "team", NULL },
};
static const char *
nm_link_type_to_rtnl_type_string (NMLinkType type)
{
int i;
for (i = 0; i < G_N_ELEMENTS (linktypes); i++) {
if (type == linktypes[i].nm_type)
return linktypes[i].rtnl_type;
}
g_return_val_if_reached (NULL);
}
const char *
nm_link_type_to_string (NMLinkType type)
{
int i;
for (i = 0; i < G_N_ELEMENTS (linktypes); i++) {
if (type == linktypes[i].nm_type)
return linktypes[i].type_string;
}
g_return_val_if_reached (NULL);
}
/******************************************************************
* Utilities
******************************************************************/
/* _timestamp_nl_to_ms:
* @timestamp_nl: a timestamp from ifa_cacheinfo.
* @monotonic_ms: *now* in CLOCK_MONOTONIC. Needed to estimate the current
* uptime and how often timestamp_nl wrapped.
*
* Convert the timestamp from ifa_cacheinfo to CLOCK_MONOTONIC milliseconds.
* The ifa_cacheinfo fields tstamp and cstamp contains timestamps that counts
* with in 1/100th of a second of clock_gettime(CLOCK_MONOTONIC). However,
* the uint32 counter wraps every 497 days of uptime, so we have to compensate
* for that. */
static gint64
_timestamp_nl_to_ms (guint32 timestamp_nl, gint64 monotonic_ms)
{
const gint64 WRAP_INTERVAL = (((gint64) G_MAXUINT32) + 1) * (1000 / 100);
gint64 timestamp_nl_ms;
/* convert timestamp from 1/100th of a second to msec. */
timestamp_nl_ms = ((gint64) timestamp_nl) * (1000 / 100);
/* timestamp wraps every 497 days. Try to compensate for that.*/
if (timestamp_nl_ms > monotonic_ms) {
/* timestamp_nl_ms is in the future. Truncate it to *now* */
timestamp_nl_ms = monotonic_ms;
} else if (monotonic_ms >= WRAP_INTERVAL) {
timestamp_nl_ms += (monotonic_ms / WRAP_INTERVAL) * WRAP_INTERVAL;
if (timestamp_nl_ms > monotonic_ms)
timestamp_nl_ms -= WRAP_INTERVAL;
}
return timestamp_nl_ms;
}
static guint32
_rtnl_addr_last_update_time_to_nm (const struct rtnl_addr *rtnladdr, gint32 *out_now_nm)
{
guint32 last_update_time = rtnl_addr_get_last_update_time ((struct rtnl_addr *) rtnladdr);
struct timespec tp;
gint64 now_nl, now_nm, result;
int err;
/* timestamp is unset. Default to 1. */
if (!last_update_time) {
if (out_now_nm)
*out_now_nm = 0;
return 1;
}
/* do all the calculations in milliseconds scale */
err = clock_gettime (CLOCK_MONOTONIC, &tp);
g_assert (err == 0);
now_nm = nm_utils_get_monotonic_timestamp_ms ();
now_nl = (((gint64) tp.tv_sec) * ((gint64) 1000)) +
(tp.tv_nsec / (NM_UTILS_NS_PER_SECOND/1000));
result = now_nm - (now_nl - _timestamp_nl_to_ms (last_update_time, now_nl));
if (out_now_nm)
*out_now_nm = now_nm / 1000;
/* converting the last_update_time into nm_utils_get_monotonic_timestamp_ms() scale is
* a good guess but fails in the following situations:
*
* - If the address existed before start of the process, the timestamp in nm scale would
* be negative or zero. In this case we default to 1.
* - during hibernation, the CLOCK_MONOTONIC/last_update_time drifts from
* nm_utils_get_monotonic_timestamp_ms() scale.
*/
if (result <= 1000)
return 1;
if (result > now_nm)
return now_nm / 1000;
return result / 1000;
}
static guint32
_extend_lifetime (guint32 lifetime, guint32 seconds)
{
guint64 v;
if ( lifetime == NM_PLATFORM_LIFETIME_PERMANENT
|| seconds == 0)
return lifetime;
v = (guint64) lifetime + (guint64) seconds;
return MIN (v, 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.
**/
static void
_nlo_rtnl_addr_get_lifetimes (const struct rtnl_addr *rtnladdr,
guint32 *out_timestamp,
guint32 *out_lifetime,
guint32 *out_preferred)
{
guint32 timestamp = 0;
gint32 now;
guint32 lifetime = rtnl_addr_get_valid_lifetime ((struct rtnl_addr *) rtnladdr);
guint32 preferred = rtnl_addr_get_preferred_lifetime ((struct rtnl_addr *) rtnladdr);
if ( lifetime != NM_PLATFORM_LIFETIME_PERMANENT
|| preferred != NM_PLATFORM_LIFETIME_PERMANENT) {
if (preferred > lifetime)
preferred = lifetime;
timestamp = _rtnl_addr_last_update_time_to_nm (rtnladdr, &now);
if (now == 0) {
/* strange. failed to detect the last-update time and assumed that timestamp is 1. */
nm_assert (timestamp == 1);
now = nm_utils_get_monotonic_timestamp_s ();
}
if (timestamp < now) {
guint32 diff = now - timestamp;
lifetime = _extend_lifetime (lifetime, diff);
preferred = _extend_lifetime (preferred, diff);
} else
nm_assert (timestamp == now);
}
*out_timestamp = timestamp;
*out_lifetime = lifetime;
*out_preferred = preferred;
}
/****************************************************************** /******************************************************************
* libnl unility functions and wrappers * libnl unility functions and wrappers
******************************************************************/ ******************************************************************/
@ -513,50 +841,6 @@ errout:
/******************************************************************/ /******************************************************************/
#if HAVE_LIBNL_INET6_ADDR_GEN_MODE
static int _support_user_ipv6ll = 0;
#define _support_user_ipv6ll_still_undecided() (G_UNLIKELY (_support_user_ipv6ll == 0))
#else
#define _support_user_ipv6ll_still_undecided() (FALSE)
#endif
static gboolean
_support_user_ipv6ll_get (void)
{
#if HAVE_LIBNL_INET6_ADDR_GEN_MODE
if (_support_user_ipv6ll_still_undecided ()) {
_support_user_ipv6ll = -1;
_LOG2W ("kernel support for IFLA_INET6_ADDR_GEN_MODE %s", "failed to detect; assume no support");
} else
return _support_user_ipv6ll > 0;
#endif
return FALSE;
}
static void
_support_user_ipv6ll_detect (const struct rtnl_link *rtnl_link)
{
#if HAVE_LIBNL_INET6_ADDR_GEN_MODE
/* If we ever see a link with valid IPv6 link-local address
* generation modes, the kernel supports it.
*/
if (_support_user_ipv6ll_still_undecided ()) {
uint8_t mode;
if (rtnl_link_inet6_get_addr_gen_mode ((struct rtnl_link *) rtnl_link, &mode) == 0) {
_support_user_ipv6ll = 1;
_LOG2D ("kernel support for IFLA_INET6_ADDR_GEN_MODE %s", "detected");
} else {
_support_user_ipv6ll = -1;
_LOG2D ("kernel support for IFLA_INET6_ADDR_GEN_MODE %s", "not detected");
}
}
#endif
}
/******************************************************************/
static int _support_kernel_extended_ifa_flags = 0; static int _support_kernel_extended_ifa_flags = 0;
#define _support_kernel_extended_ifa_flags_still_undecided() (G_UNLIKELY (_support_kernel_extended_ifa_flags == 0)) #define _support_kernel_extended_ifa_flags_still_undecided() (G_UNLIKELY (_support_kernel_extended_ifa_flags == 0))
@ -596,127 +880,6 @@ _support_kernel_extended_ifa_flags_get (void)
return _support_kernel_extended_ifa_flags > 0; return _support_kernel_extended_ifa_flags > 0;
} }
/******************************************************************
* Object type specific utilities
******************************************************************/
static guint
_nm_ip_config_source_to_rtprot (NMIPConfigSource source)
{
switch (source) {
case NM_IP_CONFIG_SOURCE_UNKNOWN:
return RTPROT_UNSPEC;
case NM_IP_CONFIG_SOURCE_KERNEL:
case NM_IP_CONFIG_SOURCE_RTPROT_KERNEL:
return RTPROT_KERNEL;
case NM_IP_CONFIG_SOURCE_DHCP:
return RTPROT_DHCP;
case NM_IP_CONFIG_SOURCE_RDISC:
return RTPROT_RA;
default:
return RTPROT_STATIC;
}
}
static NMIPConfigSource
_nm_ip_config_source_from_rtprot (guint rtprot)
{
switch (rtprot) {
case RTPROT_UNSPEC:
return NM_IP_CONFIG_SOURCE_UNKNOWN;
case RTPROT_KERNEL:
return NM_IP_CONFIG_SOURCE_RTPROT_KERNEL;
case RTPROT_REDIRECT:
return NM_IP_CONFIG_SOURCE_KERNEL;
case RTPROT_RA:
return NM_IP_CONFIG_SOURCE_RDISC;
case RTPROT_DHCP:
return NM_IP_CONFIG_SOURCE_DHCP;
default:
return NM_IP_CONFIG_SOURCE_USER;
}
}
/******************************************************************/
typedef struct {
const NMLinkType nm_type;
const char *type_string;
/* IFLA_INFO_KIND / rtnl_link_get_type() where applicable; the rtnl type
* should only be specified if the device type can be created without
* additional parameters, and if the device type can be determined from
* the rtnl_type. eg, tun/tap should not be specified since both
* tun and tap devices use "tun", and InfiniBand should not be
* specified because a PKey is required at creation. Drivers set this
* value from their 'struct rtnl_link_ops' structure.
*/
const char *rtnl_type;
/* uevent DEVTYPE where applicable, from /sys/class/net/<ifname>/uevent;
* drivers set this value from their SET_NETDEV_DEV() call and the
* 'struct device_type' name member.
*/
const char *devtype;
} LinkDesc;
static const LinkDesc linktypes[] = {
{ NM_LINK_TYPE_NONE, "none", NULL, NULL },
{ NM_LINK_TYPE_UNKNOWN, "unknown", NULL, NULL },
{ NM_LINK_TYPE_ETHERNET, "ethernet", NULL, NULL },
{ NM_LINK_TYPE_INFINIBAND, "infiniband", NULL, NULL },
{ NM_LINK_TYPE_OLPC_MESH, "olpc-mesh", NULL, NULL },
{ NM_LINK_TYPE_WIFI, "wifi", NULL, "wlan" },
{ NM_LINK_TYPE_WWAN_ETHERNET, "wwan", NULL, "wwan" },
{ NM_LINK_TYPE_WIMAX, "wimax", "wimax", "wimax" },
{ NM_LINK_TYPE_DUMMY, "dummy", "dummy", NULL },
{ NM_LINK_TYPE_GRE, "gre", "gre", NULL },
{ NM_LINK_TYPE_GRETAP, "gretap", "gretap", NULL },
{ NM_LINK_TYPE_IFB, "ifb", "ifb", NULL },
{ NM_LINK_TYPE_LOOPBACK, "loopback", NULL, NULL },
{ NM_LINK_TYPE_MACVLAN, "macvlan", "macvlan", NULL },
{ NM_LINK_TYPE_MACVTAP, "macvtap", "macvtap", NULL },
{ NM_LINK_TYPE_OPENVSWITCH, "openvswitch", "openvswitch", NULL },
{ NM_LINK_TYPE_TAP, "tap", NULL, NULL },
{ NM_LINK_TYPE_TUN, "tun", NULL, NULL },
{ NM_LINK_TYPE_VETH, "veth", "veth", NULL },
{ NM_LINK_TYPE_VLAN, "vlan", "vlan", "vlan" },
{ NM_LINK_TYPE_VXLAN, "vxlan", "vxlan", "vxlan" },
{ NM_LINK_TYPE_BNEP, "bluetooth", NULL, "bluetooth" },
{ NM_LINK_TYPE_BRIDGE, "bridge", "bridge", "bridge" },
{ NM_LINK_TYPE_BOND, "bond", "bond", "bond" },
{ NM_LINK_TYPE_TEAM, "team", "team", NULL },
};
static const char *
nm_link_type_to_rtnl_type_string (NMLinkType type)
{
int i;
for (i = 0; i < G_N_ELEMENTS (linktypes); i++) {
if (type == linktypes[i].nm_type)
return linktypes[i].rtnl_type;
}
g_return_val_if_reached (NULL);
}
const char *
nm_link_type_to_string (NMLinkType type)
{
int i;
for (i = 0; i < G_N_ELEMENTS (linktypes); i++) {
if (type == linktypes[i].nm_type)
return linktypes[i].type_string;
}
g_return_val_if_reached (NULL);
}
/****************************************************************** /******************************************************************
* NMPlatform types and functions * NMPlatform types and functions
******************************************************************/ ******************************************************************/
@ -1096,143 +1259,6 @@ _nmp_vt_cmd_plobj_init_from_nl_link (NMPlatform *platform, NMPlatformObject *_ob
return TRUE; return TRUE;
} }
/* _timestamp_nl_to_ms:
* @timestamp_nl: a timestamp from ifa_cacheinfo.
* @monotonic_ms: *now* in CLOCK_MONOTONIC. Needed to estimate the current
* uptime and how often timestamp_nl wrapped.
*
* Convert the timestamp from ifa_cacheinfo to CLOCK_MONOTONIC milliseconds.
* The ifa_cacheinfo fields tstamp and cstamp contains timestamps that counts
* with in 1/100th of a second of clock_gettime(CLOCK_MONOTONIC). However,
* the uint32 counter wraps every 497 days of uptime, so we have to compensate
* for that. */
static gint64
_timestamp_nl_to_ms (guint32 timestamp_nl, gint64 monotonic_ms)
{
const gint64 WRAP_INTERVAL = (((gint64) G_MAXUINT32) + 1) * (1000 / 100);
gint64 timestamp_nl_ms;
/* convert timestamp from 1/100th of a second to msec. */
timestamp_nl_ms = ((gint64) timestamp_nl) * (1000 / 100);
/* timestamp wraps every 497 days. Try to compensate for that.*/
if (timestamp_nl_ms > monotonic_ms) {
/* timestamp_nl_ms is in the future. Truncate it to *now* */
timestamp_nl_ms = monotonic_ms;
} else if (monotonic_ms >= WRAP_INTERVAL) {
timestamp_nl_ms += (monotonic_ms / WRAP_INTERVAL) * WRAP_INTERVAL;
if (timestamp_nl_ms > monotonic_ms)
timestamp_nl_ms -= WRAP_INTERVAL;
}
return timestamp_nl_ms;
}
static guint32
_rtnl_addr_last_update_time_to_nm (const struct rtnl_addr *rtnladdr, gint32 *out_now_nm)
{
guint32 last_update_time = rtnl_addr_get_last_update_time ((struct rtnl_addr *) rtnladdr);
struct timespec tp;
gint64 now_nl, now_nm, result;
int err;
/* timestamp is unset. Default to 1. */
if (!last_update_time) {
if (out_now_nm)
*out_now_nm = 0;
return 1;
}
/* do all the calculations in milliseconds scale */
err = clock_gettime (CLOCK_MONOTONIC, &tp);
g_assert (err == 0);
now_nm = nm_utils_get_monotonic_timestamp_ms ();
now_nl = (((gint64) tp.tv_sec) * ((gint64) 1000)) +
(tp.tv_nsec / (NM_UTILS_NS_PER_SECOND/1000));
result = now_nm - (now_nl - _timestamp_nl_to_ms (last_update_time, now_nl));
if (out_now_nm)
*out_now_nm = now_nm / 1000;
/* converting the last_update_time into nm_utils_get_monotonic_timestamp_ms() scale is
* a good guess but fails in the following situations:
*
* - If the address existed before start of the process, the timestamp in nm scale would
* be negative or zero. In this case we default to 1.
* - during hibernation, the CLOCK_MONOTONIC/last_update_time drifts from
* nm_utils_get_monotonic_timestamp_ms() scale.
*/
if (result <= 1000)
return 1;
if (result > now_nm)
return now_nm / 1000;
return result / 1000;
}
static guint32
_extend_lifetime (guint32 lifetime, guint32 seconds)
{
guint64 v;
if ( lifetime == NM_PLATFORM_LIFETIME_PERMANENT
|| seconds == 0)
return lifetime;
v = (guint64) lifetime + (guint64) seconds;
return MIN (v, 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.
**/
static void
_nlo_rtnl_addr_get_lifetimes (const struct rtnl_addr *rtnladdr,
guint32 *out_timestamp,
guint32 *out_lifetime,
guint32 *out_preferred)
{
guint32 timestamp = 0;
gint32 now;
guint32 lifetime = rtnl_addr_get_valid_lifetime ((struct rtnl_addr *) rtnladdr);
guint32 preferred = rtnl_addr_get_preferred_lifetime ((struct rtnl_addr *) rtnladdr);
if ( lifetime != NM_PLATFORM_LIFETIME_PERMANENT
|| preferred != NM_PLATFORM_LIFETIME_PERMANENT) {
if (preferred > lifetime)
preferred = lifetime;
timestamp = _rtnl_addr_last_update_time_to_nm (rtnladdr, &now);
if (now == 0) {
/* strange. failed to detect the last-update time and assumed that timestamp is 1. */
nm_assert (timestamp == 1);
now = nm_utils_get_monotonic_timestamp_s ();
}
if (timestamp < now) {
guint32 diff = now - timestamp;
lifetime = _extend_lifetime (lifetime, diff);
preferred = _extend_lifetime (preferred, diff);
} else
nm_assert (timestamp == now);
}
*out_timestamp = timestamp;
*out_lifetime = lifetime;
*out_preferred = preferred;
}
gboolean gboolean
_nmp_vt_cmd_plobj_init_from_nl_ip4_address (NMPlatform *platform, NMPlatformObject *_obj, const struct nl_object *_nlo, gboolean id_only, gboolean complete_from_cache) _nmp_vt_cmd_plobj_init_from_nl_ip4_address (NMPlatform *platform, NMPlatformObject *_obj, const struct nl_object *_nlo, gboolean id_only, gboolean complete_from_cache)
{ {
@ -4305,24 +4331,6 @@ ip6_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteFlags fl
return ipx_route_get_all (platform, ifindex, NMP_OBJECT_TYPE_IP6_ROUTE, flags); return ipx_route_get_all (platform, ifindex, NMP_OBJECT_TYPE_IP6_ROUTE, flags);
} }
static void
clear_host_address (int family, const void *network, int plen, void *dst)
{
g_return_if_fail (plen == (guint8)plen);
g_return_if_fail (network);
switch (family) {
case AF_INET:
*((in_addr_t *) dst) = nm_utils_ip4_address_clear_host_address (*((in_addr_t *) network), plen);
break;
case AF_INET6:
nm_utils_ip6_address_clear_host_address ((struct in6_addr *) dst, (const struct in6_addr *) network, plen);
break;
default:
g_assert_not_reached ();
}
}
static struct nl_object * static struct nl_object *
build_rtnl_route (int family, int ifindex, NMIPConfigSource source, build_rtnl_route (int family, int ifindex, NMIPConfigSource source,
gconstpointer network, int plen, gconstpointer gateway, gconstpointer network, int plen, gconstpointer gateway,