Blame SOURCES/0007-relax-parsing-protinfo.patch

4c8f2e
From b14cc1f2fb310e6ff00d3df867dc336d6b521f3f Mon Sep 17 00:00:00 2001
4c8f2e
From: Thomas Haller <thaller@redhat.com>
4c8f2e
Date: Thu, 20 Mar 2014 19:18:42 +0100
4c8f2e
Subject: [PATCH 1/3] route: don't enforce minlen in inet6_parse_protinfo()
4c8f2e
 (IFLA_PROTINFO) and inet_parse_af() (IFLA_AF_SPEC)
4c8f2e
4c8f2e
Older kernel version might have fewer values defined, so they would send
4c8f2e
netlink messages that got rejected. Only check that at least one value
4c8f2e
got sent.
4c8f2e
4c8f2e
This is especially grave as libnl uses an internal copy of the
4c8f2e
kernel header files. Thus not only it is bound to the installed kernel
4c8f2e
headers but to the libnl internal header copies that might easily be out
4c8f2e
of sync with the kernel.
4c8f2e
4c8f2e
This affects IFLA_PROTINFO, inet6_parse_protinfo():
4c8f2e
  - tb[IFLA_INET6_CONF], expecting DEVCONF_MAX
4c8f2e
  - tb[IFLA_INET6_STATS], expecting __IPSTATS_MIB_MAX
4c8f2e
  - tb[IFLA_INET6_ICMP6STATS], expecting __ICMP6_MIB_MAX
4c8f2e
and IFLA_AF_SPEC, inet_parse_af():
4c8f2e
  - tb[IFLA_INET_CONF], expecting IPV4_DEVCONF_MAX
4c8f2e
4c8f2e
https://bugzilla.redhat.com/show_bug.cgi?id=1062533
4c8f2e
4c8f2e
Acked-by: Thomas Graf <tgraf@suug.ch>
4c8f2e
Signed-off-by: Thomas Haller <thaller@redhat.com>
4c8f2e
(cherry picked from commit dfd0a80ec845a800504fecb936c2b33d6918fc9c)
4c8f2e
---
4c8f2e
 lib/route/link/inet.c  |  4 +++-
4c8f2e
 lib/route/link/inet6.c | 18 +++++++++++++-----
4c8f2e
 2 files changed, 16 insertions(+), 6 deletions(-)
4c8f2e
4c8f2e
diff --git a/lib/route/link/inet.c b/lib/route/link/inet.c
4c8f2e
index e2c867d..eb2e8ae 100644
4c8f2e
--- a/lib/route/link/inet.c
4c8f2e
+++ b/lib/route/link/inet.c
4c8f2e
@@ -92,7 +92,7 @@ static void inet_free(struct rtnl_link *link, void *data)
4c8f2e
 }
4c8f2e
 
4c8f2e
 static struct nla_policy inet_policy[IFLA_INET6_MAX+1] = {
4c8f2e
-	[IFLA_INET_CONF]	= { .minlen = IPV4_DEVCONF_MAX * 4 },
4c8f2e
+	[IFLA_INET_CONF]	= { .minlen = 4 },
4c8f2e
 };
4c8f2e
 
4c8f2e
 static int inet_parse_af(struct rtnl_link *link, struct nlattr *attr, void *data)
4c8f2e
@@ -104,6 +104,8 @@ static int inet_parse_af(struct rtnl_link *link, struct nlattr *attr, void *data
4c8f2e
 	err = nla_parse_nested(tb, IFLA_INET_MAX, attr, inet_policy);
4c8f2e
 	if (err < 0)
4c8f2e
 		return err;
4c8f2e
+	if (tb[IFLA_INET_CONF] && nla_len(tb[IFLA_INET_CONF]) % 4)
4c8f2e
+		return -EINVAL;
4c8f2e
 
4c8f2e
 	if (tb[IFLA_INET_CONF])
4c8f2e
 		nla_memcpy(&id->i_conf, tb[IFLA_INET_CONF], sizeof(id->i_conf));
4c8f2e
diff --git a/lib/route/link/inet6.c b/lib/route/link/inet6.c
4c8f2e
index 4c627bd..f171fed 100644
4c8f2e
--- a/lib/route/link/inet6.c
4c8f2e
+++ b/lib/route/link/inet6.c
4c8f2e
@@ -45,9 +45,9 @@ static void inet6_free(struct rtnl_link *link, void *data)
4c8f2e
 static struct nla_policy inet6_policy[IFLA_INET6_MAX+1] = {
4c8f2e
 	[IFLA_INET6_FLAGS]	= { .type = NLA_U32 },
4c8f2e
 	[IFLA_INET6_CACHEINFO]	= { .minlen = sizeof(struct ifla_cacheinfo) },
4c8f2e
-	[IFLA_INET6_CONF]	= { .minlen = DEVCONF_MAX * 4 },
4c8f2e
-	[IFLA_INET6_STATS]	= { .minlen = __IPSTATS_MIB_MAX * 8 },
4c8f2e
-	[IFLA_INET6_ICMP6STATS]	= { .minlen = __ICMP6_MIB_MAX * 8 },
4c8f2e
+	[IFLA_INET6_CONF]	= { .minlen = 4 },
4c8f2e
+	[IFLA_INET6_STATS]	= { .minlen = 8 },
4c8f2e
+	[IFLA_INET6_ICMP6STATS]	= { .minlen = 8 },
4c8f2e
 };
4c8f2e
 
4c8f2e
 static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr,
4c8f2e
@@ -60,6 +60,12 @@ static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr,
4c8f2e
 	err = nla_parse_nested(tb, IFLA_INET6_MAX, attr, inet6_policy);
4c8f2e
 	if (err < 0)
4c8f2e
 		return err;
4c8f2e
+	if (tb[IFLA_INET6_CONF] && nla_len(tb[IFLA_INET6_CONF]) % 4)
4c8f2e
+		return -EINVAL;
4c8f2e
+	if (tb[IFLA_INET6_STATS] && nla_len(tb[IFLA_INET6_STATS]) % 8)
4c8f2e
+		return -EINVAL;
4c8f2e
+	if (tb[IFLA_INET6_ICMP6STATS] && nla_len(tb[IFLA_INET6_ICMP6STATS]) % 8)
4c8f2e
+		return -EINVAL;
4c8f2e
 
4c8f2e
 	if (tb[IFLA_INET6_FLAGS])
4c8f2e
 		i6->i6_flags = nla_get_u32(tb[IFLA_INET6_FLAGS]);
4c8f2e
@@ -80,8 +86,9 @@ static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr,
4c8f2e
 		unsigned char *cnt = nla_data(tb[IFLA_INET6_STATS]);
4c8f2e
 		uint64_t stat;
4c8f2e
 		int i;
4c8f2e
+		int len = min_t(int, __IPSTATS_MIB_MAX, nla_len(tb[IFLA_INET6_STATS]) / 8);
4c8f2e
 
4c8f2e
-		for (i = 1; i < __IPSTATS_MIB_MAX; i++) {
4c8f2e
+		for (i = 1; i < len; i++) {
4c8f2e
 			memcpy(&stat, &cnt[i * sizeof(stat)], sizeof(stat));
4c8f2e
 			rtnl_link_set_stat(link, RTNL_LINK_IP6_INPKTS + i - 1,
4c8f2e
 					   stat);
4c8f2e
@@ -92,8 +99,9 @@ static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr,
4c8f2e
 		unsigned char *cnt = nla_data(tb[IFLA_INET6_ICMP6STATS]);
4c8f2e
 		uint64_t stat;
4c8f2e
 		int i;
4c8f2e
+		int len = min_t(int, __ICMP6_MIB_MAX, nla_len(tb[IFLA_INET6_ICMP6STATS]) / 8);
4c8f2e
 
4c8f2e
-		for (i = 1; i < __ICMP6_MIB_MAX; i++) {
4c8f2e
+		for (i = 1; i < len; i++) {
4c8f2e
 			memcpy(&stat, &cnt[i * sizeof(stat)], sizeof(stat));
4c8f2e
 			rtnl_link_set_stat(link, RTNL_LINK_ICMP6_INMSGS + i - 1,
4c8f2e
 					   stat);
4c8f2e
-- 
4c8f2e
1.8.5.3
4c8f2e
4c8f2e
4c8f2e
From b104b959d0508d89be672d751b370ad92cb0dc72 Mon Sep 17 00:00:00 2001
4c8f2e
From: Thomas Haller <thaller@redhat.com>
4c8f2e
Date: Thu, 20 Mar 2014 19:18:43 +0100
4c8f2e
Subject: [PATCH 2/3] route: detect missing cfgid in rtnl_link_inet_get_conf()
4c8f2e
4c8f2e
If the netlink message for IFLA_INET_CONF contains less then
4c8f2e
IPV4_DEVCONF_MAX entires, the last entries in i_conf are unset.
4c8f2e
Modify rtnl_link_inet_get_conf() to return -EINVAL when accessing
4c8f2e
an unset cfgid.
4c8f2e
4c8f2e
Acked-by: Thomas Graf <tgraf@suug.ch>
4c8f2e
Signed-off-by: Thomas Haller <thaller@redhat.com>
4c8f2e
(cherry picked from commit 3584a7ab55cb93225a0216385b62fbe5331388cd)
4c8f2e
---
4c8f2e
 lib/route/link/inet.c | 14 ++++++++++++--
4c8f2e
 1 file changed, 12 insertions(+), 2 deletions(-)
4c8f2e
4c8f2e
diff --git a/lib/route/link/inet.c b/lib/route/link/inet.c
4c8f2e
index eb2e8ae..2e61323 100644
4c8f2e
--- a/lib/route/link/inet.c
4c8f2e
+++ b/lib/route/link/inet.c
4c8f2e
@@ -107,8 +107,14 @@ static int inet_parse_af(struct rtnl_link *link, struct nlattr *attr, void *data
4c8f2e
 	if (tb[IFLA_INET_CONF] && nla_len(tb[IFLA_INET_CONF]) % 4)
4c8f2e
 		return -EINVAL;
4c8f2e
 
4c8f2e
-	if (tb[IFLA_INET_CONF])
4c8f2e
+	if (tb[IFLA_INET_CONF]) {
4c8f2e
+		int i;
4c8f2e
+		int len = min_t(int, IPV4_DEVCONF_MAX, nla_len(tb[IFLA_INET_CONF]) / 4);
4c8f2e
+
4c8f2e
+		for (i = 0; i < len; i++)
4c8f2e
+			id->i_confset[i] = 1;
4c8f2e
 		nla_memcpy(&id->i_conf, tb[IFLA_INET_CONF], sizeof(id->i_conf));
4c8f2e
+	}
4c8f2e
 
4c8f2e
 	return 0;
4c8f2e
 }
4c8f2e
@@ -186,7 +192,7 @@ static void inet_dump_details(struct rtnl_link *link,
4c8f2e
 	for (i = 0; i < IPV4_DEVCONF_MAX; i++) {
4c8f2e
 		nl_dump_line(p, "%-19s %3u",
4c8f2e
 			rtnl_link_inet_devconf2str(i+1, buf, sizeof(buf)),
4c8f2e
-			id->i_conf[i]);
4c8f2e
+			id->i_confset[i] ? id->i_conf[i] : 0);
4c8f2e
 
4c8f2e
 		if (++n == 3) {
4c8f2e
 			nl_dump(p, "\n");
4c8f2e
@@ -222,6 +228,8 @@ static struct rtnl_link_af_ops inet_ops = {
4c8f2e
  * @return 0 on success or a negative error code.
4c8f2e
  * @return -NLE_RANGE cfgid is out of range, 1..IPV4_DEVCONF_MAX
4c8f2e
  * @return -NLE_NOATTR configuration setting not available
4c8f2e
+ * @return -NLE_INVAL cfgid not set. If the link was received via netlink,
4c8f2e
+ *                    it means that the cfgid is not supported.
4c8f2e
  */
4c8f2e
 int rtnl_link_inet_get_conf(struct rtnl_link *link, const unsigned int cfgid,
4c8f2e
 			    uint32_t *res)
4c8f2e
@@ -234,6 +242,8 @@ int rtnl_link_inet_get_conf(struct rtnl_link *link, const unsigned int cfgid,
4c8f2e
 	if (!(id = rtnl_link_af_alloc(link, &inet_ops)))
4c8f2e
 		return -NLE_NOATTR;
4c8f2e
 
4c8f2e
+	if (!id->i_confset[cfgid - 1])
4c8f2e
+		return -NLE_INVAL;
4c8f2e
 	*res = id->i_conf[cfgid - 1];
4c8f2e
 
4c8f2e
 	return 0;
4c8f2e
-- 
4c8f2e
1.8.5.3
4c8f2e
4c8f2e
4c8f2e
From 8421ae8b6bfa7a88cf9cdddf07fabd88362de963 Mon Sep 17 00:00:00 2001
4c8f2e
From: Thomas Haller <thaller@redhat.com>
4c8f2e
Date: Thu, 20 Mar 2014 19:18:44 +0100
4c8f2e
Subject: [PATCH 3/3] route: update kernel header snmp.h and fix
4c8f2e
 inet6_parse_protinfo() after kernel API breakage
4c8f2e
4c8f2e
Take 'include/uapi/linux/snmp.h' from current kernel v3.13
4c8f2e
(commit d8ec26d7f8287f5788a494f56e8814210f0e64be).
4c8f2e
4c8f2e
The header file added new values for IPSTATS_MIB_* and ICMP6_MIB_*, but
4c8f2e
more importantly, the kernel broke user space API by reordering enum values in
4c8f2e
IPSTATS_MIB_*. Add a workaround when parsing IFLA_PROTINFO trying to
4c8f2e
be compatible with both older and newer kernels.
4c8f2e
4c8f2e
Note that this workaround might fail for some specific kernel versions by
4c8f2e
assuming the old enum value mapping, although the kernel version already
4c8f2e
contains the API change. In this case rtnl_link_get_stat() mixes up
4c8f2e
values.
4c8f2e
4c8f2e
Acked-by: Thomas Graf <tgraf@suug.ch>
4c8f2e
Signed-off-by: Thomas Haller <thaller@redhat.com>
4c8f2e
(cherry picked from commit 5981a39583ab65dca230a8ee70625626d9ec9fc8)
4c8f2e
---
4c8f2e
 include/linux/snmp.h         |  43 +++++++++++++---
4c8f2e
 include/netlink/route/link.h |   6 +++
4c8f2e
 lib/route/link.c             |   6 +++
4c8f2e
 lib/route/link/inet6.c       | 117 +++++++++++++++++++++++++++++++++++++++----
4c8f2e
 4 files changed, 156 insertions(+), 16 deletions(-)
4c8f2e
4c8f2e
diff --git a/include/linux/snmp.h b/include/linux/snmp.h
4c8f2e
index 12b2b18..1bdb4a3 100644
4c8f2e
--- a/include/linux/snmp.h
4c8f2e
+++ b/include/linux/snmp.h
4c8f2e
@@ -18,7 +18,14 @@
4c8f2e
 enum
4c8f2e
 {
4c8f2e
 	IPSTATS_MIB_NUM = 0,
4c8f2e
+/* frequently written fields in fast path, kept in same cache line */
4c8f2e
 	IPSTATS_MIB_INPKTS,			/* InReceives */
4c8f2e
+	IPSTATS_MIB_INOCTETS,			/* InOctets */
4c8f2e
+	IPSTATS_MIB_INDELIVERS,			/* InDelivers */
4c8f2e
+	IPSTATS_MIB_OUTFORWDATAGRAMS,		/* OutForwDatagrams */
4c8f2e
+	IPSTATS_MIB_OUTPKTS,			/* OutRequests */
4c8f2e
+	IPSTATS_MIB_OUTOCTETS,			/* OutOctets */
4c8f2e
+/* other fields */
4c8f2e
 	IPSTATS_MIB_INHDRERRORS,		/* InHdrErrors */
4c8f2e
 	IPSTATS_MIB_INTOOBIGERRORS,		/* InTooBigErrors */
4c8f2e
 	IPSTATS_MIB_INNOROUTES,			/* InNoRoutes */
4c8f2e
@@ -26,9 +33,6 @@ enum
4c8f2e
 	IPSTATS_MIB_INUNKNOWNPROTOS,		/* InUnknownProtos */
4c8f2e
 	IPSTATS_MIB_INTRUNCATEDPKTS,		/* InTruncatedPkts */
4c8f2e
 	IPSTATS_MIB_INDISCARDS,			/* InDiscards */
4c8f2e
-	IPSTATS_MIB_INDELIVERS,			/* InDelivers */
4c8f2e
-	IPSTATS_MIB_OUTFORWDATAGRAMS,		/* OutForwDatagrams */
4c8f2e
-	IPSTATS_MIB_OUTPKTS,			/* OutRequests */
4c8f2e
 	IPSTATS_MIB_OUTDISCARDS,		/* OutDiscards */
4c8f2e
 	IPSTATS_MIB_OUTNOROUTES,		/* OutNoRoutes */
4c8f2e
 	IPSTATS_MIB_REASMTIMEOUT,		/* ReasmTimeout */
4c8f2e
@@ -42,12 +46,15 @@ enum
4c8f2e
 	IPSTATS_MIB_OUTMCASTPKTS,		/* OutMcastPkts */
4c8f2e
 	IPSTATS_MIB_INBCASTPKTS,		/* InBcastPkts */
4c8f2e
 	IPSTATS_MIB_OUTBCASTPKTS,		/* OutBcastPkts */
4c8f2e
-	IPSTATS_MIB_INOCTETS,			/* InOctets */
4c8f2e
-	IPSTATS_MIB_OUTOCTETS,			/* OutOctets */
4c8f2e
 	IPSTATS_MIB_INMCASTOCTETS,		/* InMcastOctets */
4c8f2e
 	IPSTATS_MIB_OUTMCASTOCTETS,		/* OutMcastOctets */
4c8f2e
 	IPSTATS_MIB_INBCASTOCTETS,		/* InBcastOctets */
4c8f2e
 	IPSTATS_MIB_OUTBCASTOCTETS,		/* OutBcastOctets */
4c8f2e
+	IPSTATS_MIB_CSUMERRORS,			/* InCsumErrors */
4c8f2e
+	IPSTATS_MIB_NOECTPKTS,			/* InNoECTPkts */
4c8f2e
+	IPSTATS_MIB_ECT1PKTS,			/* InECT1Pkts */
4c8f2e
+	IPSTATS_MIB_ECT0PKTS,			/* InECT0Pkts */
4c8f2e
+	IPSTATS_MIB_CEPKTS,			/* InCEPkts */
4c8f2e
 	__IPSTATS_MIB_MAX
4c8f2e
 };
4c8f2e
 
4c8f2e
@@ -85,6 +92,7 @@ enum
4c8f2e
 	ICMP_MIB_OUTTIMESTAMPREPS,		/* OutTimestampReps */
4c8f2e
 	ICMP_MIB_OUTADDRMASKS,			/* OutAddrMasks */
4c8f2e
 	ICMP_MIB_OUTADDRMASKREPS,		/* OutAddrMaskReps */
4c8f2e
+	ICMP_MIB_CSUMERRORS,			/* InCsumErrors */
4c8f2e
 	__ICMP_MIB_MAX
4c8f2e
 };
4c8f2e
 
4c8f2e
@@ -101,6 +109,7 @@ enum
4c8f2e
 	ICMP6_MIB_INERRORS,			/* InErrors */
4c8f2e
 	ICMP6_MIB_OUTMSGS,			/* OutMsgs */
4c8f2e
 	ICMP6_MIB_OUTERRORS,			/* OutErrors */
4c8f2e
+	ICMP6_MIB_CSUMERRORS,			/* InCsumErrors */
4c8f2e
 	__ICMP6_MIB_MAX
4c8f2e
 };
4c8f2e
 
4c8f2e
@@ -128,6 +137,7 @@ enum
4c8f2e
 	TCP_MIB_RETRANSSEGS,			/* RetransSegs */
4c8f2e
 	TCP_MIB_INERRS,				/* InErrs */
4c8f2e
 	TCP_MIB_OUTRSTS,			/* OutRsts */
4c8f2e
+	TCP_MIB_CSUMERRORS,			/* InCsumErrors */
4c8f2e
 	__TCP_MIB_MAX
4c8f2e
 };
4c8f2e
 
4c8f2e
@@ -145,6 +155,7 @@ enum
4c8f2e
 	UDP_MIB_OUTDATAGRAMS,			/* OutDatagrams */
4c8f2e
 	UDP_MIB_RCVBUFERRORS,			/* RcvbufErrors */
4c8f2e
 	UDP_MIB_SNDBUFERRORS,			/* SndbufErrors */
4c8f2e
+	UDP_MIB_CSUMERRORS,			/* InCsumErrors */
4c8f2e
 	__UDP_MIB_MAX
4c8f2e
 };
4c8f2e
 
4c8f2e
@@ -192,7 +203,6 @@ enum
4c8f2e
 	LINUX_MIB_TCPPARTIALUNDO,		/* TCPPartialUndo */
4c8f2e
 	LINUX_MIB_TCPDSACKUNDO,			/* TCPDSACKUndo */
4c8f2e
 	LINUX_MIB_TCPLOSSUNDO,			/* TCPLossUndo */
4c8f2e
-	LINUX_MIB_TCPLOSS,			/* TCPLoss */
4c8f2e
 	LINUX_MIB_TCPLOSTRETRANSMIT,		/* TCPLostRetransmit */
4c8f2e
 	LINUX_MIB_TCPRENOFAILURES,		/* TCPRenoFailures */
4c8f2e
 	LINUX_MIB_TCPSACKFAILURES,		/* TCPSackFailures */
4c8f2e
@@ -201,6 +211,8 @@ enum
4c8f2e
 	LINUX_MIB_TCPFORWARDRETRANS,		/* TCPForwardRetrans */
4c8f2e
 	LINUX_MIB_TCPSLOWSTARTRETRANS,		/* TCPSlowStartRetrans */
4c8f2e
 	LINUX_MIB_TCPTIMEOUTS,			/* TCPTimeouts */
4c8f2e
+	LINUX_MIB_TCPLOSSPROBES,		/* TCPLossProbes */
4c8f2e
+	LINUX_MIB_TCPLOSSPROBERECOVERY,		/* TCPLossProbeRecovery */
4c8f2e
 	LINUX_MIB_TCPRENORECOVERYFAIL,		/* TCPRenoRecoveryFail */
4c8f2e
 	LINUX_MIB_TCPSACKRECOVERYFAIL,		/* TCPSackRecoveryFail */
4c8f2e
 	LINUX_MIB_TCPSCHEDULERFAILED,		/* TCPSchedulerFailed */
4c8f2e
@@ -209,7 +221,6 @@ enum
4c8f2e
 	LINUX_MIB_TCPDSACKOFOSENT,		/* TCPDSACKOfoSent */
4c8f2e
 	LINUX_MIB_TCPDSACKRECV,			/* TCPDSACKRecv */
4c8f2e
 	LINUX_MIB_TCPDSACKOFORECV,		/* TCPDSACKOfoRecv */
4c8f2e
-	LINUX_MIB_TCPABORTONSYN,		/* TCPAbortOnSyn */
4c8f2e
 	LINUX_MIB_TCPABORTONDATA,		/* TCPAbortOnData */
4c8f2e
 	LINUX_MIB_TCPABORTONCLOSE,		/* TCPAbortOnClose */
4c8f2e
 	LINUX_MIB_TCPABORTONMEMORY,		/* TCPAbortOnMemory */
4c8f2e
@@ -231,6 +242,22 @@ enum
4c8f2e
 	LINUX_MIB_TCPDEFERACCEPTDROP,
4c8f2e
 	LINUX_MIB_IPRPFILTER, /* IP Reverse Path Filter (rp_filter) */
4c8f2e
 	LINUX_MIB_TCPTIMEWAITOVERFLOW,		/* TCPTimeWaitOverflow */
4c8f2e
+	LINUX_MIB_TCPREQQFULLDOCOOKIES,		/* TCPReqQFullDoCookies */
4c8f2e
+	LINUX_MIB_TCPREQQFULLDROP,		/* TCPReqQFullDrop */
4c8f2e
+	LINUX_MIB_TCPRETRANSFAIL,		/* TCPRetransFail */
4c8f2e
+	LINUX_MIB_TCPRCVCOALESCE,		/* TCPRcvCoalesce */
4c8f2e
+	LINUX_MIB_TCPOFOQUEUE,			/* TCPOFOQueue */
4c8f2e
+	LINUX_MIB_TCPOFODROP,			/* TCPOFODrop */
4c8f2e
+	LINUX_MIB_TCPOFOMERGE,			/* TCPOFOMerge */
4c8f2e
+	LINUX_MIB_TCPCHALLENGEACK,		/* TCPChallengeACK */
4c8f2e
+	LINUX_MIB_TCPSYNCHALLENGE,		/* TCPSYNChallenge */
4c8f2e
+	LINUX_MIB_TCPFASTOPENACTIVE,		/* TCPFastOpenActive */
4c8f2e
+	LINUX_MIB_TCPFASTOPENPASSIVE,		/* TCPFastOpenPassive*/
4c8f2e
+	LINUX_MIB_TCPFASTOPENPASSIVEFAIL,	/* TCPFastOpenPassiveFail */
4c8f2e
+	LINUX_MIB_TCPFASTOPENLISTENOVERFLOW,	/* TCPFastOpenListenOverflow */
4c8f2e
+	LINUX_MIB_TCPFASTOPENCOOKIEREQD,	/* TCPFastOpenCookieReqd */
4c8f2e
+	LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES, /* TCPSpuriousRtxHostQueues */
4c8f2e
+	LINUX_MIB_BUSYPOLLRXPACKETS,		/* BusyPollRxPackets */
4c8f2e
 	__LINUX_MIB_MAX
4c8f2e
 };
4c8f2e
 
4c8f2e
@@ -264,6 +291,8 @@ enum
4c8f2e
 	LINUX_MIB_XFRMOUTPOLDEAD,		/* XfrmOutPolDead */
4c8f2e
 	LINUX_MIB_XFRMOUTPOLERROR,		/* XfrmOutPolError */
4c8f2e
 	LINUX_MIB_XFRMFWDHDRERROR,		/* XfrmFwdHdrError*/
4c8f2e
+	LINUX_MIB_XFRMOUTSTATEINVALID,		/* XfrmOutStateInvalid */
4c8f2e
+	LINUX_MIB_XFRMACQUIREERROR,		/* XfrmAcquireError */
4c8f2e
 	__LINUX_MIB_XFRMMAX
4c8f2e
 };
4c8f2e
 
4c8f2e
diff --git a/include/netlink/route/link.h b/include/netlink/route/link.h
4c8f2e
index dbde72f..2d061be 100644
4c8f2e
--- a/include/netlink/route/link.h
4c8f2e
+++ b/include/netlink/route/link.h
4c8f2e
@@ -92,6 +92,12 @@ typedef enum {
4c8f2e
 	RTNL_LINK_ICMP6_INERRORS,	/*!< ICMPv6 SNMP InErrors */
4c8f2e
 	RTNL_LINK_ICMP6_OUTMSGS,	/*!< ICMPv6 SNMP OutMsgs */
4c8f2e
 	RTNL_LINK_ICMP6_OUTERRORS,	/*!< ICMPv6 SNMP OutErrors */
4c8f2e
+	RTNL_LINK_ICMP6_CSUMERRORS,	/*!< ICMPv6 SNMP InCsumErrors */
4c8f2e
+	RTNL_LINK_IP6_CSUMERRORS,	/*!< IPv6 SNMP InCsumErrors */
4c8f2e
+	RTNL_LINK_IP6_NOECTPKTS,	/*!< IPv6 SNMP InNoECTPkts */
4c8f2e
+	RTNL_LINK_IP6_ECT1PKTS,		/*!< IPv6 SNMP InECT1Pkts */
4c8f2e
+	RTNL_LINK_IP6_ECT0PKTS,		/*!< IPv6 SNMP InECT0Pkts */
4c8f2e
+	RTNL_LINK_IP6_CEPKTS,		/*!< IPv6 SNMP InCEPkts */
4c8f2e
 	__RTNL_LINK_STATS_MAX,
4c8f2e
 } rtnl_link_stat_id_t;
4c8f2e
 
4c8f2e
diff --git a/lib/route/link.c b/lib/route/link.c
4c8f2e
index 3171513..8fe3376 100644
4c8f2e
--- a/lib/route/link.c
4c8f2e
+++ b/lib/route/link.c
4c8f2e
@@ -2470,6 +2470,12 @@ static const struct trans_tbl link_stats[] = {
4c8f2e
 	__ADD(RTNL_LINK_ICMP6_INERRORS, ICMP6_InErrors)
4c8f2e
 	__ADD(RTNL_LINK_ICMP6_OUTMSGS, ICMP6_OutMsgs)
4c8f2e
 	__ADD(RTNL_LINK_ICMP6_OUTERRORS, ICMP6_OutErrors)
4c8f2e
+	__ADD(RTNL_LINK_ICMP6_CSUMERRORS, ICMP6_InCsumErrors)
4c8f2e
+	__ADD(RTNL_LINK_IP6_CSUMERRORS, Ip6_InCsumErrors)
4c8f2e
+	__ADD(RTNL_LINK_IP6_NOECTPKTS, Ip6_InNoECTPkts)
4c8f2e
+	__ADD(RTNL_LINK_IP6_ECT1PKTS, Ip6_InECT1Pkts)
4c8f2e
+	__ADD(RTNL_LINK_IP6_ECT0PKTS, Ip6_InECT0Pkts)
4c8f2e
+	__ADD(RTNL_LINK_IP6_CEPKTS, Ip6_InCEPkts)
4c8f2e
 };
4c8f2e
 
4c8f2e
 char *rtnl_link_stat2str(int st, char *buf, size_t len)
4c8f2e
diff --git a/lib/route/link/inet6.c b/lib/route/link/inet6.c
4c8f2e
index f171fed..6fa2741 100644
4c8f2e
--- a/lib/route/link/inet6.c
4c8f2e
+++ b/lib/route/link/inet6.c
4c8f2e
@@ -50,6 +50,84 @@ static struct nla_policy inet6_policy[IFLA_INET6_MAX+1] = {
4c8f2e
 	[IFLA_INET6_ICMP6STATS]	= { .minlen = 8 },
4c8f2e
 };
4c8f2e
 
4c8f2e
+static const uint8_t map_stat_id_from_IPSTATS_MIB_v1[__IPSTATS_MIB_MAX] = {
4c8f2e
+	/* 14a196807482e6fc74f15fc03176d5c08880588f^:include/linux/snmp.h
4c8f2e
+	 * version before the API change in commit 14a196807482e6fc74f15fc03176d5c08880588f.
4c8f2e
+	 * This version was valid since commit edf391ff17232f097d72441c9ad467bcb3b5db18, which
4c8f2e
+	 * predates support for parsing IFLA_PROTINFO in libnl3. Such an even older meaning of
4c8f2e
+	 * the flags is not supported in libnl3. */
4c8f2e
+	[ 1] = RTNL_LINK_IP6_INPKTS,                    /* IPSTATS_MIB_INPKTS                   */
4c8f2e
+	[ 2] = RTNL_LINK_IP6_INHDRERRORS,               /* IPSTATS_MIB_INHDRERRORS              */
4c8f2e
+	[ 3] = RTNL_LINK_IP6_INTOOBIGERRORS,            /* IPSTATS_MIB_INTOOBIGERRORS           */
4c8f2e
+	[ 4] = RTNL_LINK_IP6_INNOROUTES,                /* IPSTATS_MIB_INNOROUTES               */
4c8f2e
+	[ 5] = RTNL_LINK_IP6_INADDRERRORS,              /* IPSTATS_MIB_INADDRERRORS             */
4c8f2e
+	[ 6] = RTNL_LINK_IP6_INUNKNOWNPROTOS,           /* IPSTATS_MIB_INUNKNOWNPROTOS          */
4c8f2e
+	[ 7] = RTNL_LINK_IP6_INTRUNCATEDPKTS,           /* IPSTATS_MIB_INTRUNCATEDPKTS          */
4c8f2e
+	[ 8] = RTNL_LINK_IP6_INDISCARDS,                /* IPSTATS_MIB_INDISCARDS               */
4c8f2e
+	[ 9] = RTNL_LINK_IP6_INDELIVERS,                /* IPSTATS_MIB_INDELIVERS               */
4c8f2e
+	[10] = RTNL_LINK_IP6_OUTFORWDATAGRAMS,          /* IPSTATS_MIB_OUTFORWDATAGRAMS         */
4c8f2e
+	[11] = RTNL_LINK_IP6_OUTPKTS,                   /* IPSTATS_MIB_OUTPKTS                  */
4c8f2e
+	[12] = RTNL_LINK_IP6_OUTDISCARDS,               /* IPSTATS_MIB_OUTDISCARDS              */
4c8f2e
+	[13] = RTNL_LINK_IP6_OUTNOROUTES,               /* IPSTATS_MIB_OUTNOROUTES              */
4c8f2e
+	[14] = RTNL_LINK_IP6_REASMTIMEOUT,              /* IPSTATS_MIB_REASMTIMEOUT             */
4c8f2e
+	[15] = RTNL_LINK_IP6_REASMREQDS,                /* IPSTATS_MIB_REASMREQDS               */
4c8f2e
+	[16] = RTNL_LINK_IP6_REASMOKS,                  /* IPSTATS_MIB_REASMOKS                 */
4c8f2e
+	[17] = RTNL_LINK_IP6_REASMFAILS,                /* IPSTATS_MIB_REASMFAILS               */
4c8f2e
+	[18] = RTNL_LINK_IP6_FRAGOKS,                   /* IPSTATS_MIB_FRAGOKS                  */
4c8f2e
+	[19] = RTNL_LINK_IP6_FRAGFAILS,                 /* IPSTATS_MIB_FRAGFAILS                */
4c8f2e
+	[20] = RTNL_LINK_IP6_FRAGCREATES,               /* IPSTATS_MIB_FRAGCREATES              */
4c8f2e
+	[21] = RTNL_LINK_IP6_INMCASTPKTS,               /* IPSTATS_MIB_INMCASTPKTS              */
4c8f2e
+	[22] = RTNL_LINK_IP6_OUTMCASTPKTS,              /* IPSTATS_MIB_OUTMCASTPKTS             */
4c8f2e
+	[23] = RTNL_LINK_IP6_INBCASTPKTS,               /* IPSTATS_MIB_INBCASTPKTS              */
4c8f2e
+	[24] = RTNL_LINK_IP6_OUTBCASTPKTS,              /* IPSTATS_MIB_OUTBCASTPKTS             */
4c8f2e
+	[25] = RTNL_LINK_IP6_INOCTETS,                  /* IPSTATS_MIB_INOCTETS                 */
4c8f2e
+	[26] = RTNL_LINK_IP6_OUTOCTETS,                 /* IPSTATS_MIB_OUTOCTETS                */
4c8f2e
+	[27] = RTNL_LINK_IP6_INMCASTOCTETS,             /* IPSTATS_MIB_INMCASTOCTETS            */
4c8f2e
+	[28] = RTNL_LINK_IP6_OUTMCASTOCTETS,            /* IPSTATS_MIB_OUTMCASTOCTETS           */
4c8f2e
+	[29] = RTNL_LINK_IP6_INBCASTOCTETS,             /* IPSTATS_MIB_INBCASTOCTETS            */
4c8f2e
+	[30] = RTNL_LINK_IP6_OUTBCASTOCTETS,            /* IPSTATS_MIB_OUTBCASTOCTETS           */
4c8f2e
+};
4c8f2e
+
4c8f2e
+static const uint8_t map_stat_id_from_IPSTATS_MIB_v2[__IPSTATS_MIB_MAX] = {
4c8f2e
+	/* d8ec26d7f8287f5788a494f56e8814210f0e64be:include/uapi/linux/snmp.h
4c8f2e
+	 * version since the API change in commit 14a196807482e6fc74f15fc03176d5c08880588f */
4c8f2e
+	[ 1] = RTNL_LINK_IP6_INPKTS,                    /* IPSTATS_MIB_INPKTS                   */
4c8f2e
+	[ 2] = RTNL_LINK_IP6_INOCTETS,                  /* IPSTATS_MIB_INOCTETS                 */
4c8f2e
+	[ 3] = RTNL_LINK_IP6_INDELIVERS,                /* IPSTATS_MIB_INDELIVERS               */
4c8f2e
+	[ 4] = RTNL_LINK_IP6_OUTFORWDATAGRAMS,          /* IPSTATS_MIB_OUTFORWDATAGRAMS         */
4c8f2e
+	[ 5] = RTNL_LINK_IP6_OUTPKTS,                   /* IPSTATS_MIB_OUTPKTS                  */
4c8f2e
+	[ 6] = RTNL_LINK_IP6_OUTOCTETS,                 /* IPSTATS_MIB_OUTOCTETS                */
4c8f2e
+	[ 7] = RTNL_LINK_IP6_INHDRERRORS,               /* IPSTATS_MIB_INHDRERRORS              */
4c8f2e
+	[ 8] = RTNL_LINK_IP6_INTOOBIGERRORS,            /* IPSTATS_MIB_INTOOBIGERRORS           */
4c8f2e
+	[ 9] = RTNL_LINK_IP6_INNOROUTES,                /* IPSTATS_MIB_INNOROUTES               */
4c8f2e
+	[10] = RTNL_LINK_IP6_INADDRERRORS,              /* IPSTATS_MIB_INADDRERRORS             */
4c8f2e
+	[11] = RTNL_LINK_IP6_INUNKNOWNPROTOS,           /* IPSTATS_MIB_INUNKNOWNPROTOS          */
4c8f2e
+	[12] = RTNL_LINK_IP6_INTRUNCATEDPKTS,           /* IPSTATS_MIB_INTRUNCATEDPKTS          */
4c8f2e
+	[13] = RTNL_LINK_IP6_INDISCARDS,                /* IPSTATS_MIB_INDISCARDS               */
4c8f2e
+	[14] = RTNL_LINK_IP6_OUTDISCARDS,               /* IPSTATS_MIB_OUTDISCARDS              */
4c8f2e
+	[15] = RTNL_LINK_IP6_OUTNOROUTES,               /* IPSTATS_MIB_OUTNOROUTES              */
4c8f2e
+	[16] = RTNL_LINK_IP6_REASMTIMEOUT,              /* IPSTATS_MIB_REASMTIMEOUT             */
4c8f2e
+	[17] = RTNL_LINK_IP6_REASMREQDS,                /* IPSTATS_MIB_REASMREQDS               */
4c8f2e
+	[18] = RTNL_LINK_IP6_REASMOKS,                  /* IPSTATS_MIB_REASMOKS                 */
4c8f2e
+	[19] = RTNL_LINK_IP6_REASMFAILS,                /* IPSTATS_MIB_REASMFAILS               */
4c8f2e
+	[20] = RTNL_LINK_IP6_FRAGOKS,                   /* IPSTATS_MIB_FRAGOKS                  */
4c8f2e
+	[21] = RTNL_LINK_IP6_FRAGFAILS,                 /* IPSTATS_MIB_FRAGFAILS                */
4c8f2e
+	[22] = RTNL_LINK_IP6_FRAGCREATES,               /* IPSTATS_MIB_FRAGCREATES              */
4c8f2e
+	[23] = RTNL_LINK_IP6_INMCASTPKTS,               /* IPSTATS_MIB_INMCASTPKTS              */
4c8f2e
+	[24] = RTNL_LINK_IP6_OUTMCASTPKTS,              /* IPSTATS_MIB_OUTMCASTPKTS             */
4c8f2e
+	[25] = RTNL_LINK_IP6_INBCASTPKTS,               /* IPSTATS_MIB_INBCASTPKTS              */
4c8f2e
+	[26] = RTNL_LINK_IP6_OUTBCASTPKTS,              /* IPSTATS_MIB_OUTBCASTPKTS             */
4c8f2e
+	[27] = RTNL_LINK_IP6_INMCASTOCTETS,             /* IPSTATS_MIB_INMCASTOCTETS            */
4c8f2e
+	[28] = RTNL_LINK_IP6_OUTMCASTOCTETS,            /* IPSTATS_MIB_OUTMCASTOCTETS           */
4c8f2e
+	[29] = RTNL_LINK_IP6_INBCASTOCTETS,             /* IPSTATS_MIB_INBCASTOCTETS            */
4c8f2e
+	[30] = RTNL_LINK_IP6_OUTBCASTOCTETS,            /* IPSTATS_MIB_OUTBCASTOCTETS           */
4c8f2e
+	[31] = RTNL_LINK_IP6_CSUMERRORS,                /* IPSTATS_MIB_CSUMERRORS               */
4c8f2e
+	[32] = RTNL_LINK_IP6_NOECTPKTS,                 /* IPSTATS_MIB_NOECTPKTS                */
4c8f2e
+	[33] = RTNL_LINK_IP6_ECT1PKTS,                  /* IPSTATS_MIB_ECT1PKTS                 */
4c8f2e
+	[34] = RTNL_LINK_IP6_ECT0PKTS,                  /* IPSTATS_MIB_ECT0PKTS                 */
4c8f2e
+	[35] = RTNL_LINK_IP6_CEPKTS,                    /* IPSTATS_MIB_CEPKTS                   */
4c8f2e
+};
4c8f2e
+
4c8f2e
 static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr,
4c8f2e
 				void *data)
4c8f2e
 {
4c8f2e
@@ -86,12 +164,23 @@ static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr,
4c8f2e
 		unsigned char *cnt = nla_data(tb[IFLA_INET6_STATS]);
4c8f2e
 		uint64_t stat;
4c8f2e
 		int i;
4c8f2e
-		int len = min_t(int, __IPSTATS_MIB_MAX, nla_len(tb[IFLA_INET6_STATS]) / 8);
4c8f2e
+		int len = nla_len(tb[IFLA_INET6_STATS]) / 8;
4c8f2e
+		const uint8_t *map_stat_id = map_stat_id_from_IPSTATS_MIB_v2;
4c8f2e
+
4c8f2e
+		if (len < 32 ||
4c8f2e
+		    (tb[IFLA_INET6_ICMP6STATS] && nla_len(tb[IFLA_INET6_ICMP6STATS]) < 6)) {
4c8f2e
+			/* kernel commit 14a196807482e6fc74f15fc03176d5c08880588f reordered the values.
4c8f2e
+			 * The later commit 6a5dc9e598fe90160fee7de098fa319665f5253e added values
4c8f2e
+			 * IPSTATS_MIB_CSUMERRORS/ICMP6_MIB_CSUMERRORS. If the netlink is shorter
4c8f2e
+			 * then this, assume that the kernel uses the previous meaning of the
4c8f2e
+			 * enumeration. */
4c8f2e
+			map_stat_id = map_stat_id_from_IPSTATS_MIB_v1;
4c8f2e
+		}
4c8f2e
 
4c8f2e
+		len = min_t(int, __IPSTATS_MIB_MAX, len);
4c8f2e
 		for (i = 1; i < len; i++) {
4c8f2e
 			memcpy(&stat, &cnt[i * sizeof(stat)], sizeof(stat));
4c8f2e
-			rtnl_link_set_stat(link, RTNL_LINK_IP6_INPKTS + i - 1,
4c8f2e
-					   stat);
4c8f2e
+			rtnl_link_set_stat(link, map_stat_id[i], stat);
4c8f2e
 		}
4c8f2e
 	}
4c8f2e
 
4c8f2e
@@ -343,19 +432,29 @@ static void inet6_dump_stats(struct rtnl_link *link,
4c8f2e
 		link->l_stats[RTNL_LINK_IP6_INADDRERRORS]);
4c8f2e
 
4c8f2e
 	nl_dump(p, "       InUnknownProtos     InTruncatedPkts   "
4c8f2e
-		   "    OutNoRoutes\n");
4c8f2e
-	nl_dump(p, "    %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n",
4c8f2e
+		   "    OutNoRoutes       InCsumErrors\n");
4c8f2e
+	nl_dump(p, "    %18" PRIu64 " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n",
4c8f2e
 		link->l_stats[RTNL_LINK_IP6_INUNKNOWNPROTOS],
4c8f2e
 		link->l_stats[RTNL_LINK_IP6_INTRUNCATEDPKTS],
4c8f2e
-		link->l_stats[RTNL_LINK_IP6_OUTNOROUTES]);
4c8f2e
+		link->l_stats[RTNL_LINK_IP6_OUTNOROUTES],
4c8f2e
+		link->l_stats[RTNL_LINK_IP6_CSUMERRORS]);
4c8f2e
 
4c8f2e
-	nl_dump(p, "    ICMPv6:     InMsgs           InErrors        "
4c8f2e
-		   "    OutMsgs          OutErrors\n");
4c8f2e
+	nl_dump(p, "           InNoECTPkts          InECT1Pkts   "
4c8f2e
+		   "     InECT0Pkts           InCEPkts\n");
4c8f2e
 	nl_dump(p, "    %18" PRIu64 " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n",
4c8f2e
+		link->l_stats[RTNL_LINK_IP6_NOECTPKTS],
4c8f2e
+		link->l_stats[RTNL_LINK_IP6_ECT1PKTS],
4c8f2e
+		link->l_stats[RTNL_LINK_IP6_ECT0PKTS],
4c8f2e
+		link->l_stats[RTNL_LINK_IP6_CEPKTS]);
4c8f2e
+
4c8f2e
+	nl_dump(p, "    ICMPv6:     InMsgs           InErrors        "
4c8f2e
+		   "    OutMsgs          OutErrors       InCsumErrors\n");
4c8f2e
+	nl_dump(p, "    %18" PRIu64 " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n",
4c8f2e
 		link->l_stats[RTNL_LINK_ICMP6_INMSGS],
4c8f2e
 		link->l_stats[RTNL_LINK_ICMP6_INERRORS],
4c8f2e
 		link->l_stats[RTNL_LINK_ICMP6_OUTMSGS],
4c8f2e
-		link->l_stats[RTNL_LINK_ICMP6_OUTERRORS]);
4c8f2e
+		link->l_stats[RTNL_LINK_ICMP6_OUTERRORS],
4c8f2e
+		link->l_stats[RTNL_LINK_ICMP6_CSUMERRORS]);
4c8f2e
 }
4c8f2e
 
4c8f2e
 static const struct nla_policy protinfo_policy = {
4c8f2e
-- 
4c8f2e
1.8.5.3
4c8f2e