@@ -1839,6 +1839,7 @@ struct nl80211_dump_wiphy_state {
long start;
long split_start, band_start, chan_start, capa_start;
bool split;
+ bool large_message;
};
static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
@@ -2168,12 +2169,23 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
* helps ensure that newly added capabilities don't break
* older tools by overrunning their buffers.
*
+ * For unsolicited NEW_WIPHY notifications, it is assumed
+ * that the client can handle larger messages. Unsolicited
+ * NEW_WIPHY notifications were added relatively recently
+ * and it is not expected that older tools with limited
+ * buffers would utilize these messages anyway. E.g. even
+ * if the message is truncated, it would not have been
+ * used regardless.
+ *
* We still increment split_start so that in the split
* case we'll continue with more data in the next round,
- * but break unconditionally so unsplit data stops here.
+ * but break unless large_messages are requested, so
+ * legacy unsplit data stops here.
*/
state->split_start++;
- break;
+ if (state->split || !state->large_message)
+ break;
+ /* Fall through */
case 9:
if (rdev->wiphy.extended_capabilities &&
(nla_put(msg, NL80211_ATTR_EXT_CAPA,
@@ -2215,7 +2227,9 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
}
state->split_start++;
- break;
+ if (state->split)
+ break;
+ /* Fall through */
case 10:
if (nl80211_send_coalesce(msg, rdev))
goto nla_put_failure;
@@ -2231,7 +2245,9 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
goto nla_put_failure;
state->split_start++;
- break;
+ if (state->split)
+ break;
+ /* Fall through */
case 11:
if (rdev->wiphy.n_vendor_commands) {
const struct nl80211_vendor_cmd_info *info;
@@ -2267,7 +2283,9 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
nla_nest_end(msg, nested);
}
state->split_start++;
- break;
+ if (state->split)
+ break;
+ /* Fall through */
case 12:
if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH &&
nla_put_u8(msg, NL80211_ATTR_MAX_CSA_COUNTERS,
@@ -2309,7 +2327,9 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
}
state->split_start++;
- break;
+ if (state->split)
+ break;
+ /* Fall through */
case 13:
if (rdev->wiphy.num_iftype_ext_capab &&
rdev->wiphy.iftype_ext_capab) {
@@ -2377,13 +2397,17 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
}
state->split_start++;
- break;
+ if (state->split)
+ break;
+ /* Fall through */
case 14:
if (nl80211_send_pmsr_capa(rdev, msg))
goto nla_put_failure;
state->split_start++;
- break;
+ if (state->split)
+ break;
+ /* Fall through */
case 15:
if (rdev->wiphy.akm_suites &&
nla_put(msg, NL80211_ATTR_AKM_SUITES,
@@ -14687,12 +14711,19 @@ void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev,
enum nl80211_commands cmd)
{
struct sk_buff *msg;
+ size_t alloc_size;
struct nl80211_dump_wiphy_state state = {};
WARN_ON(cmd != NL80211_CMD_NEW_WIPHY &&
cmd != NL80211_CMD_DEL_WIPHY);
- msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (cmd == NL80211_CMD_NEW_WIPHY) {
+ state.large_message = true;
+ alloc_size = 8192UL;
+ } else
+ alloc_size = NLMSG_DEFAULT_SIZE;
+
+ msg = nlmsg_new(alloc_size, GFP_KERNEL);
if (!msg)
return;