aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/core/rtnetlink.c22
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 }