about summary refs log tree commit diff
path: root/src/platform/nm-linux-platform.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/platform/nm-linux-platform.c')
-rw-r--r--src/platform/nm-linux-platform.c61
1 files changed, 54 insertions, 7 deletions
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index e2ff1f61..3282e698 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -55,6 +55,8 @@
 #include "wifi/wifi-utils.h"
 #include "wifi/wifi-utils-wext.h"
 
+#define offset_plus_sizeof(t,m) (offsetof (t,m) + sizeof (((t *) NULL)->m))
+
 #define VLAN_FLAG_MVRP 0x8
 
 /* nm-internal error codes for libnl. Make sure they don't overlap. */
@@ -831,7 +833,7 @@ _parse_af_inet6 (NMPlatform *platform,
 {
 	static struct nla_policy policy[IFLA_INET6_MAX+1] = {
 		[IFLA_INET6_FLAGS]              = { .type = NLA_U32 },
-		[IFLA_INET6_CACHEINFO]          = { .minlen = sizeof(struct ifla_cacheinfo) },
+		[IFLA_INET6_CACHEINFO]          = { .minlen = offset_plus_sizeof(struct ifla_cacheinfo, retrans_time) },
 		[IFLA_INET6_CONF]               = { .minlen = 4 },
 		[IFLA_INET6_STATS]              = { .minlen = 8 },
 		[IFLA_INET6_ICMP6STATS]         = { .minlen = 8 },
@@ -1242,7 +1244,7 @@ _parse_lnk_vlan (const char *kind, struct nlattr *info_data)
 {
 	static struct nla_policy policy[IFLA_VLAN_MAX+1] = {
 		[IFLA_VLAN_ID]          = { .type = NLA_U16 },
-		[IFLA_VLAN_FLAGS]       = { .minlen = sizeof(struct ifla_vlan_flags) },
+		[IFLA_VLAN_FLAGS]       = { .minlen = offset_plus_sizeof(struct ifla_vlan_flags, flags) },
 		[IFLA_VLAN_INGRESS_QOS] = { .type = NLA_NESTED },
 		[IFLA_VLAN_EGRESS_QOS]  = { .type = NLA_NESTED },
 		[IFLA_VLAN_PROTOCOL]    = { .type = NLA_U16 },
@@ -1429,9 +1431,9 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr
 		[IFLA_LINKINFO]         = { .type = NLA_NESTED },
 		[IFLA_QDISC]            = { .type = NLA_STRING,
 		                            .maxlen = IFQDISCSIZ },
-		[IFLA_STATS]            = { .minlen = sizeof(struct rtnl_link_stats) },
-		[IFLA_STATS64]          = { .minlen = sizeof(struct rtnl_link_stats64)},
-		[IFLA_MAP]              = { .minlen = sizeof(struct rtnl_link_ifmap) },
+		[IFLA_STATS]            = { .minlen = offset_plus_sizeof(struct rtnl_link_stats, tx_compressed) },
+		[IFLA_STATS64]          = { .minlen = offset_plus_sizeof(struct rtnl_link_stats64, tx_compressed)},
+		[IFLA_MAP]              = { .minlen = offset_plus_sizeof(struct rtnl_link_ifmap, port) },
 		[IFLA_IFALIAS]          = { .type = NLA_STRING, .maxlen = IFALIASZ },
 		[IFLA_NUM_VF]           = { .type = NLA_U32 },
 		[IFLA_AF_SPEC]          = { .type = NLA_NESTED },
@@ -1612,7 +1614,7 @@ _new_from_nl_addr (struct nlmsghdr *nlh, gboolean id_only)
 	static struct nla_policy policy[IFA_MAX+1] = {
 		[IFA_LABEL]     = { .type = NLA_STRING,
 		                     .maxlen = IFNAMSIZ },
-		[IFA_CACHEINFO] = { .minlen = sizeof(struct ifa_cacheinfo) },
+		[IFA_CACHEINFO] = { .minlen = offset_plus_sizeof(struct ifa_cacheinfo, tstamp) },
 	};
 	const struct ifaddrmsg *ifa;
 	struct nlattr *tb[IFA_MAX+1];
@@ -1726,7 +1728,7 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
 		[RTA_OIF]       = { .type = NLA_U32 },
 		[RTA_PRIORITY]  = { .type = NLA_U32 },
 		[RTA_FLOW]      = { .type = NLA_U32 },
-		[RTA_CACHEINFO] = { .minlen = sizeof(struct rta_cacheinfo) },
+		[RTA_CACHEINFO] = { .minlen = offset_plus_sizeof(struct rta_cacheinfo, rta_tsage) },
 		[RTA_METRICS]   = { .type = NLA_NESTED },
 		[RTA_MULTIPATH] = { .type = NLA_NESTED },
 	};
@@ -5126,6 +5128,49 @@ wifi_indicate_addressing_running (NMPlatform *platform, int ifindex, gboolean ru
 
 /******************************************************************/
 
+static gboolean
+link_can_assume (NMPlatform *platform, int ifindex)
+{
+	NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
+	NMPCacheId cache_id;
+	const NMPlatformObject *const *objs;
+	guint i, len;
+	const NMPObject *link;
+
+	if (ifindex <= 0)
+		return FALSE;
+
+	link = cache_lookup_link (platform, ifindex);
+	if (!link)
+		return FALSE;
+
+	if (!NM_FLAGS_HAS (link->link.n_ifi_flags, IFF_UP))
+		return FALSE;
+
+	if (link->link.master > 0)
+		return TRUE;
+
+	if (nmp_cache_lookup_multi (priv->cache,
+	                            nmp_cache_id_init_addrroute_visible_by_ifindex (&cache_id, NMP_OBJECT_TYPE_IP4_ADDRESS, ifindex),
+	                            NULL))
+		return TRUE;
+
+	objs = nmp_cache_lookup_multi (priv->cache,
+	                               nmp_cache_id_init_addrroute_visible_by_ifindex (&cache_id, NMP_OBJECT_TYPE_IP6_ADDRESS, ifindex),
+	                               &len);
+	if (objs) {
+		for (i = 0; i < len; i++) {
+			const NMPlatformIP6Address *a = (NMPlatformIP6Address *) objs[i];
+
+			if (!IN6_IS_ADDR_LINKLOCAL (&a->address))
+				return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+/******************************************************************/
+
 static guint32
 mesh_get_channel (NMPlatform *platform, int ifindex)
 {
@@ -6216,6 +6261,8 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
 	platform_class->link_enslave = link_enslave;
 	platform_class->link_release = link_release;
 
+	platform_class->link_can_assume = link_can_assume;
+
 	platform_class->vlan_add = vlan_add;
 	platform_class->link_vlan_change = link_vlan_change;
 	platform_class->link_vxlan_add = link_vxlan_add;