summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2014-09-25 16:44:09 +0200
committerThomas Haller <thaller@redhat.com>2014-09-25 17:45:53 +0200
commit4d675ce0fcef7f33311258df94e98f31dab15680 (patch)
treea421a87f4e86ba28931da2d66a2f7ba33b846b28
parent6d65f1d56ff2ab55a70f11bef9b163c326c8055f (diff)
platform: fix parsing vxlan netlink message for older kernel
vxlan_info_data_parser() must take care of missing netlink attributes. Otherwise, older kernels will crash NM. Also, workaround compilation against old kernel headers which are missing 'struct ifla_vxlan_port_range'. We do this by defining our own 'struct nm_ifla_vxlan_port_range' version. Reported-by: Javier Jardón <jjardon@gnome.org> Signed-off-by: Thomas Haller <thaller@redhat.com>
-rw-r--r--src/platform/nm-linux-platform.c60
1 files changed, 41 insertions, 19 deletions
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index 5b308f7e2f..26fa5fe135 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -3059,6 +3059,13 @@ macvlan_get_properties (NMPlatform *platform, int ifindex, NMPlatformMacvlanProp
#undef IFLA_VXLAN_MAX
#define IFLA_VXLAN_MAX IFLA_VXLAN_LOCAL6
+/* older kernel header might not contain 'struct ifla_vxlan_port_range'.
+ * Redefine it. */
+struct nm_ifla_vxlan_port_range {
+ guint16 low;
+ guint16 high;
+};
+
static const struct nla_policy vxlan_info_policy[IFLA_VXLAN_MAX + 1] = {
[IFLA_VXLAN_ID] = { .type = NLA_U32 },
[IFLA_VXLAN_GROUP] = { .type = NLA_U32 },
@@ -3074,7 +3081,7 @@ static const struct nla_policy vxlan_info_policy[IFLA_VXLAN_MAX + 1] = {
[IFLA_VXLAN_AGEING] = { .type = NLA_U32 },
[IFLA_VXLAN_LIMIT] = { .type = NLA_U32 },
[IFLA_VXLAN_PORT_RANGE] = { .type = NLA_UNSPEC,
- .minlen = sizeof (struct ifla_vxlan_port_range) },
+ .minlen = sizeof (struct nm_ifla_vxlan_port_range) },
[IFLA_VXLAN_PROXY] = { .type = NLA_U8 },
[IFLA_VXLAN_RSC] = { .type = NLA_U8 },
[IFLA_VXLAN_L2MISS] = { .type = NLA_U8 },
@@ -3087,7 +3094,7 @@ vxlan_info_data_parser (struct nlattr *info_data, gpointer parser_data)
{
NMPlatformVxlanProperties *props = parser_data;
struct nlattr *tb[IFLA_VXLAN_MAX + 1];
- struct ifla_vxlan_port_range *range;
+ struct nm_ifla_vxlan_port_range *range;
int err;
err = nla_parse_nested (tb, IFLA_VXLAN_MAX, info_data,
@@ -3097,8 +3104,10 @@ vxlan_info_data_parser (struct nlattr *info_data, gpointer parser_data)
memset (props, 0, sizeof (*props));
- props->parent_ifindex = tb[IFLA_VXLAN_LINK] ? nla_get_u32 (tb[IFLA_VXLAN_LINK]) : 0;
- props->id = nla_get_u32 (tb[IFLA_VXLAN_ID]);
+ if (tb[IFLA_VXLAN_LINK])
+ props->parent_ifindex = nla_get_u32 (tb[IFLA_VXLAN_LINK]);
+ if (tb[IFLA_VXLAN_ID])
+ props->id = nla_get_u32 (tb[IFLA_VXLAN_ID]);
if (tb[IFLA_VXLAN_GROUP])
props->group = nla_get_u32 (tb[IFLA_VXLAN_GROUP]);
if (tb[IFLA_VXLAN_LOCAL])
@@ -3108,21 +3117,34 @@ vxlan_info_data_parser (struct nlattr *info_data, gpointer parser_data)
if (tb[IFLA_VXLAN_LOCAL6])
memcpy (&props->local6, nla_data (tb[IFLA_VXLAN_LOCAL6]), sizeof (props->local6));
- props->ageing = nla_get_u32 (tb[IFLA_VXLAN_AGEING]);
- props->limit = nla_get_u32 (tb[IFLA_VXLAN_LIMIT]);
- props->tos = nla_get_u8 (tb[IFLA_VXLAN_TOS]);
- props->ttl = nla_get_u8 (tb[IFLA_VXLAN_TTL]);
-
- props->dst_port = nla_get_u16 (tb[IFLA_VXLAN_PORT]);
- range = nla_data (tb[IFLA_VXLAN_PORT_RANGE]);
- props->src_port_min = range->low;
- props->src_port_max = range->high;
-
- props->learning = !!nla_get_u8 (tb[IFLA_VXLAN_LEARNING]);
- props->proxy = !!nla_get_u8 (tb[IFLA_VXLAN_PROXY]);
- props->rsc = !!nla_get_u8 (tb[IFLA_VXLAN_RSC]);
- props->l2miss = !!nla_get_u8 (tb[IFLA_VXLAN_L2MISS]);
- props->l3miss = !!nla_get_u8 (tb[IFLA_VXLAN_L3MISS]);
+ if (tb[IFLA_VXLAN_AGEING])
+ props->ageing = nla_get_u32 (tb[IFLA_VXLAN_AGEING]);
+ if (tb[IFLA_VXLAN_LIMIT])
+ props->limit = nla_get_u32 (tb[IFLA_VXLAN_LIMIT]);
+ if (tb[IFLA_VXLAN_TOS])
+ props->tos = nla_get_u8 (tb[IFLA_VXLAN_TOS]);
+ if (tb[IFLA_VXLAN_TTL])
+ props->ttl = nla_get_u8 (tb[IFLA_VXLAN_TTL]);
+
+ if (tb[IFLA_VXLAN_PORT])
+ props->dst_port = nla_get_u16 (tb[IFLA_VXLAN_PORT]);
+
+ if (tb[IFLA_VXLAN_PORT_RANGE]) {
+ range = nla_data (tb[IFLA_VXLAN_PORT_RANGE]);
+ props->src_port_min = range->low;
+ props->src_port_max = range->high;
+ }
+
+ if (tb[IFLA_VXLAN_LEARNING])
+ props->learning = !!nla_get_u8 (tb[IFLA_VXLAN_LEARNING]);
+ if (tb[IFLA_VXLAN_PROXY])
+ props->proxy = !!nla_get_u8 (tb[IFLA_VXLAN_PROXY]);
+ if (tb[IFLA_VXLAN_RSC])
+ props->rsc = !!nla_get_u8 (tb[IFLA_VXLAN_RSC]);
+ if (tb[IFLA_VXLAN_L2MISS])
+ props->l2miss = !!nla_get_u8 (tb[IFLA_VXLAN_L2MISS]);
+ if (tb[IFLA_VXLAN_L3MISS])
+ props->l3miss = !!nla_get_u8 (tb[IFLA_VXLAN_L3MISS]);
return 0;
}