diff options
author | Thomas Haller <thaller@redhat.com> | 2014-09-25 16:44:09 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2014-09-25 17:45:53 +0200 |
commit | 4d675ce0fcef7f33311258df94e98f31dab15680 (patch) | |
tree | a421a87f4e86ba28931da2d66a2f7ba33b846b28 | |
parent | 6d65f1d56ff2ab55a70f11bef9b163c326c8055f (diff) | |
download | NetworkManager-4d675ce0fcef7f33311258df94e98f31dab15680.tar.gz |
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.c | 60 |
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; } |