|
@@ -1244,6 +1244,7 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
|
|
struct nlattr *tb[IFLA_MAX+1];
|
|
struct nlattr *tb[IFLA_MAX+1];
|
|
u32 ext_filter_mask = 0;
|
|
u32 ext_filter_mask = 0;
|
|
int err;
|
|
int err;
|
|
|
|
+ int hdrlen;
|
|
|
|
|
|
s_h = cb->args[0];
|
|
s_h = cb->args[0];
|
|
s_idx = cb->args[1];
|
|
s_idx = cb->args[1];
|
|
@@ -1251,8 +1252,17 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
|
|
rcu_read_lock();
|
|
rcu_read_lock();
|
|
cb->seq = net->dev_base_seq;
|
|
cb->seq = net->dev_base_seq;
|
|
|
|
|
|
- if (nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX,
|
|
|
|
- ifla_policy) >= 0) {
|
|
|
|
|
|
+ /* A hack to preserve kernel<->userspace interface.
|
|
|
|
+ * The correct header is ifinfomsg. It is consistent with rtnl_getlink.
|
|
|
|
+ * However, before Linux v3.9 the code here assumed rtgenmsg and that's
|
|
|
|
+ * what iproute2 < v3.9.0 used.
|
|
|
|
+ * We can detect the old iproute2. Even including the IFLA_EXT_MASK
|
|
|
|
+ * attribute, its netlink message is shorter than struct ifinfomsg.
|
|
|
|
+ */
|
|
|
|
+ hdrlen = nlmsg_len(cb->nlh) < sizeof(struct ifinfomsg) ?
|
|
|
|
+ sizeof(struct rtgenmsg) : sizeof(struct ifinfomsg);
|
|
|
|
+
|
|
|
|
+ if (nlmsg_parse(cb->nlh, hdrlen, tb, IFLA_MAX, ifla_policy) >= 0) {
|
|
|
|
|
|
if (tb[IFLA_EXT_MASK])
|
|
if (tb[IFLA_EXT_MASK])
|
|
ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
|
|
ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
|
|
@@ -2126,9 +2136,13 @@ static u16 rtnl_calcit(struct sk_buff *skb, struct nlmsghdr *nlh)
|
|
struct nlattr *tb[IFLA_MAX+1];
|
|
struct nlattr *tb[IFLA_MAX+1];
|
|
u32 ext_filter_mask = 0;
|
|
u32 ext_filter_mask = 0;
|
|
u16 min_ifinfo_dump_size = 0;
|
|
u16 min_ifinfo_dump_size = 0;
|
|
|
|
+ int hdrlen;
|
|
|
|
+
|
|
|
|
+ /* Same kernel<->userspace interface hack as in rtnl_dump_ifinfo. */
|
|
|
|
+ hdrlen = nlmsg_len(nlh) < sizeof(struct ifinfomsg) ?
|
|
|
|
+ sizeof(struct rtgenmsg) : sizeof(struct ifinfomsg);
|
|
|
|
|
|
- if (nlmsg_parse(nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX,
|
|
|
|
- ifla_policy) >= 0) {
|
|
|
|
|
|
+ if (nlmsg_parse(nlh, hdrlen, tb, IFLA_MAX, ifla_policy) >= 0) {
|
|
if (tb[IFLA_EXT_MASK])
|
|
if (tb[IFLA_EXT_MASK])
|
|
ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
|
|
ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
|
|
}
|
|
}
|