提交 7f2b8562 编写于 作者: Y Ying Xue 提交者: David S. Miller

net: nl80211: __dev_get_by_index instead of dev_get_by_index to find interface

As __cfg80211_rdev_from_attrs(), nl80211_dump_wiphy_parse() and
nl80211_set_wiphy() are all under rtnl_lock protection,
__dev_get_by_index() instead of dev_get_by_index() should be used
to find interface handler in them allowing us to avoid to change
interface reference counter.

Cc: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: NYing Xue <ying.xue@windriver.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 5af28de3
...@@ -165,7 +165,7 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs) ...@@ -165,7 +165,7 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
if (attrs[NL80211_ATTR_IFINDEX]) { if (attrs[NL80211_ATTR_IFINDEX]) {
int ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]); int ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
netdev = dev_get_by_index(netns, ifindex); netdev = __dev_get_by_index(netns, ifindex);
if (netdev) { if (netdev) {
if (netdev->ieee80211_ptr) if (netdev->ieee80211_ptr)
tmp = wiphy_to_dev( tmp = wiphy_to_dev(
...@@ -173,8 +173,6 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs) ...@@ -173,8 +173,6 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
else else
tmp = NULL; tmp = NULL;
dev_put(netdev);
/* not wireless device -- return error */ /* not wireless device -- return error */
if (!tmp) if (!tmp)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
...@@ -1656,7 +1654,7 @@ static int nl80211_dump_wiphy_parse(struct sk_buff *skb, ...@@ -1656,7 +1654,7 @@ static int nl80211_dump_wiphy_parse(struct sk_buff *skb,
struct cfg80211_registered_device *rdev; struct cfg80211_registered_device *rdev;
int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]); int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
netdev = dev_get_by_index(sock_net(skb->sk), ifidx); netdev = __dev_get_by_index(sock_net(skb->sk), ifidx);
if (!netdev) if (!netdev)
return -ENODEV; return -ENODEV;
if (netdev->ieee80211_ptr) { if (netdev->ieee80211_ptr) {
...@@ -1664,7 +1662,6 @@ static int nl80211_dump_wiphy_parse(struct sk_buff *skb, ...@@ -1664,7 +1662,6 @@ static int nl80211_dump_wiphy_parse(struct sk_buff *skb,
netdev->ieee80211_ptr->wiphy); netdev->ieee80211_ptr->wiphy);
state->filter_wiphy = rdev->wiphy_idx; state->filter_wiphy = rdev->wiphy_idx;
} }
dev_put(netdev);
} }
return 0; return 0;
...@@ -1987,7 +1984,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) ...@@ -1987,7 +1984,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[NL80211_ATTR_IFINDEX]) { if (info->attrs[NL80211_ATTR_IFINDEX]) {
int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]); int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
netdev = dev_get_by_index(genl_info_net(info), ifindex); netdev = __dev_get_by_index(genl_info_net(info), ifindex);
if (netdev && netdev->ieee80211_ptr) if (netdev && netdev->ieee80211_ptr)
rdev = wiphy_to_dev(netdev->ieee80211_ptr->wiphy); rdev = wiphy_to_dev(netdev->ieee80211_ptr->wiphy);
else else
...@@ -2015,32 +2012,24 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) ...@@ -2015,32 +2012,24 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME])); rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
if (result) if (result)
goto bad_res; return result;
if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) { if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) {
struct ieee80211_txq_params txq_params; struct ieee80211_txq_params txq_params;
struct nlattr *tb[NL80211_TXQ_ATTR_MAX + 1]; struct nlattr *tb[NL80211_TXQ_ATTR_MAX + 1];
if (!rdev->ops->set_txq_params) { if (!rdev->ops->set_txq_params)
result = -EOPNOTSUPP; return -EOPNOTSUPP;
goto bad_res;
}
if (!netdev) { if (!netdev)
result = -EINVAL; return -EINVAL;
goto bad_res;
}
if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
result = -EINVAL; return -EINVAL;
goto bad_res;
}
if (!netif_running(netdev)) { if (!netif_running(netdev))
result = -ENETDOWN; return -ENETDOWN;
goto bad_res;
}
nla_for_each_nested(nl_txq_params, nla_for_each_nested(nl_txq_params,
info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS], info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
...@@ -2051,12 +2040,12 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) ...@@ -2051,12 +2040,12 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
txq_params_policy); txq_params_policy);
result = parse_txq_params(tb, &txq_params); result = parse_txq_params(tb, &txq_params);
if (result) if (result)
goto bad_res; return result;
result = rdev_set_txq_params(rdev, netdev, result = rdev_set_txq_params(rdev, netdev,
&txq_params); &txq_params);
if (result) if (result)
goto bad_res; return result;
} }
} }
...@@ -2065,7 +2054,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) ...@@ -2065,7 +2054,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
nl80211_can_set_dev_channel(wdev) ? wdev : NULL, nl80211_can_set_dev_channel(wdev) ? wdev : NULL,
info); info);
if (result) if (result)
goto bad_res; return result;
} }
if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) { if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) {
...@@ -2076,19 +2065,15 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) ...@@ -2076,19 +2065,15 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
if (!(rdev->wiphy.features & NL80211_FEATURE_VIF_TXPOWER)) if (!(rdev->wiphy.features & NL80211_FEATURE_VIF_TXPOWER))
txp_wdev = NULL; txp_wdev = NULL;
if (!rdev->ops->set_tx_power) { if (!rdev->ops->set_tx_power)
result = -EOPNOTSUPP; return -EOPNOTSUPP;
goto bad_res;
}
idx = NL80211_ATTR_WIPHY_TX_POWER_SETTING; idx = NL80211_ATTR_WIPHY_TX_POWER_SETTING;
type = nla_get_u32(info->attrs[idx]); type = nla_get_u32(info->attrs[idx]);
if (!info->attrs[NL80211_ATTR_WIPHY_TX_POWER_LEVEL] && if (!info->attrs[NL80211_ATTR_WIPHY_TX_POWER_LEVEL] &&
(type != NL80211_TX_POWER_AUTOMATIC)) { (type != NL80211_TX_POWER_AUTOMATIC))
result = -EINVAL; return -EINVAL;
goto bad_res;
}
if (type != NL80211_TX_POWER_AUTOMATIC) { if (type != NL80211_TX_POWER_AUTOMATIC) {
idx = NL80211_ATTR_WIPHY_TX_POWER_LEVEL; idx = NL80211_ATTR_WIPHY_TX_POWER_LEVEL;
...@@ -2097,7 +2082,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) ...@@ -2097,7 +2082,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
result = rdev_set_tx_power(rdev, txp_wdev, type, mbm); result = rdev_set_tx_power(rdev, txp_wdev, type, mbm);
if (result) if (result)
goto bad_res; return result;
} }
if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] && if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
...@@ -2105,10 +2090,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) ...@@ -2105,10 +2090,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
u32 tx_ant, rx_ant; u32 tx_ant, rx_ant;
if ((!rdev->wiphy.available_antennas_tx && if ((!rdev->wiphy.available_antennas_tx &&
!rdev->wiphy.available_antennas_rx) || !rdev->wiphy.available_antennas_rx) ||
!rdev->ops->set_antenna) { !rdev->ops->set_antenna)
result = -EOPNOTSUPP; return -EOPNOTSUPP;
goto bad_res;
}
tx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX]); tx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX]);
rx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]); rx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]);
...@@ -2116,17 +2099,15 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) ...@@ -2116,17 +2099,15 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
/* reject antenna configurations which don't match the /* reject antenna configurations which don't match the
* available antenna masks, except for the "all" mask */ * available antenna masks, except for the "all" mask */
if ((~tx_ant && (tx_ant & ~rdev->wiphy.available_antennas_tx)) || if ((~tx_ant && (tx_ant & ~rdev->wiphy.available_antennas_tx)) ||
(~rx_ant && (rx_ant & ~rdev->wiphy.available_antennas_rx))) { (~rx_ant && (rx_ant & ~rdev->wiphy.available_antennas_rx)))
result = -EINVAL; return -EINVAL;
goto bad_res;
}
tx_ant = tx_ant & rdev->wiphy.available_antennas_tx; tx_ant = tx_ant & rdev->wiphy.available_antennas_tx;
rx_ant = rx_ant & rdev->wiphy.available_antennas_rx; rx_ant = rx_ant & rdev->wiphy.available_antennas_rx;
result = rdev_set_antenna(rdev, tx_ant, rx_ant); result = rdev_set_antenna(rdev, tx_ant, rx_ant);
if (result) if (result)
goto bad_res; return result;
} }
changed = 0; changed = 0;
...@@ -2134,30 +2115,27 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) ...@@ -2134,30 +2115,27 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) { if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) {
retry_short = nla_get_u8( retry_short = nla_get_u8(
info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]); info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]);
if (retry_short == 0) { if (retry_short == 0)
result = -EINVAL; return -EINVAL;
goto bad_res;
}
changed |= WIPHY_PARAM_RETRY_SHORT; changed |= WIPHY_PARAM_RETRY_SHORT;
} }
if (info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]) { if (info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]) {
retry_long = nla_get_u8( retry_long = nla_get_u8(
info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]); info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]);
if (retry_long == 0) { if (retry_long == 0)
result = -EINVAL; return -EINVAL;
goto bad_res;
}
changed |= WIPHY_PARAM_RETRY_LONG; changed |= WIPHY_PARAM_RETRY_LONG;
} }
if (info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]) { if (info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]) {
frag_threshold = nla_get_u32( frag_threshold = nla_get_u32(
info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]); info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]);
if (frag_threshold < 256) { if (frag_threshold < 256)
result = -EINVAL; return -EINVAL;
goto bad_res;
}
if (frag_threshold != (u32) -1) { if (frag_threshold != (u32) -1) {
/* /*
* Fragments (apart from the last one) are required to * Fragments (apart from the last one) are required to
...@@ -2187,10 +2165,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) ...@@ -2187,10 +2165,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
u32 old_frag_threshold, old_rts_threshold; u32 old_frag_threshold, old_rts_threshold;
u8 old_coverage_class; u8 old_coverage_class;
if (!rdev->ops->set_wiphy_params) { if (!rdev->ops->set_wiphy_params)
result = -EOPNOTSUPP; return -EOPNOTSUPP;
goto bad_res;
}
old_retry_short = rdev->wiphy.retry_short; old_retry_short = rdev->wiphy.retry_short;
old_retry_long = rdev->wiphy.retry_long; old_retry_long = rdev->wiphy.retry_long;
...@@ -2218,11 +2194,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) ...@@ -2218,11 +2194,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
rdev->wiphy.coverage_class = old_coverage_class; rdev->wiphy.coverage_class = old_coverage_class;
} }
} }
return 0;
bad_res:
if (netdev)
dev_put(netdev);
return result;
} }
static inline u64 wdev_id(struct wireless_dev *wdev) static inline u64 wdev_id(struct wireless_dev *wdev)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册