diff options
Diffstat (limited to 'src/platform/nm-linux-platform.c')
| -rw-r--r-- | src/platform/nm-linux-platform.c | 61 |
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; |