diff options
-rw-r--r-- | net/core/rtnetlink.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 233b5ae87583..1063996f8317 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -1244,6 +1244,7 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | |||
1244 | struct nlattr *tb[IFLA_MAX+1]; | 1244 | struct nlattr *tb[IFLA_MAX+1]; |
1245 | u32 ext_filter_mask = 0; | 1245 | u32 ext_filter_mask = 0; |
1246 | int err; | 1246 | int err; |
1247 | int hdrlen; | ||
1247 | 1248 | ||
1248 | s_h = cb->args[0]; | 1249 | s_h = cb->args[0]; |
1249 | s_idx = cb->args[1]; | 1250 | s_idx = cb->args[1]; |
@@ -1251,8 +1252,17 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | |||
1251 | rcu_read_lock(); | 1252 | rcu_read_lock(); |
1252 | cb->seq = net->dev_base_seq; | 1253 | cb->seq = net->dev_base_seq; |
1253 | 1254 | ||
1254 | if (nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX, | 1255 | /* A hack to preserve kernel<->userspace interface. |
1255 | ifla_policy) >= 0) { | 1256 | * The correct header is ifinfomsg. It is consistent with rtnl_getlink. |
1257 | * However, before Linux v3.9 the code here assumed rtgenmsg and that's | ||
1258 | * what iproute2 < v3.9.0 used. | ||
1259 | * We can detect the old iproute2. Even including the IFLA_EXT_MASK | ||
1260 | * attribute, its netlink message is shorter than struct ifinfomsg. | ||
1261 | */ | ||
1262 | hdrlen = nlmsg_len(cb->nlh) < sizeof(struct ifinfomsg) ? | ||
1263 | sizeof(struct rtgenmsg) : sizeof(struct ifinfomsg); | ||
1264 | |||
1265 | if (nlmsg_parse(cb->nlh, hdrlen, tb, IFLA_MAX, ifla_policy) >= 0) { | ||
1256 | 1266 | ||
1257 | if (tb[IFLA_EXT_MASK]) | 1267 | if (tb[IFLA_EXT_MASK]) |
1258 | ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]); | 1268 | 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) | |||
2126 | struct nlattr *tb[IFLA_MAX+1]; | 2136 | struct nlattr *tb[IFLA_MAX+1]; |
2127 | u32 ext_filter_mask = 0; | 2137 | u32 ext_filter_mask = 0; |
2128 | u16 min_ifinfo_dump_size = 0; | 2138 | u16 min_ifinfo_dump_size = 0; |
2139 | int hdrlen; | ||
2140 | |||
2141 | /* Same kernel<->userspace interface hack as in rtnl_dump_ifinfo. */ | ||
2142 | hdrlen = nlmsg_len(nlh) < sizeof(struct ifinfomsg) ? | ||
2143 | sizeof(struct rtgenmsg) : sizeof(struct ifinfomsg); | ||
2129 | 2144 | ||
2130 | if (nlmsg_parse(nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX, | 2145 | if (nlmsg_parse(nlh, hdrlen, tb, IFLA_MAX, ifla_policy) >= 0) { |
2131 | ifla_policy) >= 0) { | ||
2132 | if (tb[IFLA_EXT_MASK]) | 2146 | if (tb[IFLA_EXT_MASK]) |
2133 | ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]); | 2147 | ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]); |
2134 | } | 2148 | } |