diff --git a/SOURCES/0050-iproute-Abort-if-nexthop-cannot-be-parsed.patch b/SOURCES/0050-iproute-Abort-if-nexthop-cannot-be-parsed.patch
new file mode 100644
index 0000000..14774b6
--- /dev/null
+++ b/SOURCES/0050-iproute-Abort-if-nexthop-cannot-be-parsed.patch
@@ -0,0 +1,52 @@
+From d80837df37cb8897769f87f7a2034a9653168221 Mon Sep 17 00:00:00 2001
+From: Phil Sutter <psutter@redhat.com>
+Date: Thu, 21 Feb 2019 14:38:57 +0100
+Subject: [PATCH] iproute: Abort if nexthop cannot be parsed
+
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1624656
+Upstream Status: iproute2.git commit ee53b42fd8b0b
+
+commit ee53b42fd8b0b0cdb857d0f5bf7467e22a3457d9
+Author: Jakub Sitnicki <jkbs@redhat.com>
+Date:   Wed Apr 11 11:43:11 2018 +0200
+
+    iproute: Abort if nexthop cannot be parsed
+
+    Attempt to add a multipath route where a nexthop definition refers to a
+    non-existent device causes 'ip' to crash and burn due to stack buffer
+    overflow:
+
+      # ip -6 route add fd00::1/64 nexthop dev fake1
+      Cannot find device "fake1"
+      Cannot find device "fake1"
+      Cannot find device "fake1"
+      ...
+      Segmentation fault (core dumped)
+
+    Don't ignore errors from the helper routine that parses the nexthop
+    definition, and abort immediately if parsing fails.
+
+    Signed-off-by: Jakub Sitnicki <jkbs@redhat.com>
+---
+ ip/iproute.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/ip/iproute.c b/ip/iproute.c
+index 35fdce8..759032d 100644
+--- a/ip/iproute.c
++++ b/ip/iproute.c
+@@ -817,7 +817,10 @@ static int parse_nexthops(struct nlmsghdr *n, struct rtmsg *r,
+ 		memset(rtnh, 0, sizeof(*rtnh));
+ 		rtnh->rtnh_len = sizeof(*rtnh);
+ 		rta->rta_len += rtnh->rtnh_len;
+-		parse_one_nh(n, r, rta, rtnh, &argc, &argv);
++		if (parse_one_nh(n, r, rta, rtnh, &argc, &argv)) {
++			fprintf(stderr, "Error: cannot parse nexthop\n");
++			exit(-1);
++		}
+ 		rtnh = RTNH_NEXT(rtnh);
+ 	}
+ 
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0051-ip-route-Fix-segfault-with-many-nexthops.patch b/SOURCES/0051-ip-route-Fix-segfault-with-many-nexthops.patch
new file mode 100644
index 0000000..07109f0
--- /dev/null
+++ b/SOURCES/0051-ip-route-Fix-segfault-with-many-nexthops.patch
@@ -0,0 +1,388 @@
+From 5845a145808162560293cf4f7c55bbb5afc8dce7 Mon Sep 17 00:00:00 2001
+From: Phil Sutter <psutter@redhat.com>
+Date: Thu, 21 Feb 2019 14:38:57 +0100
+Subject: [PATCH] ip-route: Fix segfault with many nexthops
+
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1624656
+Upstream Status: iproute2.git commit bd59e5b1517b0
+Conflicts: Context changes due to missing other commits.
+
+commit bd59e5b1517b09b6f26d59f38fe6077d953c2396
+Author: Phil Sutter <phil@nwl.cc>
+Date:   Thu Sep 6 15:31:51 2018 +0200
+
+    ip-route: Fix segfault with many nexthops
+
+    It was possible to crash ip-route by adding an IPv6 route with 37
+    nexthop statements. A simple reproducer is:
+
+    | for i in `seq 37`; do
+    |       nhs="nexthop via 1111::$i "$nhs
+    | done
+    | ip -6 route add 3333::/64 $nhs
+
+    The related code was broken in multiple ways:
+
+    * parse_one_nh() assumed that rta points to 4kB of storage but caller
+      provided just 1kB. Fixed by passing 'len' parameter with the correct
+      value.
+
+    * Error checking of rta_addattr*() calls in parse_one_nh() and called
+      functions was completely absent, so with above fix in place output
+      flood would occur due to parser looping forever.
+
+    While being at it, increase message buffer sizes to 4k. This allows for
+    at most 144 nexthops.
+
+    Signed-off-by: Phil Sutter <phil@nwl.cc>
+    Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
+---
+ ip/iproute.c          | 43 +++++++++++++++++++++--------------
+ ip/iproute_lwtunnel.c | 63 ++++++++++++++++++++++++++++++++-------------------
+ 2 files changed, 66 insertions(+), 40 deletions(-)
+
+diff --git a/ip/iproute.c b/ip/iproute.c
+index 759032d..d4db035 100644
+--- a/ip/iproute.c
++++ b/ip/iproute.c
+@@ -721,7 +721,7 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+ }
+ 
+ static int parse_one_nh(struct nlmsghdr *n, struct rtmsg *r,
+-			struct rtattr *rta, struct rtnexthop *rtnh,
++			struct rtattr *rta, size_t len, struct rtnexthop *rtnh,
+ 			int *argcp, char ***argvp)
+ {
+ 	int argc = *argcp;
+@@ -742,11 +742,16 @@ static int parse_one_nh(struct nlmsghdr *n, struct rtmsg *r,
+ 			if (r->rtm_family == AF_UNSPEC)
+ 				r->rtm_family = addr.family;
+ 			if (addr.family == r->rtm_family) {
+-				rta_addattr_l(rta, 4096, RTA_GATEWAY, &addr.data, addr.bytelen);
+-				rtnh->rtnh_len += sizeof(struct rtattr) + addr.bytelen;
++				if (rta_addattr_l(rta, len, RTA_GATEWAY,
++						  &addr.data, addr.bytelen))
++					return -1;
++				rtnh->rtnh_len += sizeof(struct rtattr)
++						  + addr.bytelen;
+ 			} else {
+-				rta_addattr_l(rta, 4096, RTA_VIA, &addr.family, addr.bytelen+2);
+-				rtnh->rtnh_len += RTA_SPACE(addr.bytelen+2);
++				if (rta_addattr_l(rta, len, RTA_VIA,
++						  &addr.family, addr.bytelen + 2))
++					return -1;
++				rtnh->rtnh_len += RTA_SPACE(addr.bytelen + 2);
+ 			}
+ 		} else if (strcmp(*argv, "dev") == 0) {
+ 			NEXT_ARG();
+@@ -769,13 +774,15 @@ static int parse_one_nh(struct nlmsghdr *n, struct rtmsg *r,
+ 			NEXT_ARG();
+ 			if (get_rt_realms_or_raw(&realm, *argv))
+ 				invarg("\"realm\" value is invalid\n", *argv);
+-			rta_addattr32(rta, 4096, RTA_FLOW, realm);
++			if (rta_addattr32(rta, len, RTA_FLOW, realm))
++				return -1;
+ 			rtnh->rtnh_len += sizeof(struct rtattr) + 4;
+ 		} else if (strcmp(*argv, "encap") == 0) {
+-			int len = rta->rta_len;
++			int old_len = rta->rta_len;
+ 
+-			lwt_parse_encap(rta, 4096, &argc, &argv);
+-			rtnh->rtnh_len += rta->rta_len - len;
++			if (lwt_parse_encap(rta, len, &argc, &argv))
++				return -1;
++			rtnh->rtnh_len += rta->rta_len - old_len;
+ 		} else if (strcmp(*argv, "as") == 0) {
+ 			inet_prefix addr;
+ 
+@@ -783,8 +790,9 @@ static int parse_one_nh(struct nlmsghdr *n, struct rtmsg *r,
+ 			if (strcmp(*argv, "to") == 0)
+ 				NEXT_ARG();
+ 			get_addr(&addr, *argv, r->rtm_family);
+-			rta_addattr_l(rta, 4096, RTA_NEWDST, &addr.data,
+-				      addr.bytelen);
++			if (rta_addattr_l(rta, len, RTA_NEWDST,
++					  &addr.data, addr.bytelen))
++				return -1;
+ 			rtnh->rtnh_len += sizeof(struct rtattr) + addr.bytelen;
+ 		} else
+ 			break;
+@@ -797,7 +805,7 @@ static int parse_one_nh(struct nlmsghdr *n, struct rtmsg *r,
+ static int parse_nexthops(struct nlmsghdr *n, struct rtmsg *r,
+ 			  int argc, char **argv)
+ {
+-	char buf[1024];
++	char buf[4096];
+ 	struct rtattr *rta = (void *)buf;
+ 	struct rtnexthop *rtnh;
+ 
+@@ -817,7 +825,7 @@ static int parse_nexthops(struct nlmsghdr *n, struct rtmsg *r,
+ 		memset(rtnh, 0, sizeof(*rtnh));
+ 		rtnh->rtnh_len = sizeof(*rtnh);
+ 		rta->rta_len += rtnh->rtnh_len;
+-		if (parse_one_nh(n, r, rta, rtnh, &argc, &argv)) {
++		if (parse_one_nh(n, r, rta, 4096, rtnh, &argc, &argv)) {
+ 			fprintf(stderr, "Error: cannot parse nexthop\n");
+ 			exit(-1);
+ 		}
+@@ -825,7 +833,8 @@ static int parse_nexthops(struct nlmsghdr *n, struct rtmsg *r,
+ 	}
+ 
+ 	if (rta->rta_len > RTA_LENGTH(0))
+-		addattr_l(n, 1024, RTA_MULTIPATH, RTA_DATA(rta), RTA_PAYLOAD(rta));
++		return addattr_l(n, 4096, RTA_MULTIPATH,
++				 RTA_DATA(rta), RTA_PAYLOAD(rta));
+ 	return 0;
+ }
+ 
+@@ -834,7 +843,7 @@ static int iproute_modify(int cmd, unsigned int flags, int argc, char **argv)
+ 	struct {
+ 		struct nlmsghdr	n;
+ 		struct rtmsg		r;
+-		char			buf[1024];
++		char			buf[4096];
+ 	} req = {
+ 		.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)),
+ 		.n.nlmsg_flags = NLM_F_REQUEST | flags,
+@@ -1238,8 +1247,8 @@ static int iproute_modify(int cmd, unsigned int flags, int argc, char **argv)
+ 		addattr_l(&req.n, sizeof(req), RTA_METRICS, RTA_DATA(mxrta), RTA_PAYLOAD(mxrta));
+ 	}
+ 
+-	if (nhs_ok)
+-		parse_nexthops(&req.n, &req.r, argc, argv);
++	if (nhs_ok && parse_nexthops(&req.n, &req.r, argc, argv))
++		return -1;
+ 
+ 	if (req.r.rtm_family == AF_UNSPEC)
+ 		req.r.rtm_family = AF_INET;
+diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c
+index 0fa1cab..1a68912 100644
+--- a/ip/iproute_lwtunnel.c
++++ b/ip/iproute_lwtunnel.c
+@@ -255,8 +255,9 @@ static int parse_encap_mpls(struct rtattr *rta, size_t len,
+ 		exit(1);
+ 	}
+ 
+-	rta_addattr_l(rta, len, MPLS_IPTUNNEL_DST, &addr.data,
+-		      addr.bytelen);
++	if (rta_addattr_l(rta, len, MPLS_IPTUNNEL_DST,
++			  &addr.data, addr.bytelen))
++		return -1;
+ 
+ 	*argcp = argc;
+ 	*argvp = argv;
+@@ -270,6 +271,7 @@ static int parse_encap_ip(struct rtattr *rta, size_t len,
+ 	int id_ok = 0, dst_ok = 0, tos_ok = 0, ttl_ok = 0;
+ 	char **argv = *argvp;
+ 	int argc = *argcp;
++	int ret = 0;
+ 
+ 	while (argc > 0) {
+ 		if (strcmp(*argv, "id") == 0) {
+@@ -280,7 +282,7 @@ static int parse_encap_ip(struct rtattr *rta, size_t len,
+ 				duparg2("id", *argv);
+ 			if (get_be64(&id, *argv, 0))
+ 				invarg("\"id\" value is invalid\n", *argv);
+-			rta_addattr64(rta, len, LWTUNNEL_IP_ID, id);
++			ret = rta_addattr64(rta, len, LWTUNNEL_IP_ID, id);
+ 		} else if (strcmp(*argv, "dst") == 0) {
+ 			inet_prefix addr;
+ 
+@@ -288,8 +290,8 @@ static int parse_encap_ip(struct rtattr *rta, size_t len,
+ 			if (dst_ok++)
+ 				duparg2("dst", *argv);
+ 			get_addr(&addr, *argv, AF_INET);
+-			rta_addattr_l(rta, len, LWTUNNEL_IP_DST,
+-				      &addr.data, addr.bytelen);
++			ret = rta_addattr_l(rta, len, LWTUNNEL_IP_DST,
++					    &addr.data, addr.bytelen);
+ 		} else if (strcmp(*argv, "tos") == 0) {
+ 			__u32 tos;
+ 
+@@ -298,7 +300,7 @@ static int parse_encap_ip(struct rtattr *rta, size_t len,
+ 				duparg2("tos", *argv);
+ 			if (rtnl_dsfield_a2n(&tos, *argv))
+ 				invarg("\"tos\" value is invalid\n", *argv);
+-			rta_addattr8(rta, len, LWTUNNEL_IP_TOS, tos);
++			ret = rta_addattr8(rta, len, LWTUNNEL_IP_TOS, tos);
+ 		} else if (strcmp(*argv, "ttl") == 0) {
+ 			__u8 ttl;
+ 
+@@ -307,10 +309,12 @@ static int parse_encap_ip(struct rtattr *rta, size_t len,
+ 				duparg2("ttl", *argv);
+ 			if (get_u8(&ttl, *argv, 0))
+ 				invarg("\"ttl\" value is invalid\n", *argv);
+-			rta_addattr8(rta, len, LWTUNNEL_IP_TTL, ttl);
++			ret = rta_addattr8(rta, len, LWTUNNEL_IP_TTL, ttl);
+ 		} else {
+ 			break;
+ 		}
++		if (ret)
++			break;
+ 		argc--; argv++;
+ 	}
+ 
+@@ -321,7 +325,7 @@ static int parse_encap_ip(struct rtattr *rta, size_t len,
+ 	*argcp = argc + 1;
+ 	*argvp = argv - 1;
+ 
+-	return 0;
++	return ret;
+ }
+ 
+ static int parse_encap_ila(struct rtattr *rta, size_t len,
+@@ -330,6 +334,7 @@ static int parse_encap_ila(struct rtattr *rta, size_t len,
+ 	__u64 locator;
+ 	int argc = *argcp;
+ 	char **argv = *argvp;
++	int ret = 0;
+ 
+ 	if (get_addr64(&locator, *argv) < 0) {
+ 		fprintf(stderr, "Bad locator: %s\n", *argv);
+@@ -338,7 +343,8 @@ static int parse_encap_ila(struct rtattr *rta, size_t len,
+ 
+ 	argc--; argv++;
+ 
+-	rta_addattr64(rta, 1024, ILA_ATTR_LOCATOR, locator);
++	if (rta_addattr64(rta, 1024, ILA_ATTR_LOCATOR, locator))
++		return -1;
+ 
+ 	while (argc > 0) {
+ 		if (strcmp(*argv, "csum-mode") == 0) {
+@@ -351,12 +357,15 @@ static int parse_encap_ila(struct rtattr *rta, size_t len,
+ 				invarg("\"csum-mode\" value is invalid\n",
+ 				       *argv);
+ 
+-			rta_addattr8(rta, 1024, ILA_ATTR_CSUM_MODE, csum_mode);
++			ret = rta_addattr8(rta, 1024, ILA_ATTR_CSUM_MODE,
++					   (__u8)csum_mode);
+ 
+ 			argc--; argv++;
+ 		} else {
+ 			break;
+ 		}
++		if (ret)
++			break;
+ 	}
+ 
+ 	/* argv is currently the first unparsed argument,
+@@ -366,7 +375,7 @@ static int parse_encap_ila(struct rtattr *rta, size_t len,
+ 	*argcp = argc + 1;
+ 	*argvp = argv - 1;
+ 
+-	return 0;
++	return ret;
+ }
+ 
+ static int parse_encap_ip6(struct rtattr *rta, size_t len,
+@@ -375,6 +384,7 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len,
+ 	int id_ok = 0, dst_ok = 0, tos_ok = 0, ttl_ok = 0;
+ 	char **argv = *argvp;
+ 	int argc = *argcp;
++	int ret = 0;
+ 
+ 	while (argc > 0) {
+ 		if (strcmp(*argv, "id") == 0) {
+@@ -385,7 +395,7 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len,
+ 				duparg2("id", *argv);
+ 			if (get_be64(&id, *argv, 0))
+ 				invarg("\"id\" value is invalid\n", *argv);
+-			rta_addattr64(rta, len, LWTUNNEL_IP6_ID, id);
++			ret = rta_addattr64(rta, len, LWTUNNEL_IP6_ID, id);
+ 		} else if (strcmp(*argv, "dst") == 0) {
+ 			inet_prefix addr;
+ 
+@@ -393,8 +403,8 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len,
+ 			if (dst_ok++)
+ 				duparg2("dst", *argv);
+ 			get_addr(&addr, *argv, AF_INET6);
+-			rta_addattr_l(rta, len, LWTUNNEL_IP6_DST,
+-				      &addr.data, addr.bytelen);
++			ret = rta_addattr_l(rta, len, LWTUNNEL_IP6_DST,
++					    &addr.data, addr.bytelen);
+ 		} else if (strcmp(*argv, "tc") == 0) {
+ 			__u32 tc;
+ 
+@@ -403,7 +413,7 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len,
+ 				duparg2("tc", *argv);
+ 			if (rtnl_dsfield_a2n(&tc, *argv))
+ 				invarg("\"tc\" value is invalid\n", *argv);
+-			rta_addattr8(rta, len, LWTUNNEL_IP6_TC, tc);
++			ret = rta_addattr8(rta, len, LWTUNNEL_IP6_TC, tc);
+ 		} else if (strcmp(*argv, "hoplimit") == 0) {
+ 			__u8 hoplimit;
+ 
+@@ -413,10 +423,13 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len,
+ 			if (get_u8(&hoplimit, *argv, 0))
+ 				invarg("\"hoplimit\" value is invalid\n",
+ 				       *argv);
+-			rta_addattr8(rta, len, LWTUNNEL_IP6_HOPLIMIT, hoplimit);
++			ret = rta_addattr8(rta, len, LWTUNNEL_IP6_HOPLIMIT,
++					   hoplimit);
+ 		} else {
+ 			break;
+ 		}
++		if (ret)
++			break;
+ 		argc--; argv++;
+ 	}
+ 
+@@ -427,7 +440,7 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len,
+ 	*argcp = argc + 1;
+ 	*argvp = argv - 1;
+ 
+-	return 0;
++	return ret;
+ }
+ 
+ struct lwt_x {
+@@ -542,6 +555,7 @@ int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp)
+ 	int argc = *argcp;
+ 	char **argv = *argvp;
+ 	__u16 type;
++	int ret = 0;
+ 
+ 	NEXT_ARG();
+ 	type = read_encap_type(*argv);
+@@ -558,16 +572,16 @@ int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp)
+ 	nest = rta_nest(rta, 1024, RTA_ENCAP);
+ 	switch (type) {
+ 	case LWTUNNEL_ENCAP_MPLS:
+-		parse_encap_mpls(rta, len, &argc, &argv);
++		ret = parse_encap_mpls(rta, len, &argc, &argv);
+ 		break;
+ 	case LWTUNNEL_ENCAP_IP:
+-		parse_encap_ip(rta, len, &argc, &argv);
++		ret = parse_encap_ip(rta, len, &argc, &argv);
+ 		break;
+ 	case LWTUNNEL_ENCAP_ILA:
+-		parse_encap_ila(rta, len, &argc, &argv);
++		ret = parse_encap_ila(rta, len, &argc, &argv);
+ 		break;
+ 	case LWTUNNEL_ENCAP_IP6:
+-		parse_encap_ip6(rta, len, &argc, &argv);
++		ret = parse_encap_ip6(rta, len, &argc, &argv);
+ 		break;
+ 	case LWTUNNEL_ENCAP_BPF:
+ 		if (parse_encap_bpf(rta, len, &argc, &argv) < 0)
+@@ -577,12 +591,15 @@ int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp)
+ 		fprintf(stderr, "Error: unsupported encap type\n");
+ 		break;
+ 	}
++	if (ret)
++		return ret;
++
+ 	rta_nest_end(rta, nest);
+ 
+-	rta_addattr16(rta, 1024, RTA_ENCAP_TYPE, type);
++	ret = rta_addattr16(rta, 1024, RTA_ENCAP_TYPE, type);
+ 
+ 	*argcp = argc;
+ 	*argvp = argv;
+ 
+-	return 0;
++	return ret;
+ }
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0052-man-ip-route.8-Document-nexthop-limit.patch b/SOURCES/0052-man-ip-route.8-Document-nexthop-limit.patch
new file mode 100644
index 0000000..cc483b9
--- /dev/null
+++ b/SOURCES/0052-man-ip-route.8-Document-nexthop-limit.patch
@@ -0,0 +1,46 @@
+From d511d7e60866060e260ec3f96b51a61c98c2c06f Mon Sep 17 00:00:00 2001
+From: Phil Sutter <psutter@redhat.com>
+Date: Thu, 21 Feb 2019 14:39:46 +0100
+Subject: [PATCH] man: ip-route.8: Document nexthop limit
+
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1624656
+Upstream Status: iproute2.git commit 6cd959bb125c5
+
+commit 6cd959bb125c50a04ab6671645fa38c5b07426f4
+Author: Phil Sutter <phil@nwl.cc>
+Date:   Tue Nov 13 16:55:13 2018 +0100
+
+    man: ip-route.8: Document nexthop limit
+
+    Add a note to 'nexthop' description stating the maximum number of
+    nexthops per command and pointing at 'append' command as a workaround.
+
+    Signed-off-by: Phil Sutter <phil@nwl.cc>
+    Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
+---
+ man/man8/ip-route.8.in | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/man/man8/ip-route.8.in b/man/man8/ip-route.8.in
+index d6e0664..d9a5477 100644
+--- a/man/man8/ip-route.8.in
++++ b/man/man8/ip-route.8.in
+@@ -548,6 +548,15 @@ argument lists:
+ route reflecting its relative bandwidth or quality.
+ .in -8
+ 
++The internal buffer used in iproute2 limits the maximum number of nexthops that
++may be specified in one go. If only
++.I ADDRESS
++is given, the current buffer size allows for 144 IPv6 nexthops and 253 IPv4
++ones. For IPv4, this effectively limits the number of nexthops possible per
++route. With IPv6, further nexthops may be appended to the same route via
++.B "ip route append"
++command.
++
+ .TP
+ .BI scope " SCOPE_VAL"
+ the scope of the destinations covered by the route prefix.
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0053-ip-route-Fix-nexthop-encap-parsing.patch b/SOURCES/0053-ip-route-Fix-nexthop-encap-parsing.patch
new file mode 100644
index 0000000..ff535eb
--- /dev/null
+++ b/SOURCES/0053-ip-route-Fix-nexthop-encap-parsing.patch
@@ -0,0 +1,85 @@
+From b83b0767eccfb386406ccb24130b975f1c2b0ee4 Mon Sep 17 00:00:00 2001
+From: Phil Sutter <psutter@redhat.com>
+Date: Thu, 21 Feb 2019 14:39:47 +0100
+Subject: [PATCH] ip-route: Fix nexthop encap parsing
+
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1624656
+Upstream Status: iproute2.git commit 05d978e0850a6
+Conflicts: Some chunks dropped due to missing support for
+           ident-type and hook-type.
+
+commit 05d978e0850a6a3bae1e6c5392d82f7b1496f86a
+Author: Phil Sutter <phil@nwl.cc>
+Date:   Tue Nov 13 13:39:04 2018 +0100
+
+    ip-route: Fix nexthop encap parsing
+
+    When parsing nexthop parameters, a buffer of 4k bytes is provided. Yet,
+    in lwt_parse_encap() and some functions called by it, buffer size was
+    assumed to be 1k despite the actual size was provided. This led to
+    spurious buffer size errors if the buffer was filled by previous nexthop
+    parameters to exceed that 1k boundary.
+
+    Fixes: 1e5293056a02c ("lwtunnel: Add encapsulation support to ip route")
+    Fixes: 5866bddd9aa9e ("ila: Add support for ILA lwtunnels")
+    Fixes: ed67f83806538 ("ila: Support for checksum neutral translation")
+    Fixes: 86905c8f057c0 ("ila: support for configuring identifier and hook types")
+    Fixes: b15f440e78373 ("lwt: BPF support for LWT")
+    Signed-off-by: Phil Sutter <phil@nwl.cc>
+    Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
+---
+ ip/iproute_lwtunnel.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c
+index 1a68912..b6f08f0 100644
+--- a/ip/iproute_lwtunnel.c
++++ b/ip/iproute_lwtunnel.c
+@@ -343,7 +343,7 @@ static int parse_encap_ila(struct rtattr *rta, size_t len,
+ 
+ 	argc--; argv++;
+ 
+-	if (rta_addattr64(rta, 1024, ILA_ATTR_LOCATOR, locator))
++	if (rta_addattr64(rta, len, ILA_ATTR_LOCATOR, locator))
+ 		return -1;
+ 
+ 	while (argc > 0) {
+@@ -357,7 +357,7 @@ static int parse_encap_ila(struct rtattr *rta, size_t len,
+ 				invarg("\"csum-mode\" value is invalid\n",
+ 				       *argv);
+ 
+-			ret = rta_addattr8(rta, 1024, ILA_ATTR_CSUM_MODE,
++			ret = rta_addattr8(rta, len, ILA_ATTR_CSUM_MODE,
+ 					   (__u8)csum_mode);
+ 
+ 			argc--; argv++;
+@@ -528,7 +528,7 @@ static int parse_encap_bpf(struct rtattr *rta, size_t len, int *argcp,
+ 			if (get_unsigned(&headroom, *argv, 0) || headroom == 0)
+ 				invarg("headroom is invalid\n", *argv);
+ 			if (!headroom_set)
+-				rta_addattr32(rta, 1024, LWT_BPF_XMIT_HEADROOM,
++				rta_addattr32(rta, len, LWT_BPF_XMIT_HEADROOM,
+ 					      headroom);
+ 			headroom_set = 1;
+ 		} else if (strcmp(*argv, "help") == 0) {
+@@ -569,7 +569,7 @@ int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp)
+ 		exit(-1);
+ 	}
+ 
+-	nest = rta_nest(rta, 1024, RTA_ENCAP);
++	nest = rta_nest(rta, len, RTA_ENCAP);
+ 	switch (type) {
+ 	case LWTUNNEL_ENCAP_MPLS:
+ 		ret = parse_encap_mpls(rta, len, &argc, &argv);
+@@ -596,7 +596,7 @@ int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp)
+ 
+ 	rta_nest_end(rta, nest);
+ 
+-	ret = rta_addattr16(rta, 1024, RTA_ENCAP_TYPE, type);
++	ret = rta_addattr16(rta, len, RTA_ENCAP_TYPE, type);
+ 
+ 	*argcp = argc;
+ 	*argvp = argv;
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0054-ip-link-Fix-listing-of-alias-interfaces.patch b/SOURCES/0054-ip-link-Fix-listing-of-alias-interfaces.patch
new file mode 100644
index 0000000..534b391
--- /dev/null
+++ b/SOURCES/0054-ip-link-Fix-listing-of-alias-interfaces.patch
@@ -0,0 +1,57 @@
+From eb3be709aece2325f7eafc113120cf5ef8f077de Mon Sep 17 00:00:00 2001
+From: Phil Sutter <psutter@redhat.com>
+Date: Mon, 11 Mar 2019 16:28:41 +0100
+Subject: [PATCH] ip-link: Fix listing of alias interfaces
+
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1673226
+Upstream Status: RHEL-only
+Conflicts: Context change due to missing commit 260137e24d3b7
+           ("iplink: Remove flags argument from iplink_get")
+
+Upstream rejected this patch as the alias notation is neither required
+nor wanted by iproute2[1]. With iproute rebase in RHEL7.5 though, we
+changed existing behaviour by accident. Therefore we will carry this
+patch for RHEL7 lifetime.
+
+[1] https://marc.info/?l=linux-netdev&m=154964861913609&w=2
+
+commit a1259acb3c2037f464e31fad1f21556f8bf58c91
+Author: Phil Sutter <phil@nwl.cc>
+Date:   Thu Feb 7 10:18:16 2019 +0100
+
+    ip-link: Fix listing of alias interfaces
+
+    Commit 50b9950dd9011 ("link dump filter") accidentally broke listing of
+    links in the old alias interface notation:
+
+    | % ip link show eth0:1
+    | RTNETLINK answers: No such device
+    | Cannot send link get request: No such device
+
+    Prior to the above commit, link lookup was performed via ifindex
+    returned by if_nametoindex(). The latter uses SIOCGIFINDEX ioctl call
+    which on kernel side causes the colon-suffix to be dropped before doing
+    the interface lookup. Netlink API though doesn't care about that at all.
+    To keep things backward compatible, mimick ioctl API behaviour and drop
+    the colon-suffix prior to sending the RTM_GETLINK request.
+
+    Fixes: 50b9950dd9011 ("link dump filter")
+---
+ ip/ipaddress.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/ip/ipaddress.c b/ip/ipaddress.c
+index 7492075..14e9e22 100644
+--- a/ip/ipaddress.c
++++ b/ip/ipaddress.c
+@@ -1707,6 +1707,7 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
+ 	 * the link device
+ 	 */
+ 	if (filter_dev && filter.group == -1 && do_link == 1) {
++		*strchrnul(filter_dev, ':') = '\0';
+ 		if (iplink_get(0, filter_dev, RTEXT_FILTER_VF) < 0) {
+ 			perror("Cannot send link get request");
+ 			exit(1);
+-- 
+1.8.3.1
+
diff --git a/SPECS/iproute.spec b/SPECS/iproute.spec
index 0521a43..0f0a78e 100644
--- a/SPECS/iproute.spec
+++ b/SPECS/iproute.spec
@@ -2,7 +2,7 @@
 
 %define rpmversion 4.11.0
 %define baserelease 0.el7
-%define specrelease 14%{?dist}
+%define specrelease 14%{?dist}.2
 %define pkg_release %{specrelease}%{?buildid}
 
 Summary:            Advanced IP routing and network device configuration tools
@@ -58,6 +58,11 @@ Patch39:            0040-link_gre6-Detect-invalid-encaplimit-values.patch
 Patch40:            0041-man-tc-csum.8-Fix-inconsistency-in-example-descripti.patch
 Patch41:            0042-tc-fix-command-tc-actions-del-hang-issue.patch
 Patch42:            0043-ip-link-Fix-use-after-free-in-nl_get_ll_addr_len.patch
+Patch43:            0050-iproute-Abort-if-nexthop-cannot-be-parsed.patch
+Patch44:            0051-ip-route-Fix-segfault-with-many-nexthops.patch
+Patch45:            0052-man-ip-route.8-Document-nexthop-limit.patch
+Patch46:            0053-ip-route-Fix-nexthop-encap-parsing.patch
+Patch47:            0054-ip-link-Fix-listing-of-alias-interfaces.patch
 License:            GPLv2+ and Public Domain
 BuildRequires:      bison
 BuildRequires:      flex
@@ -170,6 +175,15 @@ cat %{SOURCE3} >>%{buildroot}%{_sysconfdir}/iproute2/rt_dsfield
 %{_includedir}/iproute2/bpf_elf.h
 
 %changelog
+* Tue Mar 12 2019 Phil Sutter <psutter@redhat.com> [4.11.0-14.el7_6.2]
+- ip-link: Fix listing of alias interfaces (Phil Sutter) [1687717]
+
+* Fri Mar 01 2019 Phil Sutter <psutter@redhat.com> [4.11.0-14.el7_6.1]
+- ip-route: Fix nexthop encap parsing (Phil Sutter) [1679996]
+- man: ip-route.8: Document nexthop limit (Phil Sutter) [1679996]
+- ip-route: Fix segfault with many nexthops (Phil Sutter) [1679996]
+- iproute: Abort if nexthop cannot be parsed (Phil Sutter) [1679996]
+
 * Tue Mar 06 2018 Phil Sutter <psutter@redhat.com> [4.11.0-14.el7]
 - ip-link: Fix use after free in nl_get_ll_addr_len() (Phil Sutter) [1550097]