From df217d5d5ccc25e564acf94935ab5d74443fe69b Mon Sep 17 00:00:00 2001 From: Jiri Benc Date: Wed, 27 Apr 2016 16:11:13 +0200 Subject: [PATCH] ip link gre: create interfaces in external mode correctly For GRE interfaces in 'external' mode, the kernel ignores all manual settings like remote IP address or TTL. However, for some of those attributes, kernel checks their value and does not allow them to be zero (even though they're ignored later). Currently, 'ip link' always includes all attributes in the netlink message. This leads to problem with creating interfaces in 'external' mode. For example, this command does not work: ip link add gre1 type gretap external and needs a bogus remote IP address to be specified, as the kernel enforces remote IP address to be either not present, or not null. Ignore the parameters that do not make sense in 'external' mode. Unfortunately, we cannot error out, as there may be existing deployments that workarounded the bug by specifying bogus values. Fixes: 926b39e1feffd ("gre: add support for collect metadata flag") Signed-off-by: Jiri Benc --- ip/link_gre.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/ip/link_gre.c b/ip/link_gre.c index bcf003aa..36ce1252 100644 --- a/ip/link_gre.c +++ b/ip/link_gre.c @@ -315,24 +315,26 @@ get_failed: return -1; } - addattr32(n, 1024, IFLA_GRE_IKEY, ikey); - addattr32(n, 1024, IFLA_GRE_OKEY, okey); - addattr_l(n, 1024, IFLA_GRE_IFLAGS, &iflags, 2); - addattr_l(n, 1024, IFLA_GRE_OFLAGS, &oflags, 2); - addattr_l(n, 1024, IFLA_GRE_LOCAL, &saddr, 4); - addattr_l(n, 1024, IFLA_GRE_REMOTE, &daddr, 4); - addattr_l(n, 1024, IFLA_GRE_PMTUDISC, &pmtudisc, 1); - if (link) - addattr32(n, 1024, IFLA_GRE_LINK, link); - addattr_l(n, 1024, IFLA_GRE_TTL, &ttl, 1); - addattr_l(n, 1024, IFLA_GRE_TOS, &tos, 1); + if (!metadata) { + addattr32(n, 1024, IFLA_GRE_IKEY, ikey); + addattr32(n, 1024, IFLA_GRE_OKEY, okey); + addattr_l(n, 1024, IFLA_GRE_IFLAGS, &iflags, 2); + addattr_l(n, 1024, IFLA_GRE_OFLAGS, &oflags, 2); + addattr_l(n, 1024, IFLA_GRE_LOCAL, &saddr, 4); + addattr_l(n, 1024, IFLA_GRE_REMOTE, &daddr, 4); + addattr_l(n, 1024, IFLA_GRE_PMTUDISC, &pmtudisc, 1); + if (link) + addattr32(n, 1024, IFLA_GRE_LINK, link); + addattr_l(n, 1024, IFLA_GRE_TTL, &ttl, 1); + addattr_l(n, 1024, IFLA_GRE_TOS, &tos, 1); + } else { + addattr_l(n, 1024, IFLA_GRE_COLLECT_METADATA, NULL, 0); + } addattr16(n, 1024, IFLA_GRE_ENCAP_TYPE, encaptype); addattr16(n, 1024, IFLA_GRE_ENCAP_FLAGS, encapflags); addattr16(n, 1024, IFLA_GRE_ENCAP_SPORT, htons(encapsport)); addattr16(n, 1024, IFLA_GRE_ENCAP_DPORT, htons(encapdport)); - if (metadata) - addattr_l(n, 1024, IFLA_GRE_COLLECT_METADATA, NULL, 0); return 0; }