nl80211.c 340 KB
Newer Older
1 2 3
/*
 * This is the new netlink-based wireless configuration interface.
 *
4
 * Copyright 2006-2010	Johannes Berg <johannes@sipsolutions.net>
5
 * Copyright 2013-2014  Intel Mobile Communications GmbH
6 7 8 9 10
 */

#include <linux/if.h>
#include <linux/module.h>
#include <linux/err.h>
11
#include <linux/slab.h>
12 13 14 15 16 17
#include <linux/list.h>
#include <linux/if_ether.h>
#include <linux/ieee80211.h>
#include <linux/nl80211.h>
#include <linux/rtnetlink.h>
#include <linux/netlink.h>
18
#include <linux/etherdevice.h>
19
#include <net/net_namespace.h>
20 21
#include <net/genetlink.h>
#include <net/cfg80211.h>
22
#include <net/sock.h>
23
#include <net/inet_connection_sock.h>
24 25
#include "core.h"
#include "nl80211.h"
26
#include "reg.h"
27
#include "rdev-ops.h"
28

29 30 31 32 33
static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
				   struct genl_info *info,
				   struct cfg80211_crypto_settings *settings,
				   int cipher_limit);

34
static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
35
			    struct genl_info *info);
36
static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
37 38
			      struct genl_info *info);

39 40
/* the netlink family */
static struct genl_family nl80211_fam = {
41 42 43 44
	.id = GENL_ID_GENERATE,		/* don't bother with a hardcoded ID */
	.name = NL80211_GENL_NAME,	/* have users key off the name instead */
	.hdrsize = 0,			/* no private header */
	.version = 1,			/* no particular meaning now */
45
	.maxattr = NL80211_ATTR_MAX,
46
	.netnsok = true,
47 48
	.pre_doit = nl80211_pre_doit,
	.post_doit = nl80211_post_doit,
49 50
};

51 52 53 54 55 56
/* multicast groups */
enum nl80211_multicast_groups {
	NL80211_MCGRP_CONFIG,
	NL80211_MCGRP_SCAN,
	NL80211_MCGRP_REGULATORY,
	NL80211_MCGRP_MLME,
57
	NL80211_MCGRP_VENDOR,
58 59 60 61
	NL80211_MCGRP_TESTMODE /* keep last - ifdef! */
};

static const struct genl_multicast_group nl80211_mcgrps[] = {
62 63 64 65 66
	[NL80211_MCGRP_CONFIG] = { .name = NL80211_MULTICAST_GROUP_CONFIG },
	[NL80211_MCGRP_SCAN] = { .name = NL80211_MULTICAST_GROUP_SCAN },
	[NL80211_MCGRP_REGULATORY] = { .name = NL80211_MULTICAST_GROUP_REG },
	[NL80211_MCGRP_MLME] = { .name = NL80211_MULTICAST_GROUP_MLME },
	[NL80211_MCGRP_VENDOR] = { .name = NL80211_MULTICAST_GROUP_VENDOR },
67
#ifdef CONFIG_NL80211_TESTMODE
68
	[NL80211_MCGRP_TESTMODE] = { .name = NL80211_MULTICAST_GROUP_TESTMODE }
69 70 71
#endif
};

72 73 74
/* returns ERR_PTR values */
static struct wireless_dev *
__cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
75
{
76 77 78 79 80 81 82
	struct cfg80211_registered_device *rdev;
	struct wireless_dev *result = NULL;
	bool have_ifidx = attrs[NL80211_ATTR_IFINDEX];
	bool have_wdev_id = attrs[NL80211_ATTR_WDEV];
	u64 wdev_id;
	int wiphy_idx = -1;
	int ifidx = -1;
83

84
	ASSERT_RTNL();
85

86 87
	if (!have_ifidx && !have_wdev_id)
		return ERR_PTR(-EINVAL);
88

89 90 91 92 93
	if (have_ifidx)
		ifidx = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
	if (have_wdev_id) {
		wdev_id = nla_get_u64(attrs[NL80211_ATTR_WDEV]);
		wiphy_idx = wdev_id >> 32;
94 95
	}

96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
	list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
		struct wireless_dev *wdev;

		if (wiphy_net(&rdev->wiphy) != netns)
			continue;

		if (have_wdev_id && rdev->wiphy_idx != wiphy_idx)
			continue;

		list_for_each_entry(wdev, &rdev->wdev_list, list) {
			if (have_ifidx && wdev->netdev &&
			    wdev->netdev->ifindex == ifidx) {
				result = wdev;
				break;
			}
			if (have_wdev_id && wdev->identifier == (u32)wdev_id) {
				result = wdev;
				break;
			}
		}

		if (result)
			break;
	}

	if (result)
		return result;
	return ERR_PTR(-ENODEV);
124 125
}

126
static struct cfg80211_registered_device *
127
__cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
128
{
129 130
	struct cfg80211_registered_device *rdev = NULL, *tmp;
	struct net_device *netdev;
131

132
	ASSERT_RTNL();
133

134
	if (!attrs[NL80211_ATTR_WIPHY] &&
135 136
	    !attrs[NL80211_ATTR_IFINDEX] &&
	    !attrs[NL80211_ATTR_WDEV])
137 138
		return ERR_PTR(-EINVAL);

139
	if (attrs[NL80211_ATTR_WIPHY])
140
		rdev = cfg80211_rdev_by_wiphy_idx(
141
				nla_get_u32(attrs[NL80211_ATTR_WIPHY]));
142

143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
	if (attrs[NL80211_ATTR_WDEV]) {
		u64 wdev_id = nla_get_u64(attrs[NL80211_ATTR_WDEV]);
		struct wireless_dev *wdev;
		bool found = false;

		tmp = cfg80211_rdev_by_wiphy_idx(wdev_id >> 32);
		if (tmp) {
			/* make sure wdev exists */
			list_for_each_entry(wdev, &tmp->wdev_list, list) {
				if (wdev->identifier != (u32)wdev_id)
					continue;
				found = true;
				break;
			}

			if (!found)
				tmp = NULL;

			if (rdev && tmp != rdev)
				return ERR_PTR(-EINVAL);
			rdev = tmp;
		}
	}

167 168
	if (attrs[NL80211_ATTR_IFINDEX]) {
		int ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
169
		netdev = __dev_get_by_index(netns, ifindex);
170 171
		if (netdev) {
			if (netdev->ieee80211_ptr)
172 173
				tmp = wiphy_to_rdev(
					netdev->ieee80211_ptr->wiphy);
174 175 176 177 178 179 180 181 182 183 184 185
			else
				tmp = NULL;

			/* not wireless device -- return error */
			if (!tmp)
				return ERR_PTR(-EINVAL);

			/* mismatch -- return error */
			if (rdev && tmp != rdev)
				return ERR_PTR(-EINVAL);

			rdev = tmp;
186 187 188
		}
	}

189 190
	if (!rdev)
		return ERR_PTR(-ENODEV);
191

192 193 194 195
	if (netns != wiphy_net(&rdev->wiphy))
		return ERR_PTR(-ENODEV);

	return rdev;
196 197 198 199 200 201 202 203 204 205
}

/*
 * This function returns a pointer to the driver
 * that the genl_info item that is passed refers to.
 *
 * The result of this can be a PTR_ERR and hence must
 * be checked with IS_ERR() for errors.
 */
static struct cfg80211_registered_device *
206
cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info)
207
{
208
	return __cfg80211_rdev_from_attrs(netns, info->attrs);
209 210
}

211
/* policy for the attributes */
212
static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
213 214
	[NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
	[NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
215
				      .len = 20-1 },
216
	[NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED },
217

218
	[NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 },
Sujith's avatar
Sujith committed
219
	[NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 },
220 221 222 223
	[NL80211_ATTR_CHANNEL_WIDTH] = { .type = NLA_U32 },
	[NL80211_ATTR_CENTER_FREQ1] = { .type = NLA_U32 },
	[NL80211_ATTR_CENTER_FREQ2] = { .type = NLA_U32 },

224 225 226 227
	[NL80211_ATTR_WIPHY_RETRY_SHORT] = { .type = NLA_U8 },
	[NL80211_ATTR_WIPHY_RETRY_LONG] = { .type = NLA_U8 },
	[NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 },
	[NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 },
228
	[NL80211_ATTR_WIPHY_COVERAGE_CLASS] = { .type = NLA_U8 },
229
	[NL80211_ATTR_WIPHY_DYN_ACK] = { .type = NLA_FLAG },
230 231 232 233

	[NL80211_ATTR_IFTYPE] = { .type = NLA_U32 },
	[NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
	[NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
234

235 236
	[NL80211_ATTR_MAC] = { .len = ETH_ALEN },
	[NL80211_ATTR_PREV_BSSID] = { .len = ETH_ALEN },
237

238
	[NL80211_ATTR_KEY] = { .type = NLA_NESTED, },
239 240 241 242 243
	[NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY,
				    .len = WLAN_MAX_KEY_LEN },
	[NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 },
	[NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
	[NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },
244
	[NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },
245
	[NL80211_ATTR_KEY_TYPE] = { .type = NLA_U32 },
246 247 248 249 250 251 252

	[NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },
	[NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 },
	[NL80211_ATTR_BEACON_HEAD] = { .type = NLA_BINARY,
				       .len = IEEE80211_MAX_DATA_LEN },
	[NL80211_ATTR_BEACON_TAIL] = { .type = NLA_BINARY,
				       .len = IEEE80211_MAX_DATA_LEN },
253 254 255 256 257
	[NL80211_ATTR_STA_AID] = { .type = NLA_U16 },
	[NL80211_ATTR_STA_FLAGS] = { .type = NLA_NESTED },
	[NL80211_ATTR_STA_LISTEN_INTERVAL] = { .type = NLA_U16 },
	[NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY,
					       .len = NL80211_MAX_SUPP_RATES },
258
	[NL80211_ATTR_STA_PLINK_ACTION] = { .type = NLA_U8 },
259
	[NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
Johannes Berg's avatar
Johannes Berg committed
260
	[NL80211_ATTR_MNTR_FLAGS] = { /* NLA_NESTED can't be empty */ },
261
	[NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY,
262
				   .len = IEEE80211_MAX_MESH_ID_LEN },
263
	[NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_U32 },
264

265 266 267
	[NL80211_ATTR_REG_ALPHA2] = { .type = NLA_STRING, .len = 2 },
	[NL80211_ATTR_REG_RULES] = { .type = NLA_NESTED },

268 269 270
	[NL80211_ATTR_BSS_CTS_PROT] = { .type = NLA_U8 },
	[NL80211_ATTR_BSS_SHORT_PREAMBLE] = { .type = NLA_U8 },
	[NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 },
271 272
	[NL80211_ATTR_BSS_BASIC_RATES] = { .type = NLA_BINARY,
					   .len = NL80211_MAX_SUPP_RATES },
273
	[NL80211_ATTR_BSS_HT_OPMODE] = { .type = NLA_U16 },
274

275
	[NL80211_ATTR_MESH_CONFIG] = { .type = NLA_NESTED },
276
	[NL80211_ATTR_SUPPORT_MESH_AUTH] = { .type = NLA_FLAG },
277

278
	[NL80211_ATTR_HT_CAPABILITY] = { .len = NL80211_HT_CAPABILITY_LEN },
279 280 281 282

	[NL80211_ATTR_MGMT_SUBTYPE] = { .type = NLA_U8 },
	[NL80211_ATTR_IE] = { .type = NLA_BINARY,
			      .len = IEEE80211_MAX_DATA_LEN },
283 284
	[NL80211_ATTR_SCAN_FREQUENCIES] = { .type = NLA_NESTED },
	[NL80211_ATTR_SCAN_SSIDS] = { .type = NLA_NESTED },
285 286 287 288 289

	[NL80211_ATTR_SSID] = { .type = NLA_BINARY,
				.len = IEEE80211_MAX_SSID_LEN },
	[NL80211_ATTR_AUTH_TYPE] = { .type = NLA_U32 },
	[NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 },
290
	[NL80211_ATTR_FREQ_FIXED] = { .type = NLA_FLAG },
291
	[NL80211_ATTR_TIMED_OUT] = { .type = NLA_FLAG },
292
	[NL80211_ATTR_USE_MFP] = { .type = NLA_U32 },
293 294 295
	[NL80211_ATTR_STA_FLAGS2] = {
		.len = sizeof(struct nl80211_sta_flag_update),
	},
296
	[NL80211_ATTR_CONTROL_PORT] = { .type = NLA_FLAG },
297 298
	[NL80211_ATTR_CONTROL_PORT_ETHERTYPE] = { .type = NLA_U16 },
	[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT] = { .type = NLA_FLAG },
299 300 301
	[NL80211_ATTR_PRIVACY] = { .type = NLA_FLAG },
	[NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 },
	[NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },
302
	[NL80211_ATTR_PID] = { .type = NLA_U32 },
303
	[NL80211_ATTR_4ADDR] = { .type = NLA_U8 },
304 305
	[NL80211_ATTR_PMKID] = { .type = NLA_BINARY,
				 .len = WLAN_PMKID_LEN },
306 307
	[NL80211_ATTR_DURATION] = { .type = NLA_U32 },
	[NL80211_ATTR_COOKIE] = { .type = NLA_U64 },
308
	[NL80211_ATTR_TX_RATES] = { .type = NLA_NESTED },
309 310 311
	[NL80211_ATTR_FRAME] = { .type = NLA_BINARY,
				 .len = IEEE80211_MAX_DATA_LEN },
	[NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, },
312
	[NL80211_ATTR_PS_STATE] = { .type = NLA_U32 },
313
	[NL80211_ATTR_CQM] = { .type = NLA_NESTED, },
314
	[NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG },
315
	[NL80211_ATTR_AP_ISOLATE] = { .type = NLA_U8 },
316 317
	[NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 },
	[NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 },
318
	[NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 },
319 320
	[NL80211_ATTR_WIPHY_ANTENNA_TX] = { .type = NLA_U32 },
	[NL80211_ATTR_WIPHY_ANTENNA_RX] = { .type = NLA_U32 },
321
	[NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 },
322
	[NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG },
323
	[NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
324
	[NL80211_ATTR_WOWLAN_TRIGGERS] = { .type = NLA_NESTED },
325
	[NL80211_ATTR_STA_PLINK_STATE] = { .type = NLA_U8 },
326
	[NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 },
327
	[NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED },
328
	[NL80211_ATTR_SCAN_SUPP_RATES] = { .type = NLA_NESTED },
329
	[NL80211_ATTR_HIDDEN_SSID] = { .type = NLA_U32 },
330 331 332 333
	[NL80211_ATTR_IE_PROBE_RESP] = { .type = NLA_BINARY,
					 .len = IEEE80211_MAX_DATA_LEN },
	[NL80211_ATTR_IE_ASSOC_RESP] = { .type = NLA_BINARY,
					 .len = IEEE80211_MAX_DATA_LEN },
334
	[NL80211_ATTR_ROAM_SUPPORT] = { .type = NLA_FLAG },
335
	[NL80211_ATTR_SCHED_SCAN_MATCH] = { .type = NLA_NESTED },
336
	[NL80211_ATTR_TX_NO_CCK_RATE] = { .type = NLA_FLAG },
337 338 339 340 341
	[NL80211_ATTR_TDLS_ACTION] = { .type = NLA_U8 },
	[NL80211_ATTR_TDLS_DIALOG_TOKEN] = { .type = NLA_U8 },
	[NL80211_ATTR_TDLS_OPERATION] = { .type = NLA_U8 },
	[NL80211_ATTR_TDLS_SUPPORT] = { .type = NLA_FLAG },
	[NL80211_ATTR_TDLS_EXTERNAL_SETUP] = { .type = NLA_FLAG },
342
	[NL80211_ATTR_TDLS_INITIATOR] = { .type = NLA_FLAG },
343
	[NL80211_ATTR_DONT_WAIT_FOR_ACK] = { .type = NLA_FLAG },
344 345
	[NL80211_ATTR_PROBE_RESP] = { .type = NLA_BINARY,
				      .len = IEEE80211_MAX_DATA_LEN },
346
	[NL80211_ATTR_DFS_REGION] = { .type = NLA_U8 },
347 348 349 350
	[NL80211_ATTR_DISABLE_HT] = { .type = NLA_FLAG },
	[NL80211_ATTR_HT_CAPABILITY_MASK] = {
		.len = NL80211_HT_CAPABILITY_LEN
	},
351
	[NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 },
352
	[NL80211_ATTR_INACTIVITY_TIMEOUT] = { .type = NLA_U16 },
353
	[NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 },
354
	[NL80211_ATTR_WDEV] = { .type = NLA_U64 },
355
	[NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 },
356
	[NL80211_ATTR_SAE_DATA] = { .type = NLA_BINARY, },
357
	[NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN },
358
	[NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },
359 360
	[NL80211_ATTR_P2P_CTWINDOW] = { .type = NLA_U8 },
	[NL80211_ATTR_P2P_OPPPS] = { .type = NLA_U8 },
361 362
	[NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 },
	[NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED },
363 364
	[NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 },
	[NL80211_ATTR_STA_EXT_CAPABILITY] = { .type = NLA_BINARY, },
365
	[NL80211_ATTR_SPLIT_WIPHY_DUMP] = { .type = NLA_FLAG, },
366 367 368 369
	[NL80211_ATTR_DISABLE_VHT] = { .type = NLA_FLAG },
	[NL80211_ATTR_VHT_CAPABILITY_MASK] = {
		.len = NL80211_VHT_CAPABILITY_LEN,
	},
370 371 372
	[NL80211_ATTR_MDID] = { .type = NLA_U16 },
	[NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY,
				  .len = IEEE80211_MAX_DATA_LEN },
373
	[NL80211_ATTR_PEER_AID] = { .type = NLA_U16 },
374 375 376
	[NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 },
	[NL80211_ATTR_CH_SWITCH_BLOCK_TX] = { .type = NLA_FLAG },
	[NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED },
377 378
	[NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_BINARY },
	[NL80211_ATTR_CSA_C_OFF_PRESP] = { .type = NLA_BINARY },
379 380
	[NL80211_ATTR_STA_SUPPORTED_CHANNELS] = { .type = NLA_BINARY },
	[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY },
381
	[NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG },
382
	[NL80211_ATTR_OPMODE_NOTIF] = { .type = NLA_U8 },
383 384 385
	[NL80211_ATTR_VENDOR_ID] = { .type = NLA_U32 },
	[NL80211_ATTR_VENDOR_SUBCMD] = { .type = NLA_U32 },
	[NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY },
386 387
	[NL80211_ATTR_QOS_MAP] = { .type = NLA_BINARY,
				   .len = IEEE80211_QOS_MAP_LEN_MAX },
388 389
	[NL80211_ATTR_MAC_HINT] = { .len = ETH_ALEN },
	[NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 },
390
	[NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 },
391
	[NL80211_ATTR_SOCKET_OWNER] = { .type = NLA_FLAG },
392
	[NL80211_ATTR_CSA_C_OFFSETS_TX] = { .type = NLA_BINARY },
393
	[NL80211_ATTR_USE_RRM] = { .type = NLA_FLAG },
394 395 396
	[NL80211_ATTR_TSID] = { .type = NLA_U8 },
	[NL80211_ATTR_USER_PRIO] = { .type = NLA_U8 },
	[NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 },
397
	[NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 },
398
	[NL80211_ATTR_MAC_MASK] = { .len = ETH_ALEN },
399
	[NL80211_ATTR_WIPHY_SELF_MANAGED_REG] = { .type = NLA_FLAG },
400
	[NL80211_ATTR_NETNS_FD] = { .type = NLA_U32 },
401
	[NL80211_ATTR_SCHED_SCAN_DELAY] = { .type = NLA_U32 },
402
	[NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG },
403 404
};

405
/* policy for the key attributes */
Alexey Dobriyan's avatar
Alexey Dobriyan committed
406
static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = {
407
	[NL80211_KEY_DATA] = { .type = NLA_BINARY, .len = WLAN_MAX_KEY_LEN },
408 409
	[NL80211_KEY_IDX] = { .type = NLA_U8 },
	[NL80211_KEY_CIPHER] = { .type = NLA_U32 },
410
	[NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },
411 412
	[NL80211_KEY_DEFAULT] = { .type = NLA_FLAG },
	[NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG },
413
	[NL80211_KEY_TYPE] = { .type = NLA_U32 },
414 415 416 417 418 419 420 421
	[NL80211_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
};

/* policy for the key default flags */
static const struct nla_policy
nl80211_key_default_policy[NUM_NL80211_KEY_DEFAULT_TYPES] = {
	[NL80211_KEY_DEFAULT_TYPE_UNICAST] = { .type = NLA_FLAG },
	[NL80211_KEY_DEFAULT_TYPE_MULTICAST] = { .type = NLA_FLAG },
422 423
};

424 425 426 427 428 429 430
/* policy for WoWLAN attributes */
static const struct nla_policy
nl80211_wowlan_policy[NUM_NL80211_WOWLAN_TRIG] = {
	[NL80211_WOWLAN_TRIG_ANY] = { .type = NLA_FLAG },
	[NL80211_WOWLAN_TRIG_DISCONNECT] = { .type = NLA_FLAG },
	[NL80211_WOWLAN_TRIG_MAGIC_PKT] = { .type = NLA_FLAG },
	[NL80211_WOWLAN_TRIG_PKT_PATTERN] = { .type = NLA_NESTED },
431 432 433 434
	[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE] = { .type = NLA_FLAG },
	[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST] = { .type = NLA_FLAG },
	[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE] = { .type = NLA_FLAG },
	[NL80211_WOWLAN_TRIG_RFKILL_RELEASE] = { .type = NLA_FLAG },
435
	[NL80211_WOWLAN_TRIG_TCP_CONNECTION] = { .type = NLA_NESTED },
436
	[NL80211_WOWLAN_TRIG_NET_DETECT] = { .type = NLA_NESTED },
437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455
};

static const struct nla_policy
nl80211_wowlan_tcp_policy[NUM_NL80211_WOWLAN_TCP] = {
	[NL80211_WOWLAN_TCP_SRC_IPV4] = { .type = NLA_U32 },
	[NL80211_WOWLAN_TCP_DST_IPV4] = { .type = NLA_U32 },
	[NL80211_WOWLAN_TCP_DST_MAC] = { .len = ETH_ALEN },
	[NL80211_WOWLAN_TCP_SRC_PORT] = { .type = NLA_U16 },
	[NL80211_WOWLAN_TCP_DST_PORT] = { .type = NLA_U16 },
	[NL80211_WOWLAN_TCP_DATA_PAYLOAD] = { .len = 1 },
	[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ] = {
		.len = sizeof(struct nl80211_wowlan_tcp_data_seq)
	},
	[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN] = {
		.len = sizeof(struct nl80211_wowlan_tcp_data_token)
	},
	[NL80211_WOWLAN_TCP_DATA_INTERVAL] = { .type = NLA_U32 },
	[NL80211_WOWLAN_TCP_WAKE_PAYLOAD] = { .len = 1 },
	[NL80211_WOWLAN_TCP_WAKE_MASK] = { .len = 1 },
456 457
};

458 459 460 461 462 463 464 465
/* policy for coalesce rule attributes */
static const struct nla_policy
nl80211_coalesce_policy[NUM_NL80211_ATTR_COALESCE_RULE] = {
	[NL80211_ATTR_COALESCE_RULE_DELAY] = { .type = NLA_U32 },
	[NL80211_ATTR_COALESCE_RULE_CONDITION] = { .type = NLA_U32 },
	[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN] = { .type = NLA_NESTED },
};

466 467 468 469 470 471 472 473
/* policy for GTK rekey offload attributes */
static const struct nla_policy
nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = {
	[NL80211_REKEY_DATA_KEK] = { .len = NL80211_KEK_LEN },
	[NL80211_REKEY_DATA_KCK] = { .len = NL80211_KCK_LEN },
	[NL80211_REKEY_DATA_REPLAY_CTR] = { .len = NL80211_REPLAY_CTR_LEN },
};

474 475
static const struct nla_policy
nl80211_match_policy[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1] = {
476
	[NL80211_SCHED_SCAN_MATCH_ATTR_SSID] = { .type = NLA_BINARY,
477
						 .len = IEEE80211_MAX_SSID_LEN },
478
	[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI] = { .type = NLA_U32 },
479 480
};

481 482 483 484
static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
				     struct netlink_callback *cb,
				     struct cfg80211_registered_device **rdev,
				     struct wireless_dev **wdev)
485
{
486
	int err;
487

488
	rtnl_lock();
489

490 491 492 493 494 495
	if (!cb->args[0]) {
		err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
				  nl80211_fam.attrbuf, nl80211_fam.maxattr,
				  nl80211_policy);
		if (err)
			goto out_unlock;
496

497 498 499 500 501 502
		*wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk),
						   nl80211_fam.attrbuf);
		if (IS_ERR(*wdev)) {
			err = PTR_ERR(*wdev);
			goto out_unlock;
		}
503
		*rdev = wiphy_to_rdev((*wdev)->wiphy);
504 505
		/* 0 is the first index - add 1 to parse only once */
		cb->args[0] = (*rdev)->wiphy_idx + 1;
506 507
		cb->args[1] = (*wdev)->identifier;
	} else {
508 509
		/* subtract the 1 again here */
		struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1);
510
		struct wireless_dev *tmp;
511

512 513 514 515
		if (!wiphy) {
			err = -ENODEV;
			goto out_unlock;
		}
516
		*rdev = wiphy_to_rdev(wiphy);
517
		*wdev = NULL;
518

519 520 521 522 523 524
		list_for_each_entry(tmp, &(*rdev)->wdev_list, list) {
			if (tmp->identifier == cb->args[1]) {
				*wdev = tmp;
				break;
			}
		}
525

526 527 528 529
		if (!*wdev) {
			err = -ENODEV;
			goto out_unlock;
		}
530 531 532
	}

	return 0;
533
 out_unlock:
534 535 536 537
	rtnl_unlock();
	return err;
}

538
static void nl80211_finish_wdev_dump(struct cfg80211_registered_device *rdev)
539 540 541 542
{
	rtnl_unlock();
}

543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572
/* IE validation */
static bool is_valid_ie_attr(const struct nlattr *attr)
{
	const u8 *pos;
	int len;

	if (!attr)
		return true;

	pos = nla_data(attr);
	len = nla_len(attr);

	while (len) {
		u8 elemlen;

		if (len < 2)
			return false;
		len -= 2;

		elemlen = pos[1];
		if (elemlen > len)
			return false;

		len -= elemlen;
		pos += 2 + elemlen;
	}

	return true;
}

573
/* message building helper */
574
static inline void *nl80211hdr_put(struct sk_buff *skb, u32 portid, u32 seq,
575 576 577
				   int flags, u8 cmd)
{
	/* since there is no private header just add the generic one */
578
	return genlmsg_put(skb, portid, seq, &nl80211_fam, flags, cmd);
579 580
}

581
static int nl80211_msg_put_channel(struct sk_buff *msg,
582 583
				   struct ieee80211_channel *chan,
				   bool large)
584
{
585 586 587 588 589 590 591
	/* Some channels must be completely excluded from the
	 * list to protect old user-space tools from breaking
	 */
	if (!large && chan->flags &
	    (IEEE80211_CHAN_NO_10MHZ | IEEE80211_CHAN_NO_20MHZ))
		return 0;

592 593 594
	if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_FREQ,
			chan->center_freq))
		goto nla_put_failure;
595

596 597 598
	if ((chan->flags & IEEE80211_CHAN_DISABLED) &&
	    nla_put_flag(msg, NL80211_FREQUENCY_ATTR_DISABLED))
		goto nla_put_failure;
599 600 601 602 603 604
	if (chan->flags & IEEE80211_CHAN_NO_IR) {
		if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IR))
			goto nla_put_failure;
		if (nla_put_flag(msg, __NL80211_FREQUENCY_ATTR_NO_IBSS))
			goto nla_put_failure;
	}
605 606 607 608 609 610 611 612 613 614 615 616 617 618
	if (chan->flags & IEEE80211_CHAN_RADAR) {
		if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))
			goto nla_put_failure;
		if (large) {
			u32 time;

			time = elapsed_jiffies_msecs(chan->dfs_state_entered);

			if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_STATE,
					chan->dfs_state))
				goto nla_put_failure;
			if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME,
					time))
				goto nla_put_failure;
619 620 621 622
			if (nla_put_u32(msg,
					NL80211_FREQUENCY_ATTR_DFS_CAC_TIME,
					chan->dfs_cac_ms))
				goto nla_put_failure;
623 624
		}
	}
625

626 627 628 629 630 631 632 633 634 635 636 637 638
	if (large) {
		if ((chan->flags & IEEE80211_CHAN_NO_HT40MINUS) &&
		    nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_MINUS))
			goto nla_put_failure;
		if ((chan->flags & IEEE80211_CHAN_NO_HT40PLUS) &&
		    nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_PLUS))
			goto nla_put_failure;
		if ((chan->flags & IEEE80211_CHAN_NO_80MHZ) &&
		    nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_80MHZ))
			goto nla_put_failure;
		if ((chan->flags & IEEE80211_CHAN_NO_160MHZ) &&
		    nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_160MHZ))
			goto nla_put_failure;
639 640 641
		if ((chan->flags & IEEE80211_CHAN_INDOOR_ONLY) &&
		    nla_put_flag(msg, NL80211_FREQUENCY_ATTR_INDOOR_ONLY))
			goto nla_put_failure;
642 643
		if ((chan->flags & IEEE80211_CHAN_IR_CONCURRENT) &&
		    nla_put_flag(msg, NL80211_FREQUENCY_ATTR_IR_CONCURRENT))
644
			goto nla_put_failure;
645 646 647 648 649 650
		if ((chan->flags & IEEE80211_CHAN_NO_20MHZ) &&
		    nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_20MHZ))
			goto nla_put_failure;
		if ((chan->flags & IEEE80211_CHAN_NO_10MHZ) &&
		    nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_10MHZ))
			goto nla_put_failure;
651 652
	}

653 654 655
	if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
			DBM_TO_MBM(chan->max_power)))
		goto nla_put_failure;
656 657 658 659 660 661 662

	return 0;

 nla_put_failure:
	return -ENOBUFS;
}

663 664
/* netlink command implementations */

665 666 667
struct key_parse {
	struct key_params p;
	int idx;
668
	int type;
669
	bool def, defmgmt;
670
	bool def_uni, def_multi;
671 672 673 674 675 676 677 678 679 680 681 682 683
};

static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k)
{
	struct nlattr *tb[NL80211_KEY_MAX + 1];
	int err = nla_parse_nested(tb, NL80211_KEY_MAX, key,
				   nl80211_key_policy);
	if (err)
		return err;

	k->def = !!tb[NL80211_KEY_DEFAULT];
	k->defmgmt = !!tb[NL80211_KEY_DEFAULT_MGMT];

684 685 686 687 688 689 690
	if (k->def) {
		k->def_uni = true;
		k->def_multi = true;
	}
	if (k->defmgmt)
		k->def_multi = true;

691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706
	if (tb[NL80211_KEY_IDX])
		k->idx = nla_get_u8(tb[NL80211_KEY_IDX]);

	if (tb[NL80211_KEY_DATA]) {
		k->p.key = nla_data(tb[NL80211_KEY_DATA]);
		k->p.key_len = nla_len(tb[NL80211_KEY_DATA]);
	}

	if (tb[NL80211_KEY_SEQ]) {
		k->p.seq = nla_data(tb[NL80211_KEY_SEQ]);
		k->p.seq_len = nla_len(tb[NL80211_KEY_SEQ]);
	}

	if (tb[NL80211_KEY_CIPHER])
		k->p.cipher = nla_get_u32(tb[NL80211_KEY_CIPHER]);

707 708 709 710 711 712
	if (tb[NL80211_KEY_TYPE]) {
		k->type = nla_get_u32(tb[NL80211_KEY_TYPE]);
		if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES)
			return -EINVAL;
	}

713 714
	if (tb[NL80211_KEY_DEFAULT_TYPES]) {
		struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
715 716 717
		err = nla_parse_nested(kdt, NUM_NL80211_KEY_DEFAULT_TYPES - 1,
				       tb[NL80211_KEY_DEFAULT_TYPES],
				       nl80211_key_default_policy);
718 719 720 721 722 723 724
		if (err)
			return err;

		k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST];
		k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST];
	}

725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748
	return 0;
}

static int nl80211_parse_key_old(struct genl_info *info, struct key_parse *k)
{
	if (info->attrs[NL80211_ATTR_KEY_DATA]) {
		k->p.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]);
		k->p.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]);
	}

	if (info->attrs[NL80211_ATTR_KEY_SEQ]) {
		k->p.seq = nla_data(info->attrs[NL80211_ATTR_KEY_SEQ]);
		k->p.seq_len = nla_len(info->attrs[NL80211_ATTR_KEY_SEQ]);
	}

	if (info->attrs[NL80211_ATTR_KEY_IDX])
		k->idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);

	if (info->attrs[NL80211_ATTR_KEY_CIPHER])
		k->p.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]);

	k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT];
	k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT];

749 750 751 752 753 754 755
	if (k->def) {
		k->def_uni = true;
		k->def_multi = true;
	}
	if (k->defmgmt)
		k->def_multi = true;

756 757 758 759 760 761
	if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
		k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
		if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES)
			return -EINVAL;
	}

762 763 764 765 766 767 768 769 770 771 772 773 774
	if (info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES]) {
		struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
		int err = nla_parse_nested(
				kdt, NUM_NL80211_KEY_DEFAULT_TYPES - 1,
				info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES],
				nl80211_key_default_policy);
		if (err)
			return err;

		k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST];
		k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST];
	}

775 776 777 778 779 780 781 782 783
	return 0;
}

static int nl80211_parse_key(struct genl_info *info, struct key_parse *k)
{
	int err;

	memset(k, 0, sizeof(*k));
	k->idx = -1;
784
	k->type = -1;
785 786 787 788 789 790 791 792 793 794 795 796

	if (info->attrs[NL80211_ATTR_KEY])
		err = nl80211_parse_key_new(info->attrs[NL80211_ATTR_KEY], k);
	else
		err = nl80211_parse_key_old(info, k);

	if (err)
		return err;

	if (k->def && k->defmgmt)
		return -EINVAL;

797 798 799 800 801
	if (k->defmgmt) {
		if (k->def_uni || !k->def_multi)
			return -EINVAL;
	}

802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817
	if (k->idx != -1) {
		if (k->defmgmt) {
			if (k->idx < 4 || k->idx > 5)
				return -EINVAL;
		} else if (k->def) {
			if (k->idx < 0 || k->idx > 3)
				return -EINVAL;
		} else {
			if (k->idx < 0 || k->idx > 5)
				return -EINVAL;
		}
	}

	return 0;
}

818 819
static struct cfg80211_cached_keys *
nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
820
		       struct nlattr *keys, bool *no_ht)
821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850
{
	struct key_parse parse;
	struct nlattr *key;
	struct cfg80211_cached_keys *result;
	int rem, err, def = 0;

	result = kzalloc(sizeof(*result), GFP_KERNEL);
	if (!result)
		return ERR_PTR(-ENOMEM);

	result->def = -1;
	result->defmgmt = -1;

	nla_for_each_nested(key, keys, rem) {
		memset(&parse, 0, sizeof(parse));
		parse.idx = -1;

		err = nl80211_parse_key_new(key, &parse);
		if (err)
			goto error;
		err = -EINVAL;
		if (!parse.p.key)
			goto error;
		if (parse.idx < 0 || parse.idx > 4)
			goto error;
		if (parse.def) {
			if (def)
				goto error;
			def = 1;
			result->def = parse.idx;
851 852
			if (!parse.def_uni || !parse.def_multi)
				goto error;
853 854 855
		} else if (parse.defmgmt)
			goto error;
		err = cfg80211_validate_key_settings(rdev, &parse.p,
856
						     parse.idx, false, NULL);
857 858 859 860 861 862
		if (err)
			goto error;
		result->params[parse.idx].cipher = parse.p.cipher;
		result->params[parse.idx].key_len = parse.p.key_len;
		result->params[parse.idx].key = result->data[parse.idx];
		memcpy(result->data[parse.idx], parse.p.key, parse.p.key_len);
863 864 865 866 867 868

		if (parse.p.cipher == WLAN_CIPHER_SUITE_WEP40 ||
		    parse.p.cipher == WLAN_CIPHER_SUITE_WEP104) {
			if (no_ht)
				*no_ht = true;
		}
869 870 871 872 873 874 875 876 877 878 879 880 881 882 883
	}

	return result;
 error:
	kfree(result);
	return ERR_PTR(err);
}

static int nl80211_key_allowed(struct wireless_dev *wdev)
{
	ASSERT_WDEV_LOCK(wdev);

	switch (wdev->iftype) {
	case NL80211_IFTYPE_AP:
	case NL80211_IFTYPE_AP_VLAN:
884
	case NL80211_IFTYPE_P2P_GO:
885
	case NL80211_IFTYPE_MESH_POINT:
886 887 888
		break;
	case NL80211_IFTYPE_ADHOC:
	case NL80211_IFTYPE_STATION:
889
	case NL80211_IFTYPE_P2P_CLIENT:
890
		if (!wdev->current_bss)
891 892
			return -ENOLINK;
		break;
893
	case NL80211_IFTYPE_UNSPECIFIED:
894
	case NL80211_IFTYPE_OCB:
895 896 897 898
	case NL80211_IFTYPE_MONITOR:
	case NL80211_IFTYPE_P2P_DEVICE:
	case NL80211_IFTYPE_WDS:
	case NUM_NL80211_IFTYPES:
899 900 901 902 903 904
		return -EINVAL;
	}

	return 0;
}

905 906 907 908 909 910 911 912 913 914 915 916 917
static struct ieee80211_channel *nl80211_get_valid_chan(struct wiphy *wiphy,
							struct nlattr *tb)
{
	struct ieee80211_channel *chan;

	if (tb == NULL)
		return NULL;
	chan = ieee80211_get_channel(wiphy, nla_get_u32(tb));
	if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
		return NULL;
	return chan;
}

918 919 920 921 922 923 924 925 926 927
static int nl80211_put_iftypes(struct sk_buff *msg, u32 attr, u16 ifmodes)
{
	struct nlattr *nl_modes = nla_nest_start(msg, attr);
	int i;

	if (!nl_modes)
		goto nla_put_failure;

	i = 0;
	while (ifmodes) {
928 929
		if ((ifmodes & 1) && nla_put_flag(msg, i))
			goto nla_put_failure;
930 931 932 933 934 935 936 937 938 939 940 941
		ifmodes >>= 1;
		i++;
	}

	nla_nest_end(msg, nl_modes);
	return 0;

nla_put_failure:
	return -ENOBUFS;
}

static int nl80211_put_iface_combinations(struct wiphy *wiphy,
942 943
					  struct sk_buff *msg,
					  bool large)
944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972
{
	struct nlattr *nl_combis;
	int i, j;

	nl_combis = nla_nest_start(msg,
				NL80211_ATTR_INTERFACE_COMBINATIONS);
	if (!nl_combis)
		goto nla_put_failure;

	for (i = 0; i < wiphy->n_iface_combinations; i++) {
		const struct ieee80211_iface_combination *c;
		struct nlattr *nl_combi, *nl_limits;

		c = &wiphy->iface_combinations[i];

		nl_combi = nla_nest_start(msg, i + 1);
		if (!nl_combi)
			goto nla_put_failure;

		nl_limits = nla_nest_start(msg, NL80211_IFACE_COMB_LIMITS);
		if (!nl_limits)
			goto nla_put_failure;

		for (j = 0; j < c->n_limits; j++) {
			struct nlattr *nl_limit;

			nl_limit = nla_nest_start(msg, j + 1);
			if (!nl_limit)
				goto nla_put_failure;
973 974 975
			if (nla_put_u32(msg, NL80211_IFACE_LIMIT_MAX,
					c->limits[j].max))
				goto nla_put_failure;
976 977 978 979 980 981 982 983
			if (nl80211_put_iftypes(msg, NL80211_IFACE_LIMIT_TYPES,
						c->limits[j].types))
				goto nla_put_failure;
			nla_nest_end(msg, nl_limit);
		}

		nla_nest_end(msg, nl_limits);

984 985 986 987 988 989 990 991
		if (c->beacon_int_infra_match &&
		    nla_put_flag(msg, NL80211_IFACE_COMB_STA_AP_BI_MATCH))
			goto nla_put_failure;
		if (nla_put_u32(msg, NL80211_IFACE_COMB_NUM_CHANNELS,
				c->num_different_channels) ||
		    nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM,
				c->max_interfaces))
			goto nla_put_failure;
992
		if (large &&
993 994 995 996
		    (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
				c->radar_detect_widths) ||
		     nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
				c->radar_detect_regions)))
997
			goto nla_put_failure;
998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008

		nla_nest_end(msg, nl_combi);
	}

	nla_nest_end(msg, nl_combis);

	return 0;
nla_put_failure:
	return -ENOBUFS;
}

1009
#ifdef CONFIG_PM
1010 1011 1012
static int nl80211_send_wowlan_tcp_caps(struct cfg80211_registered_device *rdev,
					struct sk_buff *msg)
{
1013
	const struct wiphy_wowlan_tcp_support *tcp = rdev->wiphy.wowlan->tcp;
1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049
	struct nlattr *nl_tcp;

	if (!tcp)
		return 0;

	nl_tcp = nla_nest_start(msg, NL80211_WOWLAN_TRIG_TCP_CONNECTION);
	if (!nl_tcp)
		return -ENOBUFS;

	if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
			tcp->data_payload_max))
		return -ENOBUFS;

	if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
			tcp->data_payload_max))
		return -ENOBUFS;

	if (tcp->seq && nla_put_flag(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ))
		return -ENOBUFS;

	if (tcp->tok && nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN,
				sizeof(*tcp->tok), tcp->tok))
		return -ENOBUFS;

	if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL,
			tcp->data_interval_max))
		return -ENOBUFS;

	if (nla_put_u32(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD,
			tcp->wake_payload_max))
		return -ENOBUFS;

	nla_nest_end(msg, nl_tcp);
	return 0;
}

1050
static int nl80211_send_wowlan(struct sk_buff *msg,
1051
			       struct cfg80211_registered_device *rdev,
1052
			       bool large)
1053
{
1054
	struct nlattr *nl_wowlan;
1055

1056
	if (!rdev->wiphy.wowlan)
1057
		return 0;
1058

1059 1060 1061
	nl_wowlan = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED);
	if (!nl_wowlan)
		return -ENOBUFS;
1062

1063
	if (((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_ANY) &&
1064
	     nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) ||
1065
	    ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_DISCONNECT) &&
1066
	     nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) ||
1067
	    ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_MAGIC_PKT) &&
1068
	     nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) ||
1069
	    ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY) &&
1070
	     nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED)) ||
1071
	    ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) &&
1072
	     nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) ||
1073
	    ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ) &&
1074
	     nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) ||
1075
	    ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_4WAY_HANDSHAKE) &&
1076
	     nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) ||
1077
	    ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_RFKILL_RELEASE) &&
1078 1079
	     nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)))
		return -ENOBUFS;
1080

1081
	if (rdev->wiphy.wowlan->n_patterns) {
1082
		struct nl80211_pattern_support pat = {
1083 1084 1085 1086
			.max_patterns = rdev->wiphy.wowlan->n_patterns,
			.min_pattern_len = rdev->wiphy.wowlan->pattern_min_len,
			.max_pattern_len = rdev->wiphy.wowlan->pattern_max_len,
			.max_pkt_offset = rdev->wiphy.wowlan->max_pkt_offset,
1087
		};
1088

1089 1090 1091 1092
		if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN,
			    sizeof(pat), &pat))
			return -ENOBUFS;
	}
1093

1094 1095 1096 1097 1098
	if ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_NET_DETECT) &&
	    nla_put_u32(msg, NL80211_WOWLAN_TRIG_NET_DETECT,
			rdev->wiphy.wowlan->max_nd_match_sets))
		return -ENOBUFS;

1099
	if (large && nl80211_send_wowlan_tcp_caps(rdev, msg))
1100 1101
		return -ENOBUFS;

1102
	nla_nest_end(msg, nl_wowlan);
1103

1104 1105 1106
	return 0;
}
#endif
1107

1108
static int nl80211_send_coalesce(struct sk_buff *msg,
1109
				 struct cfg80211_registered_device *rdev)
1110 1111 1112
{
	struct nl80211_coalesce_rule_support rule;

1113
	if (!rdev->wiphy.coalesce)
1114 1115
		return 0;

1116 1117 1118 1119 1120 1121
	rule.max_rules = rdev->wiphy.coalesce->n_rules;
	rule.max_delay = rdev->wiphy.coalesce->max_delay;
	rule.pat.max_patterns = rdev->wiphy.coalesce->n_patterns;
	rule.pat.min_pattern_len = rdev->wiphy.coalesce->pattern_min_len;
	rule.pat.max_pattern_len = rdev->wiphy.coalesce->pattern_max_len;
	rule.pat.max_pkt_offset = rdev->wiphy.coalesce->max_pkt_offset;
1122 1123 1124 1125 1126 1127 1128

	if (nla_put(msg, NL80211_ATTR_COALESCE_RULE, sizeof(rule), &rule))
		return -ENOBUFS;

	return 0;
}

1129 1130 1131 1132 1133 1134
static int nl80211_send_band_rateinfo(struct sk_buff *msg,
				      struct ieee80211_supported_band *sband)
{
	struct nlattr *nl_rates, *nl_rate;
	struct ieee80211_rate *rate;
	int i;
1135

1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147
	/* add HT info */
	if (sband->ht_cap.ht_supported &&
	    (nla_put(msg, NL80211_BAND_ATTR_HT_MCS_SET,
		     sizeof(sband->ht_cap.mcs),
		     &sband->ht_cap.mcs) ||
	     nla_put_u16(msg, NL80211_BAND_ATTR_HT_CAPA,
			 sband->ht_cap.cap) ||
	     nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR,
			sband->ht_cap.ampdu_factor) ||
	     nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY,
			sband->ht_cap.ampdu_density)))
		return -ENOBUFS;
1148

1149 1150 1151 1152 1153 1154 1155 1156
	/* add VHT info */
	if (sband->vht_cap.vht_supported &&
	    (nla_put(msg, NL80211_BAND_ATTR_VHT_MCS_SET,
		     sizeof(sband->vht_cap.vht_mcs),
		     &sband->vht_cap.vht_mcs) ||
	     nla_put_u32(msg, NL80211_BAND_ATTR_VHT_CAPA,
			 sband->vht_cap.cap)))
		return -ENOBUFS;
1157

1158 1159 1160 1161
	/* add bitrates */
	nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES);
	if (!nl_rates)
		return -ENOBUFS;
1162

1163 1164 1165 1166
	for (i = 0; i < sband->n_bitrates; i++) {
		nl_rate = nla_nest_start(msg, i);
		if (!nl_rate)
			return -ENOBUFS;
1167

1168 1169 1170 1171 1172 1173 1174 1175
		rate = &sband->bitrates[i];
		if (nla_put_u32(msg, NL80211_BITRATE_ATTR_RATE,
				rate->bitrate))
			return -ENOBUFS;
		if ((rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) &&
		    nla_put_flag(msg,
				 NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE))
			return -ENOBUFS;
1176

1177 1178
		nla_nest_end(msg, nl_rate);
	}
1179

1180
	nla_nest_end(msg, nl_rates);
1181

1182 1183
	return 0;
}
1184

1185 1186 1187 1188 1189 1190 1191 1192
static int
nl80211_send_mgmt_stypes(struct sk_buff *msg,
			 const struct ieee80211_txrx_stypes *mgmt_stypes)
{
	u16 stypes;
	struct nlattr *nl_ftypes, *nl_ifs;
	enum nl80211_iftype ift;
	int i;
1193

1194 1195
	if (!mgmt_stypes)
		return 0;
1196

1197 1198 1199
	nl_ifs = nla_nest_start(msg, NL80211_ATTR_TX_FRAME_TYPES);
	if (!nl_ifs)
		return -ENOBUFS;
1200

1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213
	for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) {
		nl_ftypes = nla_nest_start(msg, ift);
		if (!nl_ftypes)
			return -ENOBUFS;
		i = 0;
		stypes = mgmt_stypes[ift].tx;
		while (stypes) {
			if ((stypes & 1) &&
			    nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE,
					(i << 4) | IEEE80211_FTYPE_MGMT))
				return -ENOBUFS;
			stypes >>= 1;
			i++;
1214
		}
1215 1216
		nla_nest_end(msg, nl_ftypes);
	}
1217

1218
	nla_nest_end(msg, nl_ifs);
1219

1220 1221 1222
	nl_ifs = nla_nest_start(msg, NL80211_ATTR_RX_FRAME_TYPES);
	if (!nl_ifs)
		return -ENOBUFS;
1223

1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240
	for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) {
		nl_ftypes = nla_nest_start(msg, ift);
		if (!nl_ftypes)
			return -ENOBUFS;
		i = 0;
		stypes = mgmt_stypes[ift].rx;
		while (stypes) {
			if ((stypes & 1) &&
			    nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE,
					(i << 4) | IEEE80211_FTYPE_MGMT))
				return -ENOBUFS;
			stypes >>= 1;
			i++;
		}
		nla_nest_end(msg, nl_ftypes);
	}
	nla_nest_end(msg, nl_ifs);
1241

1242 1243
	return 0;
}
1244

1245 1246 1247 1248 1249 1250 1251
struct nl80211_dump_wiphy_state {
	s64 filter_wiphy;
	long start;
	long split_start, band_start, chan_start;
	bool split;
};

1252
static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
1253
			      enum nl80211_commands cmd,
1254
			      struct sk_buff *msg, u32 portid, u32 seq,
1255
			      int flags, struct nl80211_dump_wiphy_state *state)
1256 1257 1258 1259 1260 1261 1262 1263 1264
{
	void *hdr;
	struct nlattr *nl_bands, *nl_band;
	struct nlattr *nl_freqs, *nl_freq;
	struct nlattr *nl_cmds;
	enum ieee80211_band band;
	struct ieee80211_channel *chan;
	int i;
	const struct ieee80211_txrx_stypes *mgmt_stypes =
1265
				rdev->wiphy.mgmt_stypes;
1266
	u32 features;
1267

1268
	hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
1269 1270
	if (!hdr)
		return -ENOBUFS;
1271

1272 1273
	if (WARN_ON(!state))
		return -EINVAL;
1274

1275
	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
1276
	    nla_put_string(msg, NL80211_ATTR_WIPHY_NAME,
1277
			   wiphy_name(&rdev->wiphy)) ||
1278 1279
	    nla_put_u32(msg, NL80211_ATTR_GENERATION,
			cfg80211_rdev_list_generation))
1280 1281
		goto nla_put_failure;

1282 1283 1284
	if (cmd != NL80211_CMD_NEW_WIPHY)
		goto finish;

1285
	switch (state->split_start) {
1286 1287
	case 0:
		if (nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT,
1288
			       rdev->wiphy.retry_short) ||
1289
		    nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_LONG,
1290
			       rdev->wiphy.retry_long) ||
1291
		    nla_put_u32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
1292
				rdev->wiphy.frag_threshold) ||
1293
		    nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD,
1294
				rdev->wiphy.rts_threshold) ||
1295
		    nla_put_u8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS,
1296
			       rdev->wiphy.coverage_class) ||
1297
		    nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
1298
			       rdev->wiphy.max_scan_ssids) ||
1299
		    nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS,
1300
			       rdev->wiphy.max_sched_scan_ssids) ||
1301
		    nla_put_u16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN,
1302
				rdev->wiphy.max_scan_ie_len) ||
1303
		    nla_put_u16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN,
1304
				rdev->wiphy.max_sched_scan_ie_len) ||
1305
		    nla_put_u8(msg, NL80211_ATTR_MAX_MATCH_SETS,
1306
			       rdev->wiphy.max_match_sets))
1307
			goto nla_put_failure;
1308

1309
		if ((rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) &&
1310
		    nla_put_flag(msg, NL80211_ATTR_SUPPORT_IBSS_RSN))
1311
			goto nla_put_failure;
1312
		if ((rdev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) &&
1313 1314
		    nla_put_flag(msg, NL80211_ATTR_SUPPORT_MESH_AUTH))
			goto nla_put_failure;
1315
		if ((rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) &&
1316 1317
		    nla_put_flag(msg, NL80211_ATTR_SUPPORT_AP_UAPSD))
			goto nla_put_failure;
1318
		if ((rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM) &&
1319 1320
		    nla_put_flag(msg, NL80211_ATTR_ROAM_SUPPORT))
			goto nla_put_failure;
1321
		if ((rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) &&
1322 1323
		    nla_put_flag(msg, NL80211_ATTR_TDLS_SUPPORT))
			goto nla_put_failure;
1324
		if ((rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) &&
1325
		    nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP))
1326
			goto nla_put_failure;
1327 1328
		state->split_start++;
		if (state->split)
1329 1330 1331
			break;
	case 1:
		if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES,
1332 1333
			    sizeof(u32) * rdev->wiphy.n_cipher_suites,
			    rdev->wiphy.cipher_suites))
1334
			goto nla_put_failure;
1335

1336
		if (nla_put_u8(msg, NL80211_ATTR_MAX_NUM_PMKIDS,
1337
			       rdev->wiphy.max_num_pmkids))
1338
			goto nla_put_failure;
1339

1340
		if ((rdev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) &&
1341
		    nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE))
1342
			goto nla_put_failure;
1343

1344
		if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX,
1345
				rdev->wiphy.available_antennas_tx) ||
1346
		    nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX,
1347
				rdev->wiphy.available_antennas_rx))
1348
			goto nla_put_failure;
1349

1350
		if ((rdev->wiphy.flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) &&
1351
		    nla_put_u32(msg, NL80211_ATTR_PROBE_RESP_OFFLOAD,
1352
				rdev->wiphy.probe_resp_offload))
1353
			goto nla_put_failure;
1354

1355 1356 1357
		if ((rdev->wiphy.available_antennas_tx ||
		     rdev->wiphy.available_antennas_rx) &&
		    rdev->ops->get_antenna) {
1358 1359
			u32 tx_ant = 0, rx_ant = 0;
			int res;
1360
			res = rdev_get_antenna(rdev, &tx_ant, &rx_ant);
1361 1362 1363 1364 1365 1366 1367 1368 1369 1370
			if (!res) {
				if (nla_put_u32(msg,
						NL80211_ATTR_WIPHY_ANTENNA_TX,
						tx_ant) ||
				    nla_put_u32(msg,
						NL80211_ATTR_WIPHY_ANTENNA_RX,
						rx_ant))
					goto nla_put_failure;
			}
		}
1371

1372 1373
		state->split_start++;
		if (state->split)
1374 1375 1376
			break;
	case 2:
		if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES,
1377
					rdev->wiphy.interface_modes))
1378
				goto nla_put_failure;
1379 1380
		state->split_start++;
		if (state->split)
1381 1382 1383 1384 1385
			break;
	case 3:
		nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS);
		if (!nl_bands)
			goto nla_put_failure;
1386

1387 1388
		for (band = state->band_start;
		     band < IEEE80211_NUM_BANDS; band++) {
1389
			struct ieee80211_supported_band *sband;
1390

1391
			sband = rdev->wiphy.bands[band];
1392

1393 1394 1395 1396 1397
			if (!sband)
				continue;

			nl_band = nla_nest_start(msg, band);
			if (!nl_band)
1398
				goto nla_put_failure;
1399

1400
			switch (state->chan_start) {
1401 1402
			case 0:
				if (nl80211_send_band_rateinfo(msg, sband))
1403
					goto nla_put_failure;
1404 1405
				state->chan_start++;
				if (state->split)
1406 1407 1408 1409 1410 1411 1412 1413
					break;
			default:
				/* add frequencies */
				nl_freqs = nla_nest_start(
					msg, NL80211_BAND_ATTR_FREQS);
				if (!nl_freqs)
					goto nla_put_failure;

1414
				for (i = state->chan_start - 1;
1415 1416 1417 1418 1419 1420 1421 1422
				     i < sband->n_channels;
				     i++) {
					nl_freq = nla_nest_start(msg, i);
					if (!nl_freq)
						goto nla_put_failure;

					chan = &sband->channels[i];

1423 1424 1425
					if (nl80211_msg_put_channel(
							msg, chan,
							state->split))
1426 1427 1428
						goto nla_put_failure;

					nla_nest_end(msg, nl_freq);
1429
					if (state->split)
1430 1431 1432
						break;
				}
				if (i < sband->n_channels)
1433
					state->chan_start = i + 2;
1434
				else
1435
					state->chan_start = 0;
1436 1437 1438 1439 1440
				nla_nest_end(msg, nl_freqs);
			}

			nla_nest_end(msg, nl_band);

1441
			if (state->split) {
1442
				/* start again here */
1443
				if (state->chan_start)
1444 1445
					band--;
				break;
1446 1447
			}
		}
1448
		nla_nest_end(msg, nl_bands);
1449

1450
		if (band < IEEE80211_NUM_BANDS)
1451
			state->band_start = band + 1;
1452
		else
1453
			state->band_start = 0;
Johannes Berg's avatar
Johannes Berg committed
1454

1455
		/* if bands & channels are done, continue outside */
1456 1457 1458
		if (state->band_start == 0 && state->chan_start == 0)
			state->split_start++;
		if (state->split)
1459 1460 1461 1462
			break;
	case 4:
		nl_cmds = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_COMMANDS);
		if (!nl_cmds)
1463 1464
			goto nla_put_failure;

1465 1466 1467
		i = 0;
#define CMD(op, n)							\
		 do {							\
1468
			if (rdev->ops->op) {				\
1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491
				i++;					\
				if (nla_put_u32(msg, i, NL80211_CMD_ ## n)) \
					goto nla_put_failure;		\
			}						\
		} while (0)

		CMD(add_virtual_intf, NEW_INTERFACE);
		CMD(change_virtual_intf, SET_INTERFACE);
		CMD(add_key, NEW_KEY);
		CMD(start_ap, START_AP);
		CMD(add_station, NEW_STATION);
		CMD(add_mpath, NEW_MPATH);
		CMD(update_mesh_config, SET_MESH_CONFIG);
		CMD(change_bss, SET_BSS);
		CMD(auth, AUTHENTICATE);
		CMD(assoc, ASSOCIATE);
		CMD(deauth, DEAUTHENTICATE);
		CMD(disassoc, DISASSOCIATE);
		CMD(join_ibss, JOIN_IBSS);
		CMD(join_mesh, JOIN_MESH);
		CMD(set_pmksa, SET_PMKSA);
		CMD(del_pmksa, DEL_PMKSA);
		CMD(flush_pmksa, FLUSH_PMKSA);
1492
		if (rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL)
1493 1494 1495 1496
			CMD(remain_on_channel, REMAIN_ON_CHANNEL);
		CMD(set_bitrate_mask, SET_TX_BITRATE_MASK);
		CMD(mgmt_tx, FRAME);
		CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL);
1497
		if (rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
1498 1499
			i++;
			if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS))
1500 1501
				goto nla_put_failure;
		}
1502 1503
		if (rdev->ops->set_monitor_channel || rdev->ops->start_ap ||
		    rdev->ops->join_mesh) {
1504 1505 1506 1507 1508
			i++;
			if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL))
				goto nla_put_failure;
		}
		CMD(set_wds_peer, SET_WDS_PEER);
1509
		if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) {
1510 1511 1512
			CMD(tdls_mgmt, TDLS_MGMT);
			CMD(tdls_oper, TDLS_OPER);
		}
1513
		if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN)
1514 1515 1516
			CMD(sched_scan_start, START_SCHED_SCAN);
		CMD(probe_client, PROBE_CLIENT);
		CMD(set_noack_map, SET_NOACK_MAP);
1517
		if (rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) {
1518 1519 1520 1521 1522 1523
			i++;
			if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS))
				goto nla_put_failure;
		}
		CMD(start_p2p_device, START_P2P_DEVICE);
		CMD(set_mcast_rate, SET_MCAST_RATE);
1524 1525 1526
#ifdef CONFIG_NL80211_TESTMODE
		CMD(testmode_cmd, TESTMODE);
#endif
1527
		if (state->split) {
1528 1529
			CMD(crit_proto_start, CRIT_PROTOCOL_START);
			CMD(crit_proto_stop, CRIT_PROTOCOL_STOP);
1530
			if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)
1531
				CMD(channel_switch, CHANNEL_SWITCH);
1532
			CMD(set_qos_map, SET_QOS_MAP);
1533 1534
			if (rdev->wiphy.features &
					NL80211_FEATURE_SUPPORTS_WMM_ADMISSION)
1535
				CMD(add_tx_ts, ADD_TX_TS);
1536
		}
1537
		/* add into the if now */
1538
#undef CMD
1539

1540
		if (rdev->ops->connect || rdev->ops->auth) {
1541 1542
			i++;
			if (nla_put_u32(msg, i, NL80211_CMD_CONNECT))
1543
				goto nla_put_failure;
1544 1545
		}

1546
		if (rdev->ops->disconnect || rdev->ops->deauth) {
1547 1548 1549 1550 1551 1552
			i++;
			if (nla_put_u32(msg, i, NL80211_CMD_DISCONNECT))
				goto nla_put_failure;
		}

		nla_nest_end(msg, nl_cmds);
1553 1554
		state->split_start++;
		if (state->split)
1555 1556
			break;
	case 5:
1557 1558
		if (rdev->ops->remain_on_channel &&
		    (rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) &&
1559 1560
		    nla_put_u32(msg,
				NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION,
1561
				rdev->wiphy.max_remain_on_channel_duration))
1562 1563
			goto nla_put_failure;

1564
		if ((rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX) &&
1565 1566 1567 1568 1569
		    nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK))
			goto nla_put_failure;

		if (nl80211_send_mgmt_stypes(msg, mgmt_stypes))
			goto nla_put_failure;
1570 1571
		state->split_start++;
		if (state->split)
1572 1573 1574
			break;
	case 6:
#ifdef CONFIG_PM
1575
		if (nl80211_send_wowlan(msg, rdev, state->split))
1576
			goto nla_put_failure;
1577 1578
		state->split_start++;
		if (state->split)
1579 1580
			break;
#else
1581
		state->split_start++;
1582
#endif
1583 1584
	case 7:
		if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES,
1585
					rdev->wiphy.software_iftypes))
1586
			goto nla_put_failure;
1587

1588
		if (nl80211_put_iface_combinations(&rdev->wiphy, msg,
1589
						   state->split))
1590
			goto nla_put_failure;
1591

1592 1593
		state->split_start++;
		if (state->split)
1594 1595
			break;
	case 8:
1596
		if ((rdev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) &&
1597
		    nla_put_u32(msg, NL80211_ATTR_DEVICE_AP_SME,
1598
				rdev->wiphy.ap_sme_capa))
1599
			goto nla_put_failure;
1600

1601
		features = rdev->wiphy.features;
1602 1603 1604 1605 1606
		/*
		 * We can only add the per-channel limit information if the
		 * dump is split, otherwise it makes it too big. Therefore
		 * only advertise it in that case.
		 */
1607
		if (state->split)
1608 1609
			features |= NL80211_FEATURE_ADVERTISE_CHAN_LIMITS;
		if (nla_put_u32(msg, NL80211_ATTR_FEATURE_FLAGS, features))
1610
			goto nla_put_failure;
1611

1612
		if (rdev->wiphy.ht_capa_mod_mask &&
1613
		    nla_put(msg, NL80211_ATTR_HT_CAPABILITY_MASK,
1614 1615
			    sizeof(*rdev->wiphy.ht_capa_mod_mask),
			    rdev->wiphy.ht_capa_mod_mask))
1616
			goto nla_put_failure;
1617

1618 1619
		if (rdev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME &&
		    rdev->wiphy.max_acl_mac_addrs &&
1620
		    nla_put_u32(msg, NL80211_ATTR_MAC_ACL_MAX,
1621
				rdev->wiphy.max_acl_mac_addrs))
1622
			goto nla_put_failure;
1623

1624 1625 1626 1627 1628 1629 1630 1631 1632 1633
		/*
		 * Any information below this point is only available to
		 * applications that can deal with it being split. This
		 * helps ensure that newly added capabilities don't break
		 * older tools by overrunning their buffers.
		 *
		 * 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.
		 */
1634
		state->split_start++;
1635 1636
		break;
	case 9:
1637
		if (rdev->wiphy.extended_capabilities &&
1638
		    (nla_put(msg, NL80211_ATTR_EXT_CAPA,
1639 1640
			     rdev->wiphy.extended_capabilities_len,
			     rdev->wiphy.extended_capabilities) ||
1641
		     nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK,
1642 1643
			     rdev->wiphy.extended_capabilities_len,
			     rdev->wiphy.extended_capabilities_mask)))
1644
			goto nla_put_failure;
1645

1646
		if (rdev->wiphy.vht_capa_mod_mask &&
1647
		    nla_put(msg, NL80211_ATTR_VHT_CAPABILITY_MASK,
1648 1649
			    sizeof(*rdev->wiphy.vht_capa_mod_mask),
			    rdev->wiphy.vht_capa_mod_mask))
1650 1651
			goto nla_put_failure;

1652 1653 1654
		state->split_start++;
		break;
	case 10:
1655
		if (nl80211_send_coalesce(msg, rdev))
1656 1657
			goto nla_put_failure;

1658
		if ((rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ) &&
1659 1660 1661
		    (nla_put_flag(msg, NL80211_ATTR_SUPPORT_5_MHZ) ||
		     nla_put_flag(msg, NL80211_ATTR_SUPPORT_10_MHZ)))
			goto nla_put_failure;
1662

1663
		if (rdev->wiphy.max_ap_assoc_sta &&
1664
		    nla_put_u32(msg, NL80211_ATTR_MAX_AP_ASSOC_STA,
1665
				rdev->wiphy.max_ap_assoc_sta))
1666 1667
			goto nla_put_failure;

1668 1669 1670
		state->split_start++;
		break;
	case 11:
1671
		if (rdev->wiphy.n_vendor_commands) {
1672 1673 1674 1675 1676 1677 1678
			const struct nl80211_vendor_cmd_info *info;
			struct nlattr *nested;

			nested = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
			if (!nested)
				goto nla_put_failure;

1679 1680
			for (i = 0; i < rdev->wiphy.n_vendor_commands; i++) {
				info = &rdev->wiphy.vendor_commands[i].info;
1681 1682 1683 1684 1685 1686
				if (nla_put(msg, i + 1, sizeof(*info), info))
					goto nla_put_failure;
			}
			nla_nest_end(msg, nested);
		}

1687
		if (rdev->wiphy.n_vendor_events) {
1688 1689
			const struct nl80211_vendor_cmd_info *info;
			struct nlattr *nested;
1690

1691 1692 1693
			nested = nla_nest_start(msg,
						NL80211_ATTR_VENDOR_EVENTS);
			if (!nested)
1694
				goto nla_put_failure;
1695

1696 1697
			for (i = 0; i < rdev->wiphy.n_vendor_events; i++) {
				info = &rdev->wiphy.vendor_events[i];
1698 1699 1700 1701 1702
				if (nla_put(msg, i + 1, sizeof(*info), info))
					goto nla_put_failure;
			}
			nla_nest_end(msg, nested);
		}
1703 1704 1705 1706 1707 1708 1709
		state->split_start++;
		break;
	case 12:
		if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH &&
		    nla_put_u8(msg, NL80211_ATTR_MAX_CSA_COUNTERS,
			       rdev->wiphy.max_num_csa_counters))
			goto nla_put_failure;
1710

1711 1712 1713 1714
		if (rdev->wiphy.regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
		    nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
			goto nla_put_failure;

1715 1716 1717 1718 1719
		if (nla_put(msg, NL80211_ATTR_EXT_FEATURES,
			    sizeof(rdev->wiphy.ext_features),
			    rdev->wiphy.ext_features))
			goto nla_put_failure;

1720
		/* done */
1721
		state->split_start = 0;
1722 1723
		break;
	}
1724
 finish:
1725 1726
	genlmsg_end(msg, hdr);
	return 0;
1727 1728

 nla_put_failure:
1729 1730
	genlmsg_cancel(msg, hdr);
	return -EMSGSIZE;
1731 1732
}

1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753
static int nl80211_dump_wiphy_parse(struct sk_buff *skb,
				    struct netlink_callback *cb,
				    struct nl80211_dump_wiphy_state *state)
{
	struct nlattr **tb = nl80211_fam.attrbuf;
	int ret = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
			      tb, nl80211_fam.maxattr, nl80211_policy);
	/* ignore parse errors for backward compatibility */
	if (ret)
		return 0;

	state->split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP];
	if (tb[NL80211_ATTR_WIPHY])
		state->filter_wiphy = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
	if (tb[NL80211_ATTR_WDEV])
		state->filter_wiphy = nla_get_u64(tb[NL80211_ATTR_WDEV]) >> 32;
	if (tb[NL80211_ATTR_IFINDEX]) {
		struct net_device *netdev;
		struct cfg80211_registered_device *rdev;
		int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);

1754
		netdev = __dev_get_by_index(sock_net(skb->sk), ifidx);
1755 1756 1757
		if (!netdev)
			return -ENODEV;
		if (netdev->ieee80211_ptr) {
1758
			rdev = wiphy_to_rdev(
1759 1760 1761 1762 1763 1764 1765 1766
				netdev->ieee80211_ptr->wiphy);
			state->filter_wiphy = rdev->wiphy_idx;
		}
	}

	return 0;
}

1767 1768
static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
{
1769
	int idx = 0, ret;
1770
	struct nl80211_dump_wiphy_state *state = (void *)cb->args[0];
1771
	struct cfg80211_registered_device *rdev;
1772

1773
	rtnl_lock();
1774 1775
	if (!state) {
		state = kzalloc(sizeof(*state), GFP_KERNEL);
1776 1777
		if (!state) {
			rtnl_unlock();
1778
			return -ENOMEM;
1779
		}
1780 1781 1782 1783 1784 1785
		state->filter_wiphy = -1;
		ret = nl80211_dump_wiphy_parse(skb, cb, state);
		if (ret) {
			kfree(state);
			rtnl_unlock();
			return ret;
1786
		}
1787
		cb->args[0] = (long)state;
1788 1789
	}

1790 1791
	list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
		if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
1792
			continue;
1793
		if (++idx <= state->start)
1794
			continue;
1795
		if (state->filter_wiphy != -1 &&
1796
		    state->filter_wiphy != rdev->wiphy_idx)
1797 1798 1799
			continue;
		/* attempt to fit multiple wiphy data chunks into the skb */
		do {
1800 1801
			ret = nl80211_send_wiphy(rdev, NL80211_CMD_NEW_WIPHY,
						 skb,
1802 1803
						 NETLINK_CB(cb->skb).portid,
						 cb->nlh->nlmsg_seq,
1804
						 NLM_F_MULTI, state);
1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819
			if (ret < 0) {
				/*
				 * If sending the wiphy data didn't fit (ENOBUFS
				 * or EMSGSIZE returned), this SKB is still
				 * empty (so it's not too big because another
				 * wiphy dataset is already in the skb) and
				 * we've not tried to adjust the dump allocation
				 * yet ... then adjust the alloc size to be
				 * bigger, and return 1 but with the empty skb.
				 * This results in an empty message being RX'ed
				 * in userspace, but that is ignored.
				 *
				 * We can then retry with the larger buffer.
				 */
				if ((ret == -ENOBUFS || ret == -EMSGSIZE) &&
1820
				    !skb->len && !state->split &&
1821 1822
				    cb->min_dump_alloc < 4096) {
					cb->min_dump_alloc = 4096;
1823
					state->split_start = 0;
1824
					rtnl_unlock();
1825 1826 1827 1828
					return 1;
				}
				idx--;
				break;
1829
			}
1830
		} while (state->split_start > 0);
1831
		break;
1832
	}
1833
	rtnl_unlock();
1834

1835
	state->start = idx;
1836 1837 1838 1839

	return skb->len;
}

1840 1841 1842 1843 1844 1845
static int nl80211_dump_wiphy_done(struct netlink_callback *cb)
{
	kfree((void *)cb->args[0]);
	return 0;
}

1846 1847 1848
static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
{
	struct sk_buff *msg;
1849
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
1850
	struct nl80211_dump_wiphy_state state = {};
1851

1852
	msg = nlmsg_new(4096, GFP_KERNEL);
1853
	if (!msg)
1854
		return -ENOMEM;
1855

1856 1857
	if (nl80211_send_wiphy(rdev, NL80211_CMD_NEW_WIPHY, msg,
			       info->snd_portid, info->snd_seq, 0,
1858
			       &state) < 0) {
1859 1860 1861
		nlmsg_free(msg);
		return -ENOBUFS;
	}
1862

Johannes Berg's avatar
Johannes Berg committed
1863
	return genlmsg_reply(msg, info);
1864 1865
}

1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876
static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = {
	[NL80211_TXQ_ATTR_QUEUE]		= { .type = NLA_U8 },
	[NL80211_TXQ_ATTR_TXOP]			= { .type = NLA_U16 },
	[NL80211_TXQ_ATTR_CWMIN]		= { .type = NLA_U16 },
	[NL80211_TXQ_ATTR_CWMAX]		= { .type = NLA_U16 },
	[NL80211_TXQ_ATTR_AIFS]			= { .type = NLA_U8 },
};

static int parse_txq_params(struct nlattr *tb[],
			    struct ieee80211_txq_params *txq_params)
{
1877
	if (!tb[NL80211_TXQ_ATTR_AC] || !tb[NL80211_TXQ_ATTR_TXOP] ||
1878 1879 1880 1881
	    !tb[NL80211_TXQ_ATTR_CWMIN] || !tb[NL80211_TXQ_ATTR_CWMAX] ||
	    !tb[NL80211_TXQ_ATTR_AIFS])
		return -EINVAL;

1882
	txq_params->ac = nla_get_u8(tb[NL80211_TXQ_ATTR_AC]);
1883 1884 1885 1886 1887
	txq_params->txop = nla_get_u16(tb[NL80211_TXQ_ATTR_TXOP]);
	txq_params->cwmin = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMIN]);
	txq_params->cwmax = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMAX]);
	txq_params->aifs = nla_get_u8(tb[NL80211_TXQ_ATTR_AIFS]);

1888 1889 1890
	if (txq_params->ac >= NL80211_NUM_ACS)
		return -EINVAL;

1891 1892 1893
	return 0;
}

1894 1895 1896
static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev)
{
	/*
1897 1898 1899 1900 1901 1902 1903 1904 1905
	 * You can only set the channel explicitly for WDS interfaces,
	 * all others have their channel managed via their respective
	 * "establish a connection" command (connect, join, ...)
	 *
	 * For AP/GO and mesh mode, the channel can be set with the
	 * channel userspace API, but is only stored and passed to the
	 * low-level driver when the AP starts or the mesh is joined.
	 * This is for backward compatibility, userspace can also give
	 * the channel in the start-ap or join-mesh commands instead.
1906 1907
	 *
	 * Monitors are special as they are normally slaved to
1908 1909
	 * whatever else is going on, so they have their own special
	 * operation to set the monitor channel if possible.
1910 1911 1912 1913
	 */
	return !wdev ||
		wdev->iftype == NL80211_IFTYPE_AP ||
		wdev->iftype == NL80211_IFTYPE_MESH_POINT ||
1914 1915
		wdev->iftype == NL80211_IFTYPE_MONITOR ||
		wdev->iftype == NL80211_IFTYPE_P2P_GO;
1916 1917
}

1918 1919 1920 1921
static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
				 struct genl_info *info,
				 struct cfg80211_chan_def *chandef)
{
1922
	u32 control_freq;
1923 1924 1925 1926 1927 1928 1929

	if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
		return -EINVAL;

	control_freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);

	chandef->chan = ieee80211_get_channel(&rdev->wiphy, control_freq);
1930 1931 1932
	chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
	chandef->center_freq1 = control_freq;
	chandef->center_freq2 = 0;
1933 1934 1935 1936 1937

	/* Primary channel not allowed */
	if (!chandef->chan || chandef->chan->flags & IEEE80211_CHAN_DISABLED)
		return -EINVAL;

1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967
	if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
		enum nl80211_channel_type chantype;

		chantype = nla_get_u32(
				info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);

		switch (chantype) {
		case NL80211_CHAN_NO_HT:
		case NL80211_CHAN_HT20:
		case NL80211_CHAN_HT40PLUS:
		case NL80211_CHAN_HT40MINUS:
			cfg80211_chandef_create(chandef, chandef->chan,
						chantype);
			break;
		default:
			return -EINVAL;
		}
	} else if (info->attrs[NL80211_ATTR_CHANNEL_WIDTH]) {
		chandef->width =
			nla_get_u32(info->attrs[NL80211_ATTR_CHANNEL_WIDTH]);
		if (info->attrs[NL80211_ATTR_CENTER_FREQ1])
			chandef->center_freq1 =
				nla_get_u32(
					info->attrs[NL80211_ATTR_CENTER_FREQ1]);
		if (info->attrs[NL80211_ATTR_CENTER_FREQ2])
			chandef->center_freq2 =
				nla_get_u32(
					info->attrs[NL80211_ATTR_CENTER_FREQ2]);
	}

1968
	if (!cfg80211_chandef_valid(chandef))
1969 1970
		return -EINVAL;

1971 1972
	if (!cfg80211_chandef_usable(&rdev->wiphy, chandef,
				     IEEE80211_CHAN_DISABLED))
1973 1974
		return -EINVAL;

1975 1976 1977 1978 1979
	if ((chandef->width == NL80211_CHAN_WIDTH_5 ||
	     chandef->width == NL80211_CHAN_WIDTH_10) &&
	    !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ))
		return -EINVAL;

1980 1981 1982
	return 0;
}

1983
static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
1984
				 struct net_device *dev,
1985 1986
				 struct genl_info *info)
{
1987
	struct cfg80211_chan_def chandef;
1988
	int result;
1989
	enum nl80211_iftype iftype = NL80211_IFTYPE_MONITOR;
1990
	struct wireless_dev *wdev = NULL;
1991

1992 1993
	if (dev)
		wdev = dev->ieee80211_ptr;
1994 1995
	if (!nl80211_can_set_dev_channel(wdev))
		return -EOPNOTSUPP;
1996 1997
	if (wdev)
		iftype = wdev->iftype;
1998

1999 2000 2001
	result = nl80211_parse_chandef(rdev, info, &chandef);
	if (result)
		return result;
2002

2003
	switch (iftype) {
2004 2005
	case NL80211_IFTYPE_AP:
	case NL80211_IFTYPE_P2P_GO:
2006 2007
		if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef,
						   iftype)) {
2008 2009 2010
			result = -EINVAL;
			break;
		}
2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027
		if (wdev->beacon_interval) {
			if (!dev || !rdev->ops->set_ap_chanwidth ||
			    !(rdev->wiphy.features &
			      NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE)) {
				result = -EBUSY;
				break;
			}

			/* Only allow dynamic channel width changes */
			if (chandef.chan != wdev->preset_chandef.chan) {
				result = -EBUSY;
				break;
			}
			result = rdev_set_ap_chanwidth(rdev, dev, &chandef);
			if (result)
				break;
		}
2028
		wdev->preset_chandef = chandef;
2029 2030
		result = 0;
		break;
2031
	case NL80211_IFTYPE_MESH_POINT:
2032
		result = cfg80211_set_mesh_channel(rdev, wdev, &chandef);
2033
		break;
2034
	case NL80211_IFTYPE_MONITOR:
2035
		result = cfg80211_set_monitor_channel(rdev, &chandef);
2036
		break;
2037
	default:
2038
		result = -EINVAL;
2039 2040 2041 2042 2043 2044 2045
	}

	return result;
}

static int nl80211_set_channel(struct sk_buff *skb, struct genl_info *info)
{
2046 2047
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *netdev = info->user_ptr[1];
2048

2049
	return __nl80211_set_channel(rdev, netdev, info);
2050 2051
}

2052 2053
static int nl80211_set_wds_peer(struct sk_buff *skb, struct genl_info *info)
{
2054 2055 2056
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
	struct wireless_dev *wdev = dev->ieee80211_ptr;
2057
	const u8 *bssid;
2058 2059 2060 2061

	if (!info->attrs[NL80211_ATTR_MAC])
		return -EINVAL;

2062 2063
	if (netif_running(dev))
		return -EBUSY;
2064

2065 2066
	if (!rdev->ops->set_wds_peer)
		return -EOPNOTSUPP;
2067

2068 2069
	if (wdev->iftype != NL80211_IFTYPE_WDS)
		return -EOPNOTSUPP;
2070 2071

	bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
2072
	return rdev_set_wds_peer(rdev, dev, bssid);
2073 2074 2075
}


2076 2077 2078
static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev;
2079 2080
	struct net_device *netdev = NULL;
	struct wireless_dev *wdev;
2081
	int result = 0, rem_txq_params = 0;
2082
	struct nlattr *nl_txq_params;
2083 2084 2085
	u32 changed;
	u8 retry_short = 0, retry_long = 0;
	u32 frag_threshold = 0, rts_threshold = 0;
2086
	u8 coverage_class = 0;
2087

2088 2089
	ASSERT_RTNL();

2090 2091 2092 2093 2094 2095 2096 2097 2098
	/*
	 * Try to find the wiphy and netdev. Normally this
	 * function shouldn't need the netdev, but this is
	 * done for backward compatibility -- previously
	 * setting the channel was done per wiphy, but now
	 * it is per netdev. Previous userland like hostapd
	 * also passed a netdev to set_wiphy, so that it is
	 * possible to let that go to the right netdev!
	 */
2099

2100 2101 2102
	if (info->attrs[NL80211_ATTR_IFINDEX]) {
		int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);

2103
		netdev = __dev_get_by_index(genl_info_net(info), ifindex);
2104
		if (netdev && netdev->ieee80211_ptr)
2105
			rdev = wiphy_to_rdev(netdev->ieee80211_ptr->wiphy);
2106
		else
2107
			netdev = NULL;
2108 2109
	}

2110
	if (!netdev) {
2111 2112
		rdev = __cfg80211_rdev_from_attrs(genl_info_net(info),
						  info->attrs);
2113
		if (IS_ERR(rdev))
2114
			return PTR_ERR(rdev);
2115 2116 2117
		wdev = NULL;
		netdev = NULL;
		result = 0;
2118
	} else
2119 2120 2121 2122 2123 2124
		wdev = netdev->ieee80211_ptr;

	/*
	 * end workaround code, by now the rdev is available
	 * and locked, and wdev may or may not be NULL.
	 */
2125 2126

	if (info->attrs[NL80211_ATTR_WIPHY_NAME])
2127 2128
		result = cfg80211_dev_rename(
			rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
2129 2130

	if (result)
2131
		return result;
2132 2133 2134 2135 2136

	if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) {
		struct ieee80211_txq_params txq_params;
		struct nlattr *tb[NL80211_TXQ_ATTR_MAX + 1];

2137 2138
		if (!rdev->ops->set_txq_params)
			return -EOPNOTSUPP;
2139

2140 2141
		if (!netdev)
			return -EINVAL;
2142

2143
		if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
2144 2145
		    netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
			return -EINVAL;
2146

2147 2148
		if (!netif_running(netdev))
			return -ENETDOWN;
2149

2150 2151 2152
		nla_for_each_nested(nl_txq_params,
				    info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
				    rem_txq_params) {
2153 2154 2155 2156 2157 2158
			result = nla_parse(tb, NL80211_TXQ_ATTR_MAX,
					   nla_data(nl_txq_params),
					   nla_len(nl_txq_params),
					   txq_params_policy);
			if (result)
				return result;
2159 2160
			result = parse_txq_params(tb, &txq_params);
			if (result)
2161
				return result;
2162

2163 2164
			result = rdev_set_txq_params(rdev, netdev,
						     &txq_params);
2165
			if (result)
2166
				return result;
2167 2168
		}
	}
2169

2170
	if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
2171 2172 2173 2174
		result = __nl80211_set_channel(
			rdev,
			nl80211_can_set_dev_channel(wdev) ? netdev : NULL,
			info);
2175
		if (result)
2176
			return result;
2177 2178
	}

2179
	if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) {
2180
		struct wireless_dev *txp_wdev = wdev;
2181 2182 2183
		enum nl80211_tx_power_setting type;
		int idx, mbm = 0;

2184 2185 2186
		if (!(rdev->wiphy.features & NL80211_FEATURE_VIF_TXPOWER))
			txp_wdev = NULL;

2187 2188
		if (!rdev->ops->set_tx_power)
			return -EOPNOTSUPP;
2189 2190 2191 2192 2193

		idx = NL80211_ATTR_WIPHY_TX_POWER_SETTING;
		type = nla_get_u32(info->attrs[idx]);

		if (!info->attrs[NL80211_ATTR_WIPHY_TX_POWER_LEVEL] &&
2194 2195
		    (type != NL80211_TX_POWER_AUTOMATIC))
			return -EINVAL;
2196 2197 2198 2199 2200 2201

		if (type != NL80211_TX_POWER_AUTOMATIC) {
			idx = NL80211_ATTR_WIPHY_TX_POWER_LEVEL;
			mbm = nla_get_u32(info->attrs[idx]);
		}

2202
		result = rdev_set_tx_power(rdev, txp_wdev, type, mbm);
2203
		if (result)
2204
			return result;
2205 2206
	}

2207 2208 2209
	if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
	    info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) {
		u32 tx_ant, rx_ant;
2210 2211
		if ((!rdev->wiphy.available_antennas_tx &&
		     !rdev->wiphy.available_antennas_rx) ||
2212 2213
		    !rdev->ops->set_antenna)
			return -EOPNOTSUPP;
2214 2215 2216 2217

		tx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX]);
		rx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]);

2218
		/* reject antenna configurations which don't match the
2219 2220
		 * available antenna masks, except for the "all" mask */
		if ((~tx_ant && (tx_ant & ~rdev->wiphy.available_antennas_tx)) ||
2221 2222
		    (~rx_ant && (rx_ant & ~rdev->wiphy.available_antennas_rx)))
			return -EINVAL;
2223

2224 2225
		tx_ant = tx_ant & rdev->wiphy.available_antennas_tx;
		rx_ant = rx_ant & rdev->wiphy.available_antennas_rx;
2226

2227
		result = rdev_set_antenna(rdev, tx_ant, rx_ant);
2228
		if (result)
2229
			return result;
2230 2231
	}

2232 2233 2234 2235 2236
	changed = 0;

	if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) {
		retry_short = nla_get_u8(
			info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]);
2237 2238 2239
		if (retry_short == 0)
			return -EINVAL;

2240 2241 2242 2243 2244 2245
		changed |= WIPHY_PARAM_RETRY_SHORT;
	}

	if (info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]) {
		retry_long = nla_get_u8(
			info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]);
2246 2247 2248
		if (retry_long == 0)
			return -EINVAL;

2249 2250 2251 2252 2253 2254
		changed |= WIPHY_PARAM_RETRY_LONG;
	}

	if (info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]) {
		frag_threshold = nla_get_u32(
			info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]);
2255 2256 2257
		if (frag_threshold < 256)
			return -EINVAL;

2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275
		if (frag_threshold != (u32) -1) {
			/*
			 * Fragments (apart from the last one) are required to
			 * have even length. Make the fragmentation code
			 * simpler by stripping LSB should someone try to use
			 * odd threshold value.
			 */
			frag_threshold &= ~0x1;
		}
		changed |= WIPHY_PARAM_FRAG_THRESHOLD;
	}

	if (info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]) {
		rts_threshold = nla_get_u32(
			info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]);
		changed |= WIPHY_PARAM_RTS_THRESHOLD;
	}

2276
	if (info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]) {
2277 2278 2279
		if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK])
			return -EINVAL;

2280 2281 2282 2283 2284
		coverage_class = nla_get_u8(
			info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]);
		changed |= WIPHY_PARAM_COVERAGE_CLASS;
	}

2285 2286 2287 2288 2289
	if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK]) {
		if (!(rdev->wiphy.features & NL80211_FEATURE_ACKTO_ESTIMATION))
			return -EOPNOTSUPP;

		changed |= WIPHY_PARAM_DYN_ACK;
2290 2291
	}

2292 2293 2294
	if (changed) {
		u8 old_retry_short, old_retry_long;
		u32 old_frag_threshold, old_rts_threshold;
2295
		u8 old_coverage_class;
2296

2297 2298
		if (!rdev->ops->set_wiphy_params)
			return -EOPNOTSUPP;
2299 2300 2301 2302 2303

		old_retry_short = rdev->wiphy.retry_short;
		old_retry_long = rdev->wiphy.retry_long;
		old_frag_threshold = rdev->wiphy.frag_threshold;
		old_rts_threshold = rdev->wiphy.rts_threshold;
2304
		old_coverage_class = rdev->wiphy.coverage_class;
2305 2306 2307 2308 2309 2310 2311 2312 2313

		if (changed & WIPHY_PARAM_RETRY_SHORT)
			rdev->wiphy.retry_short = retry_short;
		if (changed & WIPHY_PARAM_RETRY_LONG)
			rdev->wiphy.retry_long = retry_long;
		if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
			rdev->wiphy.frag_threshold = frag_threshold;
		if (changed & WIPHY_PARAM_RTS_THRESHOLD)
			rdev->wiphy.rts_threshold = rts_threshold;
2314 2315
		if (changed & WIPHY_PARAM_COVERAGE_CLASS)
			rdev->wiphy.coverage_class = coverage_class;
2316

2317
		result = rdev_set_wiphy_params(rdev, changed);
2318 2319 2320 2321 2322
		if (result) {
			rdev->wiphy.retry_short = old_retry_short;
			rdev->wiphy.retry_long = old_retry_long;
			rdev->wiphy.frag_threshold = old_frag_threshold;
			rdev->wiphy.rts_threshold = old_rts_threshold;
2323
			rdev->wiphy.coverage_class = old_coverage_class;
2324 2325
		}
	}
2326
	return 0;
2327 2328
}

2329 2330 2331
static inline u64 wdev_id(struct wireless_dev *wdev)
{
	return (u64)wdev->identifier |
2332
	       ((u64)wiphy_to_rdev(wdev->wiphy)->wiphy_idx << 32);
2333
}
2334

2335
static int nl80211_send_chandef(struct sk_buff *msg,
2336
				const struct cfg80211_chan_def *chandef)
2337
{
2338 2339
	if (WARN_ON(!cfg80211_chandef_valid(chandef)))
		return -EINVAL;
2340

2341 2342 2343
	if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
			chandef->chan->center_freq))
		return -ENOBUFS;
2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360
	switch (chandef->width) {
	case NL80211_CHAN_WIDTH_20_NOHT:
	case NL80211_CHAN_WIDTH_20:
	case NL80211_CHAN_WIDTH_40:
		if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
				cfg80211_get_chandef_type(chandef)))
			return -ENOBUFS;
		break;
	default:
		break;
	}
	if (nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, chandef->width))
		return -ENOBUFS;
	if (nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ1, chandef->center_freq1))
		return -ENOBUFS;
	if (chandef->center_freq2 &&
	    nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ2, chandef->center_freq2))
2361 2362 2363 2364
		return -ENOBUFS;
	return 0;
}

2365
static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags,
2366
			      struct cfg80211_registered_device *rdev,
2367
			      struct wireless_dev *wdev, bool removal)
2368
{
2369
	struct net_device *dev = wdev->netdev;
2370
	u8 cmd = NL80211_CMD_NEW_INTERFACE;
2371 2372
	void *hdr;

2373 2374 2375 2376
	if (removal)
		cmd = NL80211_CMD_DEL_INTERFACE;

	hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
2377 2378 2379
	if (!hdr)
		return -1;

2380 2381
	if (dev &&
	    (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
2382
	     nla_put_string(msg, NL80211_ATTR_IFNAME, dev->name)))
2383 2384 2385 2386
		goto nla_put_failure;

	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
	    nla_put_u32(msg, NL80211_ATTR_IFTYPE, wdev->iftype) ||
2387
	    nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) ||
2388
	    nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, wdev_address(wdev)) ||
2389 2390 2391 2392
	    nla_put_u32(msg, NL80211_ATTR_GENERATION,
			rdev->devlist_generation ^
			(cfg80211_rdev_list_generation << 2)))
		goto nla_put_failure;
2393

2394
	if (rdev->ops->get_channel) {
2395 2396 2397 2398 2399 2400 2401 2402
		int ret;
		struct cfg80211_chan_def chandef;

		ret = rdev_get_channel(rdev, wdev, &chandef);
		if (ret == 0) {
			if (nl80211_send_chandef(msg, &chandef))
				goto nla_put_failure;
		}
2403 2404
	}

2405 2406 2407 2408 2409
	if (wdev->ssid_len) {
		if (nla_put(msg, NL80211_ATTR_SSID, wdev->ssid_len, wdev->ssid))
			goto nla_put_failure;
	}

2410 2411
	genlmsg_end(msg, hdr);
	return 0;
2412 2413

 nla_put_failure:
2414 2415
	genlmsg_cancel(msg, hdr);
	return -EMSGSIZE;
2416 2417 2418 2419 2420 2421 2422 2423
}

static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *cb)
{
	int wp_idx = 0;
	int if_idx = 0;
	int wp_start = cb->args[0];
	int if_start = cb->args[1];
2424
	struct cfg80211_registered_device *rdev;
2425 2426
	struct wireless_dev *wdev;

2427
	rtnl_lock();
2428 2429
	list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
		if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
2430
			continue;
Johannes Berg's avatar
Johannes Berg committed
2431 2432
		if (wp_idx < wp_start) {
			wp_idx++;
2433
			continue;
Johannes Berg's avatar
Johannes Berg committed
2434
		}
2435 2436
		if_idx = 0;

2437
		list_for_each_entry(wdev, &rdev->wdev_list, list) {
Johannes Berg's avatar
Johannes Berg committed
2438 2439
			if (if_idx < if_start) {
				if_idx++;
2440
				continue;
Johannes Berg's avatar
Johannes Berg committed
2441
			}
2442
			if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid,
2443
					       cb->nlh->nlmsg_seq, NLM_F_MULTI,
2444
					       rdev, wdev, false) < 0) {
Johannes Berg's avatar
Johannes Berg committed
2445 2446 2447
				goto out;
			}
			if_idx++;
2448
		}
Johannes Berg's avatar
Johannes Berg committed
2449 2450

		wp_idx++;
2451
	}
Johannes Berg's avatar
Johannes Berg committed
2452
 out:
2453
	rtnl_unlock();
2454 2455 2456 2457 2458 2459 2460 2461 2462 2463

	cb->args[0] = wp_idx;
	cb->args[1] = if_idx;

	return skb->len;
}

static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
{
	struct sk_buff *msg;
2464
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
2465
	struct wireless_dev *wdev = info->user_ptr[1];
2466

2467
	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2468
	if (!msg)
2469
		return -ENOMEM;
2470

2471
	if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0,
2472
			       rdev, wdev, false) < 0) {
2473 2474 2475
		nlmsg_free(msg);
		return -ENOBUFS;
	}
2476

Johannes Berg's avatar
Johannes Berg committed
2477
	return genlmsg_reply(msg, info);
2478 2479
}

2480 2481 2482 2483 2484 2485
static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = {
	[NL80211_MNTR_FLAG_FCSFAIL] = { .type = NLA_FLAG },
	[NL80211_MNTR_FLAG_PLCPFAIL] = { .type = NLA_FLAG },
	[NL80211_MNTR_FLAG_CONTROL] = { .type = NLA_FLAG },
	[NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG },
	[NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG },
2486
	[NL80211_MNTR_FLAG_ACTIVE] = { .type = NLA_FLAG },
2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509
};

static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
{
	struct nlattr *flags[NL80211_MNTR_FLAG_MAX + 1];
	int flag;

	*mntrflags = 0;

	if (!nla)
		return -EINVAL;

	if (nla_parse_nested(flags, NL80211_MNTR_FLAG_MAX,
			     nla, mntr_flags_policy))
		return -EINVAL;

	for (flag = 1; flag <= NL80211_MNTR_FLAG_MAX; flag++)
		if (flags[flag])
			*mntrflags |= (1<<flag);

	return 0;
}

2510
static int nl80211_valid_4addr(struct cfg80211_registered_device *rdev,
2511 2512
			       struct net_device *netdev, u8 use_4addr,
			       enum nl80211_iftype iftype)
2513
{
2514
	if (!use_4addr) {
2515
		if (netdev && (netdev->priv_flags & IFF_BRIDGE_PORT))
2516
			return -EBUSY;
2517
		return 0;
2518
	}
2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535

	switch (iftype) {
	case NL80211_IFTYPE_AP_VLAN:
		if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP)
			return 0;
		break;
	case NL80211_IFTYPE_STATION:
		if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_STATION)
			return 0;
		break;
	default:
		break;
	}

	return -EOPNOTSUPP;
}

2536 2537
static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
{
2538
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
2539
	struct vif_params params;
2540
	int err;
2541
	enum nl80211_iftype otype, ntype;
2542
	struct net_device *dev = info->user_ptr[1];
2543
	u32 _flags, *flags = NULL;
2544
	bool change = false;
2545

2546 2547
	memset(&params, 0, sizeof(params));

2548
	otype = ntype = dev->ieee80211_ptr->iftype;
2549

2550
	if (info->attrs[NL80211_ATTR_IFTYPE]) {
2551
		ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
2552
		if (otype != ntype)
2553
			change = true;
2554 2555
		if (ntype > NL80211_IFTYPE_MAX)
			return -EINVAL;
2556 2557
	}

2558
	if (info->attrs[NL80211_ATTR_MESH_ID]) {
2559 2560
		struct wireless_dev *wdev = dev->ieee80211_ptr;

2561 2562
		if (ntype != NL80211_IFTYPE_MESH_POINT)
			return -EINVAL;
2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573
		if (netif_running(dev))
			return -EBUSY;

		wdev_lock(wdev);
		BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN !=
			     IEEE80211_MAX_MESH_ID_LEN);
		wdev->mesh_id_up_len =
			nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
		memcpy(wdev->ssid, nla_data(info->attrs[NL80211_ATTR_MESH_ID]),
		       wdev->mesh_id_up_len);
		wdev_unlock(wdev);
2574 2575
	}

2576 2577 2578
	if (info->attrs[NL80211_ATTR_4ADDR]) {
		params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
		change = true;
2579
		err = nl80211_valid_4addr(rdev, dev, params.use_4addr, ntype);
2580
		if (err)
2581
			return err;
2582 2583 2584 2585
	} else {
		params.use_4addr = -1;
	}

2586
	if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) {
2587 2588
		if (ntype != NL80211_IFTYPE_MONITOR)
			return -EINVAL;
2589 2590
		err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS],
					  &_flags);
2591
		if (err)
2592
			return err;
2593 2594 2595

		flags = &_flags;
		change = true;
2596
	}
Johannes Berg's avatar
Johannes Berg committed
2597

2598
	if (flags && (*flags & MONITOR_FLAG_ACTIVE) &&
2599 2600 2601
	    !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR))
		return -EOPNOTSUPP;

2602
	if (change)
2603
		err = cfg80211_change_iface(rdev, dev, ntype, flags, &params);
2604 2605
	else
		err = 0;
2606

2607 2608 2609
	if (!err && params.use_4addr != -1)
		dev->ieee80211_ptr->use_4addr = params.use_4addr;

2610 2611 2612 2613 2614
	return err;
}

static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
{
2615
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
2616
	struct vif_params params;
2617
	struct wireless_dev *wdev;
2618
	struct sk_buff *msg, *event;
2619 2620
	int err;
	enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
2621
	u32 flags;
2622

2623 2624 2625
	/* to avoid failing a new interface creation due to pending removal */
	cfg80211_destroy_ifaces(rdev);

2626 2627
	memset(&params, 0, sizeof(params));

2628 2629 2630 2631 2632 2633 2634 2635 2636
	if (!info->attrs[NL80211_ATTR_IFNAME])
		return -EINVAL;

	if (info->attrs[NL80211_ATTR_IFTYPE]) {
		type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
		if (type > NL80211_IFTYPE_MAX)
			return -EINVAL;
	}

2637
	if (!rdev->ops->add_virtual_intf ||
2638 2639
	    !(rdev->wiphy.interface_modes & (1 << type)))
		return -EOPNOTSUPP;
2640

2641 2642 2643
	if ((type == NL80211_IFTYPE_P2P_DEVICE ||
	     rdev->wiphy.features & NL80211_FEATURE_MAC_ON_CREATE) &&
	    info->attrs[NL80211_ATTR_MAC]) {
2644 2645 2646 2647 2648 2649
		nla_memcpy(params.macaddr, info->attrs[NL80211_ATTR_MAC],
			   ETH_ALEN);
		if (!is_valid_ether_addr(params.macaddr))
			return -EADDRNOTAVAIL;
	}

2650
	if (info->attrs[NL80211_ATTR_4ADDR]) {
2651
		params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
2652
		err = nl80211_valid_4addr(rdev, NULL, params.use_4addr, type);
2653
		if (err)
2654
			return err;
2655
	}
2656

2657 2658 2659
	err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
				  info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
				  &flags);
2660

2661
	if (!err && (flags & MONITOR_FLAG_ACTIVE) &&
2662 2663 2664
	    !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR))
		return -EOPNOTSUPP;

2665 2666 2667 2668
	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
	if (!msg)
		return -ENOMEM;

2669 2670
	wdev = rdev_add_virtual_intf(rdev,
				nla_data(info->attrs[NL80211_ATTR_IFNAME]),
2671 2672
				NET_NAME_USER, type, err ? NULL : &flags,
				&params);
2673 2674 2675 2676
	if (WARN_ON(!wdev)) {
		nlmsg_free(msg);
		return -EPROTO;
	} else if (IS_ERR(wdev)) {
2677
		nlmsg_free(msg);
2678
		return PTR_ERR(wdev);
2679
	}
2680

2681
	if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
2682 2683
		wdev->owner_nlportid = info->snd_portid;

2684 2685 2686 2687
	switch (type) {
	case NL80211_IFTYPE_MESH_POINT:
		if (!info->attrs[NL80211_ATTR_MESH_ID])
			break;
2688 2689 2690 2691 2692 2693 2694 2695
		wdev_lock(wdev);
		BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN !=
			     IEEE80211_MAX_MESH_ID_LEN);
		wdev->mesh_id_up_len =
			nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
		memcpy(wdev->ssid, nla_data(info->attrs[NL80211_ATTR_MESH_ID]),
		       wdev->mesh_id_up_len);
		wdev_unlock(wdev);
2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713
		break;
	case NL80211_IFTYPE_P2P_DEVICE:
		/*
		 * P2P Device doesn't have a netdev, so doesn't go
		 * through the netdev notifier and must be added here
		 */
		mutex_init(&wdev->mtx);
		INIT_LIST_HEAD(&wdev->event_list);
		spin_lock_init(&wdev->event_lock);
		INIT_LIST_HEAD(&wdev->mgmt_registrations);
		spin_lock_init(&wdev->mgmt_registrations_lock);

		wdev->identifier = ++rdev->wdev_id;
		list_add_rcu(&wdev->list, &rdev->wdev_list);
		rdev->devlist_generation++;
		break;
	default:
		break;
2714 2715
	}

2716
	if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0,
2717
			       rdev, wdev, false) < 0) {
2718 2719 2720 2721
		nlmsg_free(msg);
		return -ENOBUFS;
	}

2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735
	event = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
	if (event) {
		if (nl80211_send_iface(event, 0, 0, 0,
				       rdev, wdev, false) < 0) {
			nlmsg_free(event);
			goto out;
		}

		genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
					event, 0, NL80211_MCGRP_CONFIG,
					GFP_KERNEL);
	}

out:
2736
	return genlmsg_reply(msg, info);
2737 2738 2739 2740
}

static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
{
2741
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
2742
	struct wireless_dev *wdev = info->user_ptr[1];
2743 2744
	struct sk_buff *msg;
	int status;
2745

2746 2747
	if (!rdev->ops->del_virtual_intf)
		return -EOPNOTSUPP;
2748

2749 2750 2751 2752 2753 2754
	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
	if (msg && nl80211_send_iface(msg, 0, 0, 0, rdev, wdev, true) < 0) {
		nlmsg_free(msg);
		msg = NULL;
	}

2755 2756 2757 2758 2759 2760 2761 2762 2763 2764
	/*
	 * If we remove a wireless device without a netdev then clear
	 * user_ptr[1] so that nl80211_post_doit won't dereference it
	 * to check if it needs to do dev_put(). Otherwise it crashes
	 * since the wdev has been freed, unlike with a netdev where
	 * we need the dev_put() for the netdev to really be freed.
	 */
	if (!wdev->netdev)
		info->user_ptr[1] = NULL;

2765 2766 2767 2768 2769 2770 2771 2772 2773
	status = rdev_del_virtual_intf(rdev, wdev);
	if (status >= 0 && msg)
		genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
					msg, 0, NL80211_MCGRP_CONFIG,
					GFP_KERNEL);
	else
		nlmsg_free(msg);

	return status;
2774 2775
}

2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789
static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
	u16 noack_map;

	if (!info->attrs[NL80211_ATTR_NOACK_MAP])
		return -EINVAL;

	if (!rdev->ops->set_noack_map)
		return -EOPNOTSUPP;

	noack_map = nla_get_u16(info->attrs[NL80211_ATTR_NOACK_MAP]);

2790
	return rdev_set_noack_map(rdev, dev, noack_map);
2791 2792
}

2793 2794 2795
struct get_key_cookie {
	struct sk_buff *msg;
	int error;
2796
	int idx;
2797 2798 2799 2800
};

static void get_key_callback(void *c, struct key_params *params)
{
2801
	struct nlattr *key;
2802 2803
	struct get_key_cookie *cookie = c;

2804 2805 2806 2807 2808 2809 2810 2811 2812 2813
	if ((params->key &&
	     nla_put(cookie->msg, NL80211_ATTR_KEY_DATA,
		     params->key_len, params->key)) ||
	    (params->seq &&
	     nla_put(cookie->msg, NL80211_ATTR_KEY_SEQ,
		     params->seq_len, params->seq)) ||
	    (params->cipher &&
	     nla_put_u32(cookie->msg, NL80211_ATTR_KEY_CIPHER,
			 params->cipher)))
		goto nla_put_failure;
2814

2815 2816 2817 2818
	key = nla_nest_start(cookie->msg, NL80211_ATTR_KEY);
	if (!key)
		goto nla_put_failure;

2819 2820 2821 2822 2823 2824 2825 2826 2827 2828
	if ((params->key &&
	     nla_put(cookie->msg, NL80211_KEY_DATA,
		     params->key_len, params->key)) ||
	    (params->seq &&
	     nla_put(cookie->msg, NL80211_KEY_SEQ,
		     params->seq_len, params->seq)) ||
	    (params->cipher &&
	     nla_put_u32(cookie->msg, NL80211_KEY_CIPHER,
			 params->cipher)))
		goto nla_put_failure;
2829

2830 2831
	if (nla_put_u8(cookie->msg, NL80211_ATTR_KEY_IDX, cookie->idx))
		goto nla_put_failure;
2832 2833 2834

	nla_nest_end(cookie->msg, key);

2835 2836 2837 2838 2839 2840 2841
	return;
 nla_put_failure:
	cookie->error = 1;
}

static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
{
2842
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
2843
	int err;
2844
	struct net_device *dev = info->user_ptr[1];
2845
	u8 key_idx = 0;
2846 2847
	const u8 *mac_addr = NULL;
	bool pairwise;
2848 2849 2850 2851 2852 2853 2854 2855 2856
	struct get_key_cookie cookie = {
		.error = 0,
	};
	void *hdr;
	struct sk_buff *msg;

	if (info->attrs[NL80211_ATTR_KEY_IDX])
		key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);

2857
	if (key_idx > 5)
2858 2859 2860 2861 2862
		return -EINVAL;

	if (info->attrs[NL80211_ATTR_MAC])
		mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);

2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873
	pairwise = !!mac_addr;
	if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
		u32 kt = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
		if (kt >= NUM_NL80211_KEYTYPES)
			return -EINVAL;
		if (kt != NL80211_KEYTYPE_GROUP &&
		    kt != NL80211_KEYTYPE_PAIRWISE)
			return -EINVAL;
		pairwise = kt == NL80211_KEYTYPE_PAIRWISE;
	}

2874 2875
	if (!rdev->ops->get_key)
		return -EOPNOTSUPP;
2876

2877 2878 2879
	if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
		return -ENOENT;

2880
	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2881 2882
	if (!msg)
		return -ENOMEM;
2883

2884
	hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
2885
			     NL80211_CMD_NEW_KEY);
2886
	if (!hdr)
2887
		goto nla_put_failure;
2888 2889

	cookie.msg = msg;
2890
	cookie.idx = key_idx;
2891

2892 2893 2894 2895 2896 2897
	if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
	    nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx))
		goto nla_put_failure;
	if (mac_addr &&
	    nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr))
		goto nla_put_failure;
2898

2899 2900
	err = rdev_get_key(rdev, dev, key_idx, pairwise, mac_addr, &cookie,
			   get_key_callback);
2901 2902

	if (err)
Niko Jokinen's avatar
Niko Jokinen committed
2903
		goto free_msg;
2904 2905 2906 2907 2908

	if (cookie.error)
		goto nla_put_failure;

	genlmsg_end(msg, hdr);
2909
	return genlmsg_reply(msg, info);
2910 2911 2912

 nla_put_failure:
	err = -ENOBUFS;
Niko Jokinen's avatar
Niko Jokinen committed
2913
 free_msg:
2914 2915 2916 2917 2918 2919
	nlmsg_free(msg);
	return err;
}

static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
{
2920
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
2921
	struct key_parse key;
2922
	int err;
2923
	struct net_device *dev = info->user_ptr[1];
2924

2925 2926 2927
	err = nl80211_parse_key(info, &key);
	if (err)
		return err;
2928

2929
	if (key.idx < 0)
2930 2931
		return -EINVAL;

2932 2933
	/* only support setting default key */
	if (!key.def && !key.defmgmt)
2934 2935
		return -EINVAL;

2936
	wdev_lock(dev->ieee80211_ptr);
2937

2938 2939 2940 2941 2942
	if (key.def) {
		if (!rdev->ops->set_default_key) {
			err = -EOPNOTSUPP;
			goto out;
		}
2943

2944 2945 2946 2947
		err = nl80211_key_allowed(dev->ieee80211_ptr);
		if (err)
			goto out;

2948
		err = rdev_set_default_key(rdev, dev, key.idx,
2949 2950 2951 2952
						 key.def_uni, key.def_multi);

		if (err)
			goto out;
2953

Johannes Berg's avatar
Johannes Berg committed
2954
#ifdef CONFIG_CFG80211_WEXT
2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971
		dev->ieee80211_ptr->wext.default_key = key.idx;
#endif
	} else {
		if (key.def_uni || !key.def_multi) {
			err = -EINVAL;
			goto out;
		}

		if (!rdev->ops->set_default_mgmt_key) {
			err = -EOPNOTSUPP;
			goto out;
		}

		err = nl80211_key_allowed(dev->ieee80211_ptr);
		if (err)
			goto out;

2972
		err = rdev_set_default_mgmt_key(rdev, dev, key.idx);
2973 2974 2975 2976 2977
		if (err)
			goto out;

#ifdef CONFIG_CFG80211_WEXT
		dev->ieee80211_ptr->wext.default_mgmt_key = key.idx;
2978
#endif
2979 2980 2981
	}

 out:
2982
	wdev_unlock(dev->ieee80211_ptr);
2983 2984 2985 2986 2987 2988

	return err;
}

static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
{
2989
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
2990
	int err;
2991
	struct net_device *dev = info->user_ptr[1];
2992
	struct key_parse key;
2993
	const u8 *mac_addr = NULL;
2994

2995 2996 2997
	err = nl80211_parse_key(info, &key);
	if (err)
		return err;
2998

2999
	if (!key.p.key)
3000 3001 3002 3003 3004
		return -EINVAL;

	if (info->attrs[NL80211_ATTR_MAC])
		mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);

3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016
	if (key.type == -1) {
		if (mac_addr)
			key.type = NL80211_KEYTYPE_PAIRWISE;
		else
			key.type = NL80211_KEYTYPE_GROUP;
	}

	/* for now */
	if (key.type != NL80211_KEYTYPE_PAIRWISE &&
	    key.type != NL80211_KEYTYPE_GROUP)
		return -EINVAL;

3017 3018
	if (!rdev->ops->add_key)
		return -EOPNOTSUPP;
3019

3020 3021 3022
	if (cfg80211_validate_key_settings(rdev, &key.p, key.idx,
					   key.type == NL80211_KEYTYPE_PAIRWISE,
					   mac_addr))
3023
		return -EINVAL;
3024

3025 3026 3027
	wdev_lock(dev->ieee80211_ptr);
	err = nl80211_key_allowed(dev->ieee80211_ptr);
	if (!err)
3028 3029 3030
		err = rdev_add_key(rdev, dev, key.idx,
				   key.type == NL80211_KEYTYPE_PAIRWISE,
				    mac_addr, &key.p);
3031
	wdev_unlock(dev->ieee80211_ptr);
3032 3033 3034 3035 3036 3037

	return err;
}

static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
{
3038
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
3039
	int err;
3040
	struct net_device *dev = info->user_ptr[1];
3041
	u8 *mac_addr = NULL;
3042
	struct key_parse key;
3043

3044 3045 3046
	err = nl80211_parse_key(info, &key);
	if (err)
		return err;
3047 3048 3049 3050

	if (info->attrs[NL80211_ATTR_MAC])
		mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);

3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062
	if (key.type == -1) {
		if (mac_addr)
			key.type = NL80211_KEYTYPE_PAIRWISE;
		else
			key.type = NL80211_KEYTYPE_GROUP;
	}

	/* for now */
	if (key.type != NL80211_KEYTYPE_PAIRWISE &&
	    key.type != NL80211_KEYTYPE_GROUP)
		return -EINVAL;

3063 3064
	if (!rdev->ops->del_key)
		return -EOPNOTSUPP;
3065

3066 3067
	wdev_lock(dev->ieee80211_ptr);
	err = nl80211_key_allowed(dev->ieee80211_ptr);
3068

3069
	if (key.type == NL80211_KEYTYPE_GROUP && mac_addr &&
3070 3071 3072
	    !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
		err = -ENOENT;

3073
	if (!err)
3074 3075 3076
		err = rdev_del_key(rdev, dev, key.idx,
				   key.type == NL80211_KEYTYPE_PAIRWISE,
				   mac_addr);
3077

Johannes Berg's avatar
Johannes Berg committed
3078
#ifdef CONFIG_CFG80211_WEXT
3079
	if (!err) {
3080
		if (key.idx == dev->ieee80211_ptr->wext.default_key)
3081
			dev->ieee80211_ptr->wext.default_key = -1;
3082
		else if (key.idx == dev->ieee80211_ptr->wext.default_mgmt_key)
3083 3084 3085
			dev->ieee80211_ptr->wext.default_mgmt_key = -1;
	}
#endif
3086
	wdev_unlock(dev->ieee80211_ptr);
3087

3088 3089 3090
	return err;
}

3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181
/* This function returns an error or the number of nested attributes */
static int validate_acl_mac_addrs(struct nlattr *nl_attr)
{
	struct nlattr *attr;
	int n_entries = 0, tmp;

	nla_for_each_nested(attr, nl_attr, tmp) {
		if (nla_len(attr) != ETH_ALEN)
			return -EINVAL;

		n_entries++;
	}

	return n_entries;
}

/*
 * This function parses ACL information and allocates memory for ACL data.
 * On successful return, the calling function is responsible to free the
 * ACL buffer returned by this function.
 */
static struct cfg80211_acl_data *parse_acl_data(struct wiphy *wiphy,
						struct genl_info *info)
{
	enum nl80211_acl_policy acl_policy;
	struct nlattr *attr;
	struct cfg80211_acl_data *acl;
	int i = 0, n_entries, tmp;

	if (!wiphy->max_acl_mac_addrs)
		return ERR_PTR(-EOPNOTSUPP);

	if (!info->attrs[NL80211_ATTR_ACL_POLICY])
		return ERR_PTR(-EINVAL);

	acl_policy = nla_get_u32(info->attrs[NL80211_ATTR_ACL_POLICY]);
	if (acl_policy != NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED &&
	    acl_policy != NL80211_ACL_POLICY_DENY_UNLESS_LISTED)
		return ERR_PTR(-EINVAL);

	if (!info->attrs[NL80211_ATTR_MAC_ADDRS])
		return ERR_PTR(-EINVAL);

	n_entries = validate_acl_mac_addrs(info->attrs[NL80211_ATTR_MAC_ADDRS]);
	if (n_entries < 0)
		return ERR_PTR(n_entries);

	if (n_entries > wiphy->max_acl_mac_addrs)
		return ERR_PTR(-ENOTSUPP);

	acl = kzalloc(sizeof(*acl) + (sizeof(struct mac_address) * n_entries),
		      GFP_KERNEL);
	if (!acl)
		return ERR_PTR(-ENOMEM);

	nla_for_each_nested(attr, info->attrs[NL80211_ATTR_MAC_ADDRS], tmp) {
		memcpy(acl->mac_addrs[i].addr, nla_data(attr), ETH_ALEN);
		i++;
	}

	acl->n_acl_entries = n_entries;
	acl->acl_policy = acl_policy;

	return acl;
}

static int nl80211_set_mac_acl(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
	struct cfg80211_acl_data *acl;
	int err;

	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
		return -EOPNOTSUPP;

	if (!dev->ieee80211_ptr->beacon_interval)
		return -EINVAL;

	acl = parse_acl_data(&rdev->wiphy, info);
	if (IS_ERR(acl))
		return PTR_ERR(acl);

	err = rdev_set_mac_acl(rdev, dev, acl);

	kfree(acl);

	return err;
}

3182
static int nl80211_parse_beacon(struct nlattr *attrs[],
3183
				struct cfg80211_beacon_data *bcn)
3184
{
3185
	bool haveinfo = false;
3186

3187 3188 3189 3190
	if (!is_valid_ie_attr(attrs[NL80211_ATTR_BEACON_TAIL]) ||
	    !is_valid_ie_attr(attrs[NL80211_ATTR_IE]) ||
	    !is_valid_ie_attr(attrs[NL80211_ATTR_IE_PROBE_RESP]) ||
	    !is_valid_ie_attr(attrs[NL80211_ATTR_IE_ASSOC_RESP]))
3191 3192
		return -EINVAL;

3193
	memset(bcn, 0, sizeof(*bcn));
3194

3195 3196 3197
	if (attrs[NL80211_ATTR_BEACON_HEAD]) {
		bcn->head = nla_data(attrs[NL80211_ATTR_BEACON_HEAD]);
		bcn->head_len = nla_len(attrs[NL80211_ATTR_BEACON_HEAD]);
3198 3199 3200
		if (!bcn->head_len)
			return -EINVAL;
		haveinfo = true;
3201 3202
	}

3203 3204 3205
	if (attrs[NL80211_ATTR_BEACON_TAIL]) {
		bcn->tail = nla_data(attrs[NL80211_ATTR_BEACON_TAIL]);
		bcn->tail_len = nla_len(attrs[NL80211_ATTR_BEACON_TAIL]);
3206
		haveinfo = true;
3207 3208
	}

3209 3210
	if (!haveinfo)
		return -EINVAL;
Johannes Berg's avatar
Johannes Berg committed
3211

3212 3213 3214
	if (attrs[NL80211_ATTR_IE]) {
		bcn->beacon_ies = nla_data(attrs[NL80211_ATTR_IE]);
		bcn->beacon_ies_len = nla_len(attrs[NL80211_ATTR_IE]);
3215 3216
	}

3217
	if (attrs[NL80211_ATTR_IE_PROBE_RESP]) {
3218
		bcn->proberesp_ies =
3219
			nla_data(attrs[NL80211_ATTR_IE_PROBE_RESP]);
3220
		bcn->proberesp_ies_len =
3221
			nla_len(attrs[NL80211_ATTR_IE_PROBE_RESP]);
3222 3223
	}

3224
	if (attrs[NL80211_ATTR_IE_ASSOC_RESP]) {
3225
		bcn->assocresp_ies =
3226
			nla_data(attrs[NL80211_ATTR_IE_ASSOC_RESP]);
3227
		bcn->assocresp_ies_len =
3228
			nla_len(attrs[NL80211_ATTR_IE_ASSOC_RESP]);
3229 3230
	}

3231 3232 3233
	if (attrs[NL80211_ATTR_PROBE_RESP]) {
		bcn->probe_resp = nla_data(attrs[NL80211_ATTR_PROBE_RESP]);
		bcn->probe_resp_len = nla_len(attrs[NL80211_ATTR_PROBE_RESP]);
3234 3235
	}

3236 3237 3238
	return 0;
}

3239 3240 3241 3242 3243 3244
static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
				   struct cfg80211_ap_settings *params)
{
	struct wireless_dev *wdev;
	bool ret = false;

3245
	list_for_each_entry(wdev, &rdev->wdev_list, list) {
3246 3247 3248 3249
		if (wdev->iftype != NL80211_IFTYPE_AP &&
		    wdev->iftype != NL80211_IFTYPE_P2P_GO)
			continue;

3250
		if (!wdev->preset_chandef.chan)
3251 3252
			continue;

3253
		params->chandef = wdev->preset_chandef;
3254 3255 3256 3257 3258 3259 3260
		ret = true;
		break;
	}

	return ret;
}

3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284
static bool nl80211_valid_auth_type(struct cfg80211_registered_device *rdev,
				    enum nl80211_auth_type auth_type,
				    enum nl80211_commands cmd)
{
	if (auth_type > NL80211_AUTHTYPE_MAX)
		return false;

	switch (cmd) {
	case NL80211_CMD_AUTHENTICATE:
		if (!(rdev->wiphy.features & NL80211_FEATURE_SAE) &&
		    auth_type == NL80211_AUTHTYPE_SAE)
			return false;
		return true;
	case NL80211_CMD_CONNECT:
	case NL80211_CMD_START_AP:
		/* SAE not supported yet */
		if (auth_type == NL80211_AUTHTYPE_SAE)
			return false;
		return true;
	default:
		return false;
	}
}

3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310
static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
	struct wireless_dev *wdev = dev->ieee80211_ptr;
	struct cfg80211_ap_settings params;
	int err;

	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
		return -EOPNOTSUPP;

	if (!rdev->ops->start_ap)
		return -EOPNOTSUPP;

	if (wdev->beacon_interval)
		return -EALREADY;

	memset(&params, 0, sizeof(params));

	/* these are required for START_AP */
	if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
	    !info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
	    !info->attrs[NL80211_ATTR_BEACON_HEAD])
		return -EINVAL;

3311
	err = nl80211_parse_beacon(info->attrs, &params.beacon);
3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353
	if (err)
		return err;

	params.beacon_interval =
		nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
	params.dtim_period =
		nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);

	err = cfg80211_validate_beacon_int(rdev, params.beacon_interval);
	if (err)
		return err;

	/*
	 * In theory, some of these attributes should be required here
	 * but since they were not used when the command was originally
	 * added, keep them optional for old user space programs to let
	 * them continue to work with drivers that do not need the
	 * additional information -- drivers must check!
	 */
	if (info->attrs[NL80211_ATTR_SSID]) {
		params.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
		params.ssid_len =
			nla_len(info->attrs[NL80211_ATTR_SSID]);
		if (params.ssid_len == 0 ||
		    params.ssid_len > IEEE80211_MAX_SSID_LEN)
			return -EINVAL;
	}

	if (info->attrs[NL80211_ATTR_HIDDEN_SSID]) {
		params.hidden_ssid = nla_get_u32(
			info->attrs[NL80211_ATTR_HIDDEN_SSID]);
		if (params.hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE &&
		    params.hidden_ssid != NL80211_HIDDEN_SSID_ZERO_LEN &&
		    params.hidden_ssid != NL80211_HIDDEN_SSID_ZERO_CONTENTS)
			return -EINVAL;
	}

	params.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];

	if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
		params.auth_type = nla_get_u32(
			info->attrs[NL80211_ATTR_AUTH_TYPE]);
3354 3355
		if (!nl80211_valid_auth_type(rdev, params.auth_type,
					     NL80211_CMD_START_AP))
3356 3357 3358 3359 3360 3361 3362 3363 3364
			return -EINVAL;
	} else
		params.auth_type = NL80211_AUTHTYPE_AUTOMATIC;

	err = nl80211_crypto_settings(rdev, info, &params.crypto,
				      NL80211_MAX_NR_CIPHER_SUITES);
	if (err)
		return err;

3365 3366 3367 3368 3369 3370 3371
	if (info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]) {
		if (!(rdev->wiphy.features & NL80211_FEATURE_INACTIVITY_TIMER))
			return -EOPNOTSUPP;
		params.inactivity_timeout = nla_get_u16(
			info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]);
	}

3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397
	if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
		if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
			return -EINVAL;
		params.p2p_ctwindow =
			nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
		if (params.p2p_ctwindow > 127)
			return -EINVAL;
		if (params.p2p_ctwindow != 0 &&
		    !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
			return -EINVAL;
	}

	if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
		u8 tmp;

		if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
			return -EINVAL;
		tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
		if (tmp > 1)
			return -EINVAL;
		params.p2p_opp_ps = tmp;
		if (params.p2p_opp_ps != 0 &&
		    !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))
			return -EINVAL;
	}

3398
	if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
3399 3400 3401 3402 3403
		err = nl80211_parse_chandef(rdev, info, &params.chandef);
		if (err)
			return err;
	} else if (wdev->preset_chandef.chan) {
		params.chandef = wdev->preset_chandef;
3404
	} else if (!nl80211_get_ap_channel(rdev, &params))
3405 3406
		return -EINVAL;

3407 3408
	if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params.chandef,
					   wdev->iftype))
3409 3410
		return -EINVAL;

3411 3412 3413 3414 3415 3416
	if (info->attrs[NL80211_ATTR_ACL_POLICY]) {
		params.acl = parse_acl_data(&rdev->wiphy, info);
		if (IS_ERR(params.acl))
			return PTR_ERR(params.acl);
	}

3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439
	if (info->attrs[NL80211_ATTR_SMPS_MODE]) {
		params.smps_mode =
			nla_get_u8(info->attrs[NL80211_ATTR_SMPS_MODE]);
		switch (params.smps_mode) {
		case NL80211_SMPS_OFF:
			break;
		case NL80211_SMPS_STATIC:
			if (!(rdev->wiphy.features &
			      NL80211_FEATURE_STATIC_SMPS))
				return -EINVAL;
			break;
		case NL80211_SMPS_DYNAMIC:
			if (!(rdev->wiphy.features &
			      NL80211_FEATURE_DYNAMIC_SMPS))
				return -EINVAL;
			break;
		default:
			return -EINVAL;
		}
	} else {
		params.smps_mode = NL80211_SMPS_OFF;
	}

3440
	wdev_lock(wdev);
3441
	err = rdev_start_ap(rdev, dev, &params);
3442
	if (!err) {
3443
		wdev->preset_chandef = params.chandef;
3444
		wdev->beacon_interval = params.beacon_interval;
3445
		wdev->chandef = params.chandef;
3446 3447
		wdev->ssid_len = params.ssid_len;
		memcpy(wdev->ssid, params.ssid, wdev->ssid_len);
3448
	}
3449
	wdev_unlock(wdev);
3450 3451 3452

	kfree(params.acl);

3453
	return err;
3454 3455
}

3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473
static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
	struct wireless_dev *wdev = dev->ieee80211_ptr;
	struct cfg80211_beacon_data params;
	int err;

	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
		return -EOPNOTSUPP;

	if (!rdev->ops->change_beacon)
		return -EOPNOTSUPP;

	if (!wdev->beacon_interval)
		return -EINVAL;

3474
	err = nl80211_parse_beacon(info->attrs, &params);
3475 3476 3477
	if (err)
		return err;

3478 3479 3480 3481 3482
	wdev_lock(wdev);
	err = rdev_change_beacon(rdev, dev, &params);
	wdev_unlock(wdev);

	return err;
3483 3484 3485
}

static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info)
3486
{
3487 3488
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
3489

3490
	return cfg80211_stop_ap(rdev, dev, false);
3491 3492
}

3493 3494 3495 3496
static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
	[NL80211_STA_FLAG_AUTHORIZED] = { .type = NLA_FLAG },
	[NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG },
	[NL80211_STA_FLAG_WME] = { .type = NLA_FLAG },
3497
	[NL80211_STA_FLAG_MFP] = { .type = NLA_FLAG },
3498
	[NL80211_STA_FLAG_AUTHENTICATED] = { .type = NLA_FLAG },
3499
	[NL80211_STA_FLAG_TDLS_PEER] = { .type = NLA_FLAG },
3500 3501
};

3502
static int parse_station_flags(struct genl_info *info,
3503
			       enum nl80211_iftype iftype,
3504
			       struct station_parameters *params)
3505 3506
{
	struct nlattr *flags[NL80211_STA_FLAG_MAX + 1];
3507
	struct nlattr *nla;
3508 3509
	int flag;

3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520
	/*
	 * Try parsing the new attribute first so userspace
	 * can specify both for older kernels.
	 */
	nla = info->attrs[NL80211_ATTR_STA_FLAGS2];
	if (nla) {
		struct nl80211_sta_flag_update *sta_flags;

		sta_flags = nla_data(nla);
		params->sta_flags_mask = sta_flags->mask;
		params->sta_flags_set = sta_flags->set;
3521
		params->sta_flags_set &= params->sta_flags_mask;
3522 3523 3524 3525 3526 3527 3528
		if ((params->sta_flags_mask |
		     params->sta_flags_set) & BIT(__NL80211_STA_FLAG_INVALID))
			return -EINVAL;
		return 0;
	}

	/* if present, parse the old attribute */
3529

3530
	nla = info->attrs[NL80211_ATTR_STA_FLAGS];
3531 3532 3533 3534 3535 3536 3537
	if (!nla)
		return 0;

	if (nla_parse_nested(flags, NL80211_STA_FLAG_MAX,
			     nla, sta_flags_policy))
		return -EINVAL;

3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564
	/*
	 * Only allow certain flags for interface types so that
	 * other attributes are silently ignored. Remember that
	 * this is backward compatibility code with old userspace
	 * and shouldn't be hit in other cases anyway.
	 */
	switch (iftype) {
	case NL80211_IFTYPE_AP:
	case NL80211_IFTYPE_AP_VLAN:
	case NL80211_IFTYPE_P2P_GO:
		params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
					 BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
					 BIT(NL80211_STA_FLAG_WME) |
					 BIT(NL80211_STA_FLAG_MFP);
		break;
	case NL80211_IFTYPE_P2P_CLIENT:
	case NL80211_IFTYPE_STATION:
		params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
					 BIT(NL80211_STA_FLAG_TDLS_PEER);
		break;
	case NL80211_IFTYPE_MESH_POINT:
		params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHENTICATED) |
					 BIT(NL80211_STA_FLAG_MFP) |
					 BIT(NL80211_STA_FLAG_AUTHORIZED);
	default:
		return -EINVAL;
	}
3565

3566 3567
	for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++) {
		if (flags[flag]) {
3568
			params->sta_flags_set |= (1<<flag);
3569

3570 3571 3572 3573 3574 3575
			/* no longer support new API additions in old API */
			if (flag > NL80211_STA_FLAG_MAX_OLD_API)
				return -EINVAL;
		}
	}

3576 3577 3578
	return 0;
}

3579 3580 3581 3582
static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info,
				 int attr)
{
	struct nlattr *rate;
3583 3584
	u32 bitrate;
	u16 bitrate_compat;
3585
	enum nl80211_attrs rate_flg;
3586 3587 3588

	rate = nla_nest_start(msg, attr);
	if (!rate)
3589
		return false;
3590 3591 3592

	/* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
	bitrate = cfg80211_calculate_bitrate(info);
3593 3594
	/* report 16-bit bitrate only if we can */
	bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3595 3596 3597 3598 3599 3600 3601
	if (bitrate > 0 &&
	    nla_put_u32(msg, NL80211_RATE_INFO_BITRATE32, bitrate))
		return false;
	if (bitrate_compat > 0 &&
	    nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate_compat))
		return false;

3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628
	switch (info->bw) {
	case RATE_INFO_BW_5:
		rate_flg = NL80211_RATE_INFO_5_MHZ_WIDTH;
		break;
	case RATE_INFO_BW_10:
		rate_flg = NL80211_RATE_INFO_10_MHZ_WIDTH;
		break;
	default:
		WARN_ON(1);
		/* fall through */
	case RATE_INFO_BW_20:
		rate_flg = 0;
		break;
	case RATE_INFO_BW_40:
		rate_flg = NL80211_RATE_INFO_40_MHZ_WIDTH;
		break;
	case RATE_INFO_BW_80:
		rate_flg = NL80211_RATE_INFO_80_MHZ_WIDTH;
		break;
	case RATE_INFO_BW_160:
		rate_flg = NL80211_RATE_INFO_160_MHZ_WIDTH;
		break;
	}

	if (rate_flg && nla_put_flag(msg, rate_flg))
		return false;

3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643
	if (info->flags & RATE_INFO_FLAGS_MCS) {
		if (nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs))
			return false;
		if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
		    nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
			return false;
	} else if (info->flags & RATE_INFO_FLAGS_VHT_MCS) {
		if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_MCS, info->mcs))
			return false;
		if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_NSS, info->nss))
			return false;
		if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
		    nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
			return false;
	}
3644 3645 3646 3647 3648

	nla_nest_end(msg, rate);
	return true;
}

3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674
static bool nl80211_put_signal(struct sk_buff *msg, u8 mask, s8 *signal,
			       int id)
{
	void *attr;
	int i = 0;

	if (!mask)
		return true;

	attr = nla_nest_start(msg, id);
	if (!attr)
		return false;

	for (i = 0; i < IEEE80211_MAX_CHAINS; i++) {
		if (!(mask & BIT(i)))
			continue;

		if (nla_put_u8(msg, i, signal[i]))
			return false;
	}

	nla_nest_end(msg, attr);

	return true;
}

3675 3676
static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
				u32 seq, int flags,
3677 3678
				struct cfg80211_registered_device *rdev,
				struct net_device *dev,
3679
				const u8 *mac_addr, struct station_info *sinfo)
3680 3681
{
	void *hdr;
3682
	struct nlattr *sinfoattr, *bss_param;
3683

3684
	hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
3685 3686 3687
	if (!hdr)
		return -1;

3688 3689 3690 3691
	if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
	    nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr) ||
	    nla_put_u32(msg, NL80211_ATTR_GENERATION, sinfo->generation))
		goto nla_put_failure;
3692

3693 3694
	sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO);
	if (!sinfoattr)
3695
		goto nla_put_failure;
3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708

#define PUT_SINFO(attr, memb, type) do {				\
	if (sinfo->filled & BIT(NL80211_STA_INFO_ ## attr) &&		\
	    nla_put_ ## type(msg, NL80211_STA_INFO_ ## attr,		\
			     sinfo->memb))				\
		goto nla_put_failure;					\
	} while (0)

	PUT_SINFO(CONNECTED_TIME, connected_time, u32);
	PUT_SINFO(INACTIVE_TIME, inactive_time, u32);

	if (sinfo->filled & (BIT(NL80211_STA_INFO_RX_BYTES) |
			     BIT(NL80211_STA_INFO_RX_BYTES64)) &&
3709
	    nla_put_u32(msg, NL80211_STA_INFO_RX_BYTES,
3710
			(u32)sinfo->rx_bytes))
3711
		goto nla_put_failure;
3712 3713 3714

	if (sinfo->filled & (BIT(NL80211_STA_INFO_TX_BYTES) |
			     BIT(NL80211_STA_INFO_TX_BYTES64)) &&
3715
	    nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES,
3716 3717
			(u32)sinfo->tx_bytes))
		goto nla_put_failure;
3718 3719 3720 3721 3722 3723 3724

	PUT_SINFO(RX_BYTES64, rx_bytes, u64);
	PUT_SINFO(TX_BYTES64, tx_bytes, u64);
	PUT_SINFO(LLID, llid, u16);
	PUT_SINFO(PLID, plid, u16);
	PUT_SINFO(PLINK_STATE, plink_state, u8);

3725 3726
	switch (rdev->wiphy.signal_type) {
	case CFG80211_SIGNAL_TYPE_MBM:
3727 3728
		PUT_SINFO(SIGNAL, signal, u8);
		PUT_SINFO(SIGNAL_AVG, signal_avg, u8);
3729 3730 3731 3732
		break;
	default:
		break;
	}
3733
	if (sinfo->filled & BIT(NL80211_STA_INFO_CHAIN_SIGNAL)) {
3734 3735 3736 3737 3738
		if (!nl80211_put_signal(msg, sinfo->chains,
					sinfo->chain_signal,
					NL80211_STA_INFO_CHAIN_SIGNAL))
			goto nla_put_failure;
	}
3739
	if (sinfo->filled & BIT(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)) {
3740 3741 3742 3743 3744
		if (!nl80211_put_signal(msg, sinfo->chains,
					sinfo->chain_signal_avg,
					NL80211_STA_INFO_CHAIN_SIGNAL_AVG))
			goto nla_put_failure;
	}
3745
	if (sinfo->filled & BIT(NL80211_STA_INFO_TX_BITRATE)) {
3746 3747 3748 3749
		if (!nl80211_put_sta_rate(msg, &sinfo->txrate,
					  NL80211_STA_INFO_TX_BITRATE))
			goto nla_put_failure;
	}
3750
	if (sinfo->filled & BIT(NL80211_STA_INFO_RX_BITRATE)) {
3751 3752
		if (!nl80211_put_sta_rate(msg, &sinfo->rxrate,
					  NL80211_STA_INFO_RX_BITRATE))
3753 3754
			goto nla_put_failure;
	}
3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766

	PUT_SINFO(RX_PACKETS, rx_packets, u32);
	PUT_SINFO(TX_PACKETS, tx_packets, u32);
	PUT_SINFO(TX_RETRIES, tx_retries, u32);
	PUT_SINFO(TX_FAILED, tx_failed, u32);
	PUT_SINFO(EXPECTED_THROUGHPUT, expected_throughput, u32);
	PUT_SINFO(BEACON_LOSS, beacon_loss_count, u32);
	PUT_SINFO(LOCAL_PM, local_pm, u32);
	PUT_SINFO(PEER_PM, peer_pm, u32);
	PUT_SINFO(NONPEER_PM, nonpeer_pm, u32);

	if (sinfo->filled & BIT(NL80211_STA_INFO_BSS_PARAM)) {
3767 3768 3769 3770
		bss_param = nla_nest_start(msg, NL80211_STA_INFO_BSS_PARAM);
		if (!bss_param)
			goto nla_put_failure;

3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781
		if (((sinfo->bss_param.flags & BSS_PARAM_FLAGS_CTS_PROT) &&
		     nla_put_flag(msg, NL80211_STA_BSS_PARAM_CTS_PROT)) ||
		    ((sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_PREAMBLE) &&
		     nla_put_flag(msg, NL80211_STA_BSS_PARAM_SHORT_PREAMBLE)) ||
		    ((sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_SLOT_TIME) &&
		     nla_put_flag(msg, NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME)) ||
		    nla_put_u8(msg, NL80211_STA_BSS_PARAM_DTIM_PERIOD,
			       sinfo->bss_param.dtim_period) ||
		    nla_put_u16(msg, NL80211_STA_BSS_PARAM_BEACON_INTERVAL,
				sinfo->bss_param.beacon_interval))
			goto nla_put_failure;
3782 3783 3784

		nla_nest_end(msg, bss_param);
	}
3785
	if ((sinfo->filled & BIT(NL80211_STA_INFO_STA_FLAGS)) &&
3786 3787 3788 3789
	    nla_put(msg, NL80211_STA_INFO_STA_FLAGS,
		    sizeof(struct nl80211_sta_flag_update),
		    &sinfo->sta_flags))
		goto nla_put_failure;
3790 3791 3792

	PUT_SINFO(T_OFFSET, t_offset, u64);
	PUT_SINFO(RX_DROP_MISC, rx_dropped_misc, u64);
3793 3794
	PUT_SINFO(BEACON_RX, rx_beacon, u64);
	PUT_SINFO(BEACON_SIGNAL_AVG, rx_beacon_signal_avg, u8);
3795 3796

#undef PUT_SINFO
3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837

	if (sinfo->filled & BIT(NL80211_STA_INFO_TID_STATS)) {
		struct nlattr *tidsattr;
		int tid;

		tidsattr = nla_nest_start(msg, NL80211_STA_INFO_TID_STATS);
		if (!tidsattr)
			goto nla_put_failure;

		for (tid = 0; tid < IEEE80211_NUM_TIDS + 1; tid++) {
			struct cfg80211_tid_stats *tidstats;
			struct nlattr *tidattr;

			tidstats = &sinfo->pertid[tid];

			if (!tidstats->filled)
				continue;

			tidattr = nla_nest_start(msg, tid + 1);
			if (!tidattr)
				goto nla_put_failure;

#define PUT_TIDVAL(attr, memb, type) do {				\
	if (tidstats->filled & BIT(NL80211_TID_STATS_ ## attr) &&	\
	    nla_put_ ## type(msg, NL80211_TID_STATS_ ## attr,		\
			     tidstats->memb))				\
		goto nla_put_failure;					\
	} while (0)

			PUT_TIDVAL(RX_MSDU, rx_msdu, u64);
			PUT_TIDVAL(TX_MSDU, tx_msdu, u64);
			PUT_TIDVAL(TX_MSDU_RETRIES, tx_msdu_retries, u64);
			PUT_TIDVAL(TX_MSDU_FAILED, tx_msdu_failed, u64);

#undef PUT_TIDVAL
			nla_nest_end(msg, tidattr);
		}

		nla_nest_end(msg, tidsattr);
	}

3838
	nla_nest_end(msg, sinfoattr);
3839

3840
	if (sinfo->assoc_req_ies_len &&
3841 3842 3843
	    nla_put(msg, NL80211_ATTR_IE, sinfo->assoc_req_ies_len,
		    sinfo->assoc_req_ies))
		goto nla_put_failure;
3844

3845 3846
	genlmsg_end(msg, hdr);
	return 0;
3847 3848

 nla_put_failure:
3849 3850
	genlmsg_cancel(msg, hdr);
	return -EMSGSIZE;
3851 3852
}

3853
static int nl80211_dump_station(struct sk_buff *skb,
Johannes Berg's avatar
Johannes Berg committed
3854
				struct netlink_callback *cb)
3855 3856
{
	struct station_info sinfo;
3857
	struct cfg80211_registered_device *rdev;
3858
	struct wireless_dev *wdev;
3859
	u8 mac_addr[ETH_ALEN];
3860
	int sta_idx = cb->args[2];
3861 3862
	int err;

3863
	err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
3864 3865
	if (err)
		return err;
Johannes Berg's avatar
Johannes Berg committed
3866

3867 3868 3869 3870 3871
	if (!wdev->netdev) {
		err = -EINVAL;
		goto out_err;
	}

3872
	if (!rdev->ops->dump_station) {
3873
		err = -EOPNOTSUPP;
Johannes Berg's avatar
Johannes Berg committed
3874 3875 3876 3877
		goto out_err;
	}

	while (1) {
3878
		memset(&sinfo, 0, sizeof(sinfo));
3879
		err = rdev_dump_station(rdev, wdev->netdev, sta_idx,
3880
					mac_addr, &sinfo);
Johannes Berg's avatar
Johannes Berg committed
3881 3882 3883
		if (err == -ENOENT)
			break;
		if (err)
Johannes Berg's avatar
Johannes Berg committed
3884
			goto out_err;
Johannes Berg's avatar
Johannes Berg committed
3885

3886
		if (nl80211_send_station(skb, NL80211_CMD_NEW_STATION,
3887
				NETLINK_CB(cb->skb).portid,
Johannes Berg's avatar
Johannes Berg committed
3888
				cb->nlh->nlmsg_seq, NLM_F_MULTI,
3889
				rdev, wdev->netdev, mac_addr,
Johannes Berg's avatar
Johannes Berg committed
3890 3891 3892 3893 3894 3895 3896 3897
				&sinfo) < 0)
			goto out;

		sta_idx++;
	}


 out:
3898
	cb->args[2] = sta_idx;
Johannes Berg's avatar
Johannes Berg committed
3899 3900
	err = skb->len;
 out_err:
3901
	nl80211_finish_wdev_dump(rdev);
Johannes Berg's avatar
Johannes Berg committed
3902 3903

	return err;
3904
}
3905

3906 3907
static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
{
3908 3909
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
3910
	struct station_info sinfo;
3911 3912
	struct sk_buff *msg;
	u8 *mac_addr = NULL;
3913
	int err;
3914

3915
	memset(&sinfo, 0, sizeof(sinfo));
3916 3917 3918 3919 3920 3921

	if (!info->attrs[NL80211_ATTR_MAC])
		return -EINVAL;

	mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);

3922 3923
	if (!rdev->ops->get_station)
		return -EOPNOTSUPP;
Johannes Berg's avatar
Johannes Berg committed
3924

3925
	err = rdev_get_station(rdev, dev, mac_addr, &sinfo);
3926
	if (err)
3927
		return err;
3928

3929
	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3930
	if (!msg)
3931
		return -ENOMEM;
3932

3933 3934
	if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION,
				 info->snd_portid, info->snd_seq, 0,
3935
				 rdev, dev, mac_addr, &sinfo) < 0) {
3936 3937 3938
		nlmsg_free(msg);
		return -ENOBUFS;
	}
Johannes Berg's avatar
Johannes Berg committed
3939

3940
	return genlmsg_reply(msg, info);
3941 3942
}

3943 3944 3945 3946 3947 3948
int cfg80211_check_station_change(struct wiphy *wiphy,
				  struct station_parameters *params,
				  enum cfg80211_station_type statype)
{
	if (params->listen_interval != -1)
		return -EINVAL;
3949 3950
	if (params->aid &&
	    !(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
3951 3952 3953 3954 3955 3956
		return -EINVAL;

	/* When you run into this, adjust the code below for the new flag */
	BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7);

	switch (statype) {
3957 3958
	case CFG80211_STA_MESH_PEER_KERNEL:
	case CFG80211_STA_MESH_PEER_USER:
3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059
		/*
		 * No ignoring the TDLS flag here -- the userspace mesh
		 * code doesn't have the bug of including TDLS in the
		 * mask everywhere.
		 */
		if (params->sta_flags_mask &
				~(BIT(NL80211_STA_FLAG_AUTHENTICATED) |
				  BIT(NL80211_STA_FLAG_MFP) |
				  BIT(NL80211_STA_FLAG_AUTHORIZED)))
			return -EINVAL;
		break;
	case CFG80211_STA_TDLS_PEER_SETUP:
	case CFG80211_STA_TDLS_PEER_ACTIVE:
		if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
			return -EINVAL;
		/* ignore since it can't change */
		params->sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
		break;
	default:
		/* disallow mesh-specific things */
		if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION)
			return -EINVAL;
		if (params->local_pm)
			return -EINVAL;
		if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE)
			return -EINVAL;
	}

	if (statype != CFG80211_STA_TDLS_PEER_SETUP &&
	    statype != CFG80211_STA_TDLS_PEER_ACTIVE) {
		/* TDLS can't be set, ... */
		if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
			return -EINVAL;
		/*
		 * ... but don't bother the driver with it. This works around
		 * a hostapd/wpa_supplicant issue -- it always includes the
		 * TLDS_PEER flag in the mask even for AP mode.
		 */
		params->sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
	}

	if (statype != CFG80211_STA_TDLS_PEER_SETUP) {
		/* reject other things that can't change */
		if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD)
			return -EINVAL;
		if (params->sta_modify_mask & STATION_PARAM_APPLY_CAPABILITY)
			return -EINVAL;
		if (params->supported_rates)
			return -EINVAL;
		if (params->ext_capab || params->ht_capa || params->vht_capa)
			return -EINVAL;
	}

	if (statype != CFG80211_STA_AP_CLIENT) {
		if (params->vlan)
			return -EINVAL;
	}

	switch (statype) {
	case CFG80211_STA_AP_MLME_CLIENT:
		/* Use this only for authorizing/unauthorizing a station */
		if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)))
			return -EOPNOTSUPP;
		break;
	case CFG80211_STA_AP_CLIENT:
		/* accept only the listed bits */
		if (params->sta_flags_mask &
				~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
				  BIT(NL80211_STA_FLAG_AUTHENTICATED) |
				  BIT(NL80211_STA_FLAG_ASSOCIATED) |
				  BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
				  BIT(NL80211_STA_FLAG_WME) |
				  BIT(NL80211_STA_FLAG_MFP)))
			return -EINVAL;

		/* but authenticated/associated only if driver handles it */
		if (!(wiphy->features & NL80211_FEATURE_FULL_AP_CLIENT_STATE) &&
		    params->sta_flags_mask &
				(BIT(NL80211_STA_FLAG_AUTHENTICATED) |
				 BIT(NL80211_STA_FLAG_ASSOCIATED)))
			return -EINVAL;
		break;
	case CFG80211_STA_IBSS:
	case CFG80211_STA_AP_STA:
		/* reject any changes other than AUTHORIZED */
		if (params->sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED))
			return -EINVAL;
		break;
	case CFG80211_STA_TDLS_PEER_SETUP:
		/* reject any changes other than AUTHORIZED or WME */
		if (params->sta_flags_mask & ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
					       BIT(NL80211_STA_FLAG_WME)))
			return -EINVAL;
		/* force (at least) rates when authorizing */
		if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED) &&
		    !params->supported_rates)
			return -EINVAL;
		break;
	case CFG80211_STA_TDLS_PEER_ACTIVE:
		/* reject any changes */
		return -EINVAL;
4060
	case CFG80211_STA_MESH_PEER_KERNEL:
4061 4062 4063
		if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE)
			return -EINVAL;
		break;
4064
	case CFG80211_STA_MESH_PEER_USER:
4065 4066
		if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION &&
		    params->plink_action != NL80211_PLINK_ACTION_BLOCK)
4067 4068 4069 4070 4071 4072 4073 4074
			return -EINVAL;
		break;
	}

	return 0;
}
EXPORT_SYMBOL(cfg80211_check_station_change);

4075
/*
4076
 * Get vlan interface making sure it is running and on the right wiphy.
4077
 */
4078 4079
static struct net_device *get_vlan(struct genl_info *info,
				   struct cfg80211_registered_device *rdev)
4080
{
4081
	struct nlattr *vlanattr = info->attrs[NL80211_ATTR_STA_VLAN];
4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094
	struct net_device *v;
	int ret;

	if (!vlanattr)
		return NULL;

	v = dev_get_by_index(genl_info_net(info), nla_get_u32(vlanattr));
	if (!v)
		return ERR_PTR(-ENODEV);

	if (!v->ieee80211_ptr || v->ieee80211_ptr->wiphy != &rdev->wiphy) {
		ret = -EINVAL;
		goto error;
4095
	}
4096

4097 4098 4099 4100 4101 4102 4103
	if (v->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
	    v->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
	    v->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
		ret = -EINVAL;
		goto error;
	}

4104 4105 4106 4107 4108 4109 4110 4111 4112
	if (!netif_running(v)) {
		ret = -ENETDOWN;
		goto error;
	}

	return v;
 error:
	dev_put(v);
	return ERR_PTR(ret);
4113 4114
}

4115 4116
static const struct nla_policy
nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] = {
4117 4118 4119 4120
	[NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 },
	[NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 },
};

4121 4122
static int nl80211_parse_sta_wme(struct genl_info *info,
				 struct station_parameters *params)
4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154
{
	struct nlattr *tb[NL80211_STA_WME_MAX + 1];
	struct nlattr *nla;
	int err;

	/* parse WME attributes if present */
	if (!info->attrs[NL80211_ATTR_STA_WME])
		return 0;

	nla = info->attrs[NL80211_ATTR_STA_WME];
	err = nla_parse_nested(tb, NL80211_STA_WME_MAX, nla,
			       nl80211_sta_wme_policy);
	if (err)
		return err;

	if (tb[NL80211_STA_WME_UAPSD_QUEUES])
		params->uapsd_queues = nla_get_u8(
			tb[NL80211_STA_WME_UAPSD_QUEUES]);
	if (params->uapsd_queues & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
		return -EINVAL;

	if (tb[NL80211_STA_WME_MAX_SP])
		params->max_sp = nla_get_u8(tb[NL80211_STA_WME_MAX_SP]);

	if (params->max_sp & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK)
		return -EINVAL;

	params->sta_modify_mask |= STATION_PARAM_APPLY_UAPSD;

	return 0;
}

4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189
static int nl80211_parse_sta_channel_info(struct genl_info *info,
				      struct station_parameters *params)
{
	if (info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]) {
		params->supported_channels =
		     nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
		params->supported_channels_len =
		     nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
		/*
		 * Need to include at least one (first channel, number of
		 * channels) tuple for each subband, and must have proper
		 * tuples for the rest of the data as well.
		 */
		if (params->supported_channels_len < 2)
			return -EINVAL;
		if (params->supported_channels_len % 2)
			return -EINVAL;
	}

	if (info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]) {
		params->supported_oper_classes =
		 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
		params->supported_oper_classes_len =
		  nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
		/*
		 * The value of the Length field of the Supported Operating
		 * Classes element is between 2 and 253.
		 */
		if (params->supported_oper_classes_len < 2 ||
		    params->supported_oper_classes_len > 253)
			return -EINVAL;
	}
	return 0;
}

4190 4191 4192
static int nl80211_set_station_tdls(struct genl_info *info,
				    struct station_parameters *params)
{
4193
	int err;
4194
	/* Dummy STA entry gets updated once the peer capabilities are known */
4195 4196
	if (info->attrs[NL80211_ATTR_PEER_AID])
		params->aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
4197 4198 4199 4200 4201 4202 4203
	if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
		params->ht_capa =
			nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
	if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
		params->vht_capa =
			nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);

4204 4205 4206 4207
	err = nl80211_parse_sta_channel_info(info, params);
	if (err)
		return err;

4208 4209 4210
	return nl80211_parse_sta_wme(info, params);
}

4211 4212
static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
{
4213 4214
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
4215
	struct station_parameters params;
4216 4217
	u8 *mac_addr;
	int err;
4218 4219 4220 4221 4222

	memset(&params, 0, sizeof(params));

	params.listen_interval = -1;

4223 4224 4225
	if (!rdev->ops->change_station)
		return -EOPNOTSUPP;

4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240
	if (info->attrs[NL80211_ATTR_STA_AID])
		return -EINVAL;

	if (!info->attrs[NL80211_ATTR_MAC])
		return -EINVAL;

	mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);

	if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) {
		params.supported_rates =
			nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
		params.supported_rates_len =
			nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
	}

4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253
	if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) {
		params.capability =
			nla_get_u16(info->attrs[NL80211_ATTR_STA_CAPABILITY]);
		params.sta_modify_mask |= STATION_PARAM_APPLY_CAPABILITY;
	}

	if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) {
		params.ext_capab =
			nla_data(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
		params.ext_capab_len =
			nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
	}

4254
	if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
4255
		return -EINVAL;
4256

4257
	if (parse_station_flags(info, dev->ieee80211_ptr->iftype, &params))
4258 4259
		return -EINVAL;

4260
	if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) {
4261
		params.plink_action =
4262 4263 4264 4265
			nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
		if (params.plink_action >= NUM_NL80211_PLINK_ACTIONS)
			return -EINVAL;
	}
4266

4267
	if (info->attrs[NL80211_ATTR_STA_PLINK_STATE]) {
4268
		params.plink_state =
4269 4270 4271 4272 4273
			nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]);
		if (params.plink_state >= NUM_NL80211_PLINK_STATES)
			return -EINVAL;
		params.sta_modify_mask |= STATION_PARAM_APPLY_PLINK_STATE;
	}
4274

4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285
	if (info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]) {
		enum nl80211_mesh_power_mode pm = nla_get_u32(
			info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]);

		if (pm <= NL80211_MESH_POWER_UNKNOWN ||
		    pm > NL80211_MESH_POWER_MAX)
			return -EINVAL;

		params.local_pm = pm;
	}

4286 4287 4288 4289 4290 4291 4292 4293 4294
	/* Include parameters for TDLS peer (will check later) */
	err = nl80211_set_station_tdls(info, &params);
	if (err)
		return err;

	params.vlan = get_vlan(info, rdev);
	if (IS_ERR(params.vlan))
		return PTR_ERR(params.vlan);

4295 4296 4297
	switch (dev->ieee80211_ptr->iftype) {
	case NL80211_IFTYPE_AP:
	case NL80211_IFTYPE_AP_VLAN:
4298 4299
	case NL80211_IFTYPE_P2P_GO:
	case NL80211_IFTYPE_P2P_CLIENT:
4300
	case NL80211_IFTYPE_STATION:
4301
	case NL80211_IFTYPE_ADHOC:
4302 4303 4304
	case NL80211_IFTYPE_MESH_POINT:
		break;
	default:
4305 4306
		err = -EOPNOTSUPP;
		goto out_put_vlan;
4307 4308
	}

4309
	/* driver will call cfg80211_check_station_change() */
4310
	err = rdev_change_station(rdev, dev, mac_addr, &params);
4311

4312
 out_put_vlan:
4313 4314
	if (params.vlan)
		dev_put(params.vlan);
Johannes Berg's avatar
Johannes Berg committed
4315

4316 4317 4318 4319 4320
	return err;
}

static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
{
4321
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
4322
	int err;
4323
	struct net_device *dev = info->user_ptr[1];
4324 4325 4326 4327 4328
	struct station_parameters params;
	u8 *mac_addr = NULL;

	memset(&params, 0, sizeof(params));

4329 4330 4331
	if (!rdev->ops->add_station)
		return -EOPNOTSUPP;

4332 4333 4334 4335 4336 4337 4338 4339 4340
	if (!info->attrs[NL80211_ATTR_MAC])
		return -EINVAL;

	if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
		return -EINVAL;

	if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
		return -EINVAL;

4341 4342
	if (!info->attrs[NL80211_ATTR_STA_AID] &&
	    !info->attrs[NL80211_ATTR_PEER_AID])
4343 4344
		return -EINVAL;

4345 4346 4347 4348 4349 4350 4351
	mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
	params.supported_rates =
		nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
	params.supported_rates_len =
		nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
	params.listen_interval =
		nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
4352

4353
	if (info->attrs[NL80211_ATTR_PEER_AID])
4354
		params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
4355 4356
	else
		params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
4357 4358
	if (!params.aid || params.aid > IEEE80211_MAX_AID)
		return -EINVAL;
4359

4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372
	if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) {
		params.capability =
			nla_get_u16(info->attrs[NL80211_ATTR_STA_CAPABILITY]);
		params.sta_modify_mask |= STATION_PARAM_APPLY_CAPABILITY;
	}

	if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) {
		params.ext_capab =
			nla_data(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
		params.ext_capab_len =
			nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
	}

4373 4374 4375
	if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
		params.ht_capa =
			nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
4376

4377 4378 4379 4380
	if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
		params.vht_capa =
			nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);

4381 4382 4383 4384 4385 4386
	if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
		params.opmode_notif_used = true;
		params.opmode_notif =
			nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
	}

4387
	if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) {
4388
		params.plink_action =
4389 4390 4391 4392
			nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
		if (params.plink_action >= NUM_NL80211_PLINK_ACTIONS)
			return -EINVAL;
	}
4393

4394 4395 4396 4397
	err = nl80211_parse_sta_channel_info(info, &params);
	if (err)
		return err;

4398 4399 4400
	err = nl80211_parse_sta_wme(info, &params);
	if (err)
		return err;
4401

4402
	if (parse_station_flags(info, dev->ieee80211_ptr->iftype, &params))
4403 4404
		return -EINVAL;

4405 4406 4407 4408 4409 4410 4411 4412 4413 4414
	/* HT/VHT requires QoS, but if we don't have that just ignore HT/VHT
	 * as userspace might just pass through the capabilities from the IEs
	 * directly, rather than enforcing this restriction and returning an
	 * error in this case.
	 */
	if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME))) {
		params.ht_capa = NULL;
		params.vht_capa = NULL;
	}

4415 4416 4417
	/* When you run into this, adjust the code below for the new flag */
	BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7);

4418 4419 4420 4421
	switch (dev->ieee80211_ptr->iftype) {
	case NL80211_IFTYPE_AP:
	case NL80211_IFTYPE_AP_VLAN:
	case NL80211_IFTYPE_P2P_GO:
4422 4423 4424 4425
		/* ignore WME attributes if iface/sta is not capable */
		if (!(rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) ||
		    !(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME)))
			params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
4426

4427
		/* TDLS peers cannot be added */
4428 4429
		if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) ||
		    info->attrs[NL80211_ATTR_PEER_AID])
4430
			return -EINVAL;
4431 4432
		/* but don't bother the driver with it */
		params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
4433

4434 4435 4436 4437 4438 4439 4440 4441
		/* allow authenticated/associated only if driver handles it */
		if (!(rdev->wiphy.features &
				NL80211_FEATURE_FULL_AP_CLIENT_STATE) &&
		    params.sta_flags_mask &
				(BIT(NL80211_STA_FLAG_AUTHENTICATED) |
				 BIT(NL80211_STA_FLAG_ASSOCIATED)))
			return -EINVAL;

4442 4443 4444 4445 4446 4447
		/* must be last in here for error handling */
		params.vlan = get_vlan(info, rdev);
		if (IS_ERR(params.vlan))
			return PTR_ERR(params.vlan);
		break;
	case NL80211_IFTYPE_MESH_POINT:
4448 4449 4450
		/* ignore uAPSD data */
		params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;

4451 4452 4453
		/* associated is disallowed */
		if (params.sta_flags_mask & BIT(NL80211_STA_FLAG_ASSOCIATED))
			return -EINVAL;
4454
		/* TDLS peers cannot be added */
4455 4456
		if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) ||
		    info->attrs[NL80211_ATTR_PEER_AID])
4457 4458 4459
			return -EINVAL;
		break;
	case NL80211_IFTYPE_STATION:
4460
	case NL80211_IFTYPE_P2P_CLIENT:
4461 4462 4463
		/* ignore uAPSD data */
		params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;

4464 4465 4466 4467
		/* these are disallowed */
		if (params.sta_flags_mask &
				(BIT(NL80211_STA_FLAG_ASSOCIATED) |
				 BIT(NL80211_STA_FLAG_AUTHENTICATED)))
4468
			return -EINVAL;
4469 4470 4471 4472 4473 4474 4475 4476 4477
		/* Only TDLS peers can be added */
		if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
			return -EINVAL;
		/* Can only add if TDLS ... */
		if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS))
			return -EOPNOTSUPP;
		/* ... with external setup is supported */
		if (!(rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP))
			return -EOPNOTSUPP;
4478 4479 4480 4481 4482
		/*
		 * Older wpa_supplicant versions always mark the TDLS peer
		 * as authorized, but it shouldn't yet be.
		 */
		params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_AUTHORIZED);
4483 4484 4485
		break;
	default:
		return -EOPNOTSUPP;
4486 4487
	}

4488
	/* be aware of params.vlan when changing code here */
4489

4490
	err = rdev_add_station(rdev, dev, mac_addr, &params);
4491 4492 4493 4494 4495 4496 4497 4498

	if (params.vlan)
		dev_put(params.vlan);
	return err;
}

static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
{
4499 4500
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
4501 4502 4503
	struct station_del_parameters params;

	memset(&params, 0, sizeof(params));
4504 4505

	if (info->attrs[NL80211_ATTR_MAC])
4506
		params.mac = nla_data(info->attrs[NL80211_ATTR_MAC]);
4507

4508
	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
4509
	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
4510
	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT &&
4511 4512
	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
		return -EINVAL;
4513

4514 4515
	if (!rdev->ops->del_station)
		return -EOPNOTSUPP;
Johannes Berg's avatar
Johannes Berg committed
4516

4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537
	if (info->attrs[NL80211_ATTR_MGMT_SUBTYPE]) {
		params.subtype =
			nla_get_u8(info->attrs[NL80211_ATTR_MGMT_SUBTYPE]);
		if (params.subtype != IEEE80211_STYPE_DISASSOC >> 4 &&
		    params.subtype != IEEE80211_STYPE_DEAUTH >> 4)
			return -EINVAL;
	} else {
		/* Default to Deauthentication frame */
		params.subtype = IEEE80211_STYPE_DEAUTH >> 4;
	}

	if (info->attrs[NL80211_ATTR_REASON_CODE]) {
		params.reason_code =
			nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
		if (params.reason_code == 0)
			return -EINVAL; /* 0 is reserved */
	} else {
		/* Default to reason code 2 */
		params.reason_code = WLAN_REASON_PREV_AUTH_NOT_VALID;
	}

4538
	return rdev_del_station(rdev, dev, &params);
4539 4540
}

4541
static int nl80211_send_mpath(struct sk_buff *msg, u32 portid, u32 seq,
4542 4543 4544 4545 4546 4547 4548
				int flags, struct net_device *dev,
				u8 *dst, u8 *next_hop,
				struct mpath_info *pinfo)
{
	void *hdr;
	struct nlattr *pinfoattr;

4549
	hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_MPATH);
4550 4551 4552
	if (!hdr)
		return -1;

4553 4554 4555 4556 4557
	if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
	    nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, dst) ||
	    nla_put(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop) ||
	    nla_put_u32(msg, NL80211_ATTR_GENERATION, pinfo->generation))
		goto nla_put_failure;
4558

4559 4560 4561
	pinfoattr = nla_nest_start(msg, NL80211_ATTR_MPATH_INFO);
	if (!pinfoattr)
		goto nla_put_failure;
4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583
	if ((pinfo->filled & MPATH_INFO_FRAME_QLEN) &&
	    nla_put_u32(msg, NL80211_MPATH_INFO_FRAME_QLEN,
			pinfo->frame_qlen))
		goto nla_put_failure;
	if (((pinfo->filled & MPATH_INFO_SN) &&
	     nla_put_u32(msg, NL80211_MPATH_INFO_SN, pinfo->sn)) ||
	    ((pinfo->filled & MPATH_INFO_METRIC) &&
	     nla_put_u32(msg, NL80211_MPATH_INFO_METRIC,
			 pinfo->metric)) ||
	    ((pinfo->filled & MPATH_INFO_EXPTIME) &&
	     nla_put_u32(msg, NL80211_MPATH_INFO_EXPTIME,
			 pinfo->exptime)) ||
	    ((pinfo->filled & MPATH_INFO_FLAGS) &&
	     nla_put_u8(msg, NL80211_MPATH_INFO_FLAGS,
			pinfo->flags)) ||
	    ((pinfo->filled & MPATH_INFO_DISCOVERY_TIMEOUT) &&
	     nla_put_u32(msg, NL80211_MPATH_INFO_DISCOVERY_TIMEOUT,
			 pinfo->discovery_timeout)) ||
	    ((pinfo->filled & MPATH_INFO_DISCOVERY_RETRIES) &&
	     nla_put_u8(msg, NL80211_MPATH_INFO_DISCOVERY_RETRIES,
			pinfo->discovery_retries)))
		goto nla_put_failure;
4584 4585 4586

	nla_nest_end(msg, pinfoattr);

4587 4588
	genlmsg_end(msg, hdr);
	return 0;
4589 4590

 nla_put_failure:
4591 4592
	genlmsg_cancel(msg, hdr);
	return -EMSGSIZE;
4593 4594 4595
}

static int nl80211_dump_mpath(struct sk_buff *skb,
Johannes Berg's avatar
Johannes Berg committed
4596
			      struct netlink_callback *cb)
4597 4598
{
	struct mpath_info pinfo;
4599
	struct cfg80211_registered_device *rdev;
4600
	struct wireless_dev *wdev;
4601 4602
	u8 dst[ETH_ALEN];
	u8 next_hop[ETH_ALEN];
4603
	int path_idx = cb->args[2];
4604 4605
	int err;

4606
	err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
4607 4608
	if (err)
		return err;
Johannes Berg's avatar
Johannes Berg committed
4609

4610
	if (!rdev->ops->dump_mpath) {
4611
		err = -EOPNOTSUPP;
Johannes Berg's avatar
Johannes Berg committed
4612 4613 4614
		goto out_err;
	}

4615
	if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) {
4616
		err = -EOPNOTSUPP;
4617
		goto out_err;
4618 4619
	}

Johannes Berg's avatar
Johannes Berg committed
4620
	while (1) {
4621
		err = rdev_dump_mpath(rdev, wdev->netdev, path_idx, dst,
4622
				      next_hop, &pinfo);
Johannes Berg's avatar
Johannes Berg committed
4623
		if (err == -ENOENT)
4624
			break;
Johannes Berg's avatar
Johannes Berg committed
4625
		if (err)
Johannes Berg's avatar
Johannes Berg committed
4626
			goto out_err;
4627

4628
		if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).portid,
Johannes Berg's avatar
Johannes Berg committed
4629
				       cb->nlh->nlmsg_seq, NLM_F_MULTI,
4630
				       wdev->netdev, dst, next_hop,
Johannes Berg's avatar
Johannes Berg committed
4631 4632
				       &pinfo) < 0)
			goto out;
4633

Johannes Berg's avatar
Johannes Berg committed
4634
		path_idx++;
4635 4636 4637
	}


Johannes Berg's avatar
Johannes Berg committed
4638
 out:
4639
	cb->args[2] = path_idx;
Johannes Berg's avatar
Johannes Berg committed
4640 4641
	err = skb->len;
 out_err:
4642
	nl80211_finish_wdev_dump(rdev);
Johannes Berg's avatar
Johannes Berg committed
4643
	return err;
4644 4645 4646 4647
}

static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
{
4648
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
4649
	int err;
4650
	struct net_device *dev = info->user_ptr[1];
4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662
	struct mpath_info pinfo;
	struct sk_buff *msg;
	u8 *dst = NULL;
	u8 next_hop[ETH_ALEN];

	memset(&pinfo, 0, sizeof(pinfo));

	if (!info->attrs[NL80211_ATTR_MAC])
		return -EINVAL;

	dst = nla_data(info->attrs[NL80211_ATTR_MAC]);

4663 4664
	if (!rdev->ops->get_mpath)
		return -EOPNOTSUPP;
4665

4666 4667
	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
		return -EOPNOTSUPP;
4668

4669
	err = rdev_get_mpath(rdev, dev, dst, next_hop, &pinfo);
4670
	if (err)
4671
		return err;
4672

4673
	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4674
	if (!msg)
4675
		return -ENOMEM;
4676

4677
	if (nl80211_send_mpath(msg, info->snd_portid, info->snd_seq, 0,
4678 4679 4680 4681
				 dev, dst, next_hop, &pinfo) < 0) {
		nlmsg_free(msg);
		return -ENOBUFS;
	}
Johannes Berg's avatar
Johannes Berg committed
4682

4683
	return genlmsg_reply(msg, info);
4684 4685 4686 4687
}

static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
{
4688 4689
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701
	u8 *dst = NULL;
	u8 *next_hop = NULL;

	if (!info->attrs[NL80211_ATTR_MAC])
		return -EINVAL;

	if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
		return -EINVAL;

	dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
	next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);

4702 4703
	if (!rdev->ops->change_mpath)
		return -EOPNOTSUPP;
4704

4705 4706
	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
		return -EOPNOTSUPP;
4707

4708
	return rdev_change_mpath(rdev, dev, dst, next_hop);
4709
}
4710

4711 4712
static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
{
4713 4714
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726
	u8 *dst = NULL;
	u8 *next_hop = NULL;

	if (!info->attrs[NL80211_ATTR_MAC])
		return -EINVAL;

	if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
		return -EINVAL;

	dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
	next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);

4727 4728
	if (!rdev->ops->add_mpath)
		return -EOPNOTSUPP;
4729

4730 4731
	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
		return -EOPNOTSUPP;
4732

4733
	return rdev_add_mpath(rdev, dev, dst, next_hop);
4734 4735 4736 4737
}

static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
{
4738 4739
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
4740 4741 4742 4743 4744
	u8 *dst = NULL;

	if (info->attrs[NL80211_ATTR_MAC])
		dst = nla_data(info->attrs[NL80211_ATTR_MAC]);

4745 4746
	if (!rdev->ops->del_mpath)
		return -EOPNOTSUPP;
Johannes Berg's avatar
Johannes Berg committed
4747

4748
	return rdev_del_mpath(rdev, dev, dst);
4749 4750
}

4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840
static int nl80211_get_mpp(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	int err;
	struct net_device *dev = info->user_ptr[1];
	struct mpath_info pinfo;
	struct sk_buff *msg;
	u8 *dst = NULL;
	u8 mpp[ETH_ALEN];

	memset(&pinfo, 0, sizeof(pinfo));

	if (!info->attrs[NL80211_ATTR_MAC])
		return -EINVAL;

	dst = nla_data(info->attrs[NL80211_ATTR_MAC]);

	if (!rdev->ops->get_mpp)
		return -EOPNOTSUPP;

	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
		return -EOPNOTSUPP;

	err = rdev_get_mpp(rdev, dev, dst, mpp, &pinfo);
	if (err)
		return err;

	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
	if (!msg)
		return -ENOMEM;

	if (nl80211_send_mpath(msg, info->snd_portid, info->snd_seq, 0,
			       dev, dst, mpp, &pinfo) < 0) {
		nlmsg_free(msg);
		return -ENOBUFS;
	}

	return genlmsg_reply(msg, info);
}

static int nl80211_dump_mpp(struct sk_buff *skb,
			    struct netlink_callback *cb)
{
	struct mpath_info pinfo;
	struct cfg80211_registered_device *rdev;
	struct wireless_dev *wdev;
	u8 dst[ETH_ALEN];
	u8 mpp[ETH_ALEN];
	int path_idx = cb->args[2];
	int err;

	err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
	if (err)
		return err;

	if (!rdev->ops->dump_mpp) {
		err = -EOPNOTSUPP;
		goto out_err;
	}

	if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) {
		err = -EOPNOTSUPP;
		goto out_err;
	}

	while (1) {
		err = rdev_dump_mpp(rdev, wdev->netdev, path_idx, dst,
				    mpp, &pinfo);
		if (err == -ENOENT)
			break;
		if (err)
			goto out_err;

		if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).portid,
				       cb->nlh->nlmsg_seq, NLM_F_MULTI,
				       wdev->netdev, dst, mpp,
				       &pinfo) < 0)
			goto out;

		path_idx++;
	}

 out:
	cb->args[2] = path_idx;
	err = skb->len;
 out_err:
	nl80211_finish_wdev_dump(rdev);
	return err;
}

4841 4842
static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
{
4843 4844
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
4845
	struct wireless_dev *wdev = dev->ieee80211_ptr;
4846
	struct bss_parameters params;
4847
	int err;
4848 4849 4850 4851 4852 4853

	memset(&params, 0, sizeof(params));
	/* default to not changing parameters */
	params.use_cts_prot = -1;
	params.use_short_preamble = -1;
	params.use_short_slot_time = -1;
4854
	params.ap_isolate = -1;
4855
	params.ht_opmode = -1;
4856 4857
	params.p2p_ctwindow = -1;
	params.p2p_opp_ps = -1;
4858 4859 4860 4861 4862 4863 4864 4865 4866 4867

	if (info->attrs[NL80211_ATTR_BSS_CTS_PROT])
		params.use_cts_prot =
		    nla_get_u8(info->attrs[NL80211_ATTR_BSS_CTS_PROT]);
	if (info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE])
		params.use_short_preamble =
		    nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE]);
	if (info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME])
		params.use_short_slot_time =
		    nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]);
4868 4869 4870 4871 4872 4873
	if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
		params.basic_rates =
			nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
		params.basic_rates_len =
			nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
	}
4874 4875
	if (info->attrs[NL80211_ATTR_AP_ISOLATE])
		params.ap_isolate = !!nla_get_u8(info->attrs[NL80211_ATTR_AP_ISOLATE]);
4876 4877 4878
	if (info->attrs[NL80211_ATTR_BSS_HT_OPMODE])
		params.ht_opmode =
			nla_get_u16(info->attrs[NL80211_ATTR_BSS_HT_OPMODE]);
4879

4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905
	if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
		if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
			return -EINVAL;
		params.p2p_ctwindow =
			nla_get_s8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
		if (params.p2p_ctwindow < 0)
			return -EINVAL;
		if (params.p2p_ctwindow != 0 &&
		    !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
			return -EINVAL;
	}

	if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
		u8 tmp;

		if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
			return -EINVAL;
		tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
		if (tmp > 1)
			return -EINVAL;
		params.p2p_opp_ps = tmp;
		if (params.p2p_opp_ps &&
		    !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))
			return -EINVAL;
	}

4906 4907
	if (!rdev->ops->change_bss)
		return -EOPNOTSUPP;
4908

4909
	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
4910 4911
	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
		return -EOPNOTSUPP;
Johannes Berg's avatar
Johannes Berg committed
4912

4913 4914 4915 4916 4917
	wdev_lock(wdev);
	err = rdev_change_bss(rdev, dev, &params);
	wdev_unlock(wdev);

	return err;
4918 4919
}

Alexey Dobriyan's avatar
Alexey Dobriyan committed
4920
static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = {
4921 4922 4923 4924 4925 4926
	[NL80211_ATTR_REG_RULE_FLAGS]		= { .type = NLA_U32 },
	[NL80211_ATTR_FREQ_RANGE_START]		= { .type = NLA_U32 },
	[NL80211_ATTR_FREQ_RANGE_END]		= { .type = NLA_U32 },
	[NL80211_ATTR_FREQ_RANGE_MAX_BW]	= { .type = NLA_U32 },
	[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]	= { .type = NLA_U32 },
	[NL80211_ATTR_POWER_RULE_MAX_EIRP]	= { .type = NLA_U32 },
4927
	[NL80211_ATTR_DFS_CAC_TIME]		= { .type = NLA_U32 },
4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941
};

static int parse_reg_rule(struct nlattr *tb[],
	struct ieee80211_reg_rule *reg_rule)
{
	struct ieee80211_freq_range *freq_range = &reg_rule->freq_range;
	struct ieee80211_power_rule *power_rule = &reg_rule->power_rule;

	if (!tb[NL80211_ATTR_REG_RULE_FLAGS])
		return -EINVAL;
	if (!tb[NL80211_ATTR_FREQ_RANGE_START])
		return -EINVAL;
	if (!tb[NL80211_ATTR_FREQ_RANGE_END])
		return -EINVAL;
4942 4943
	if (!tb[NL80211_ATTR_FREQ_RANGE_MAX_BW])
		return -EINVAL;
4944 4945 4946 4947 4948 4949 4950 4951 4952
	if (!tb[NL80211_ATTR_POWER_RULE_MAX_EIRP])
		return -EINVAL;

	reg_rule->flags = nla_get_u32(tb[NL80211_ATTR_REG_RULE_FLAGS]);

	freq_range->start_freq_khz =
		nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]);
	freq_range->end_freq_khz =
		nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]);
4953 4954
	freq_range->max_bandwidth_khz =
		nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]);
4955 4956 4957 4958 4959 4960 4961 4962

	power_rule->max_eirp =
		nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]);

	if (tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN])
		power_rule->max_antenna_gain =
			nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]);

4963 4964 4965 4966
	if (tb[NL80211_ATTR_DFS_CAC_TIME])
		reg_rule->dfs_cac_ms =
			nla_get_u32(tb[NL80211_ATTR_DFS_CAC_TIME]);

4967 4968 4969 4970 4971 4972
	return 0;
}

static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
{
	char *data = NULL;
4973
	bool is_indoor;
4974
	enum nl80211_user_reg_hint_type user_reg_hint_type;
4975 4976
	u32 owner_nlportid;

4977

4978 4979 4980 4981 4982 4983
	/*
	 * You should only get this when cfg80211 hasn't yet initialized
	 * completely when built-in to the kernel right between the time
	 * window between nl80211_init() and regulatory_init(), if that is
	 * even possible.
	 */
4984
	if (unlikely(!rcu_access_pointer(cfg80211_regdomain)))
4985
		return -EINPROGRESS;
4986

4987 4988 4989 4990 4991 4992 4993 4994 4995
	if (info->attrs[NL80211_ATTR_USER_REG_HINT_TYPE])
		user_reg_hint_type =
		  nla_get_u32(info->attrs[NL80211_ATTR_USER_REG_HINT_TYPE]);
	else
		user_reg_hint_type = NL80211_USER_REG_HINT_USER;

	switch (user_reg_hint_type) {
	case NL80211_USER_REG_HINT_USER:
	case NL80211_USER_REG_HINT_CELL_BASE:
4996 4997 4998 4999 5000 5001
		if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
			return -EINVAL;

		data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
		return regulatory_hint_user(data, user_reg_hint_type);
	case NL80211_USER_REG_HINT_INDOOR:
5002 5003 5004 5005 5006 5007 5008 5009 5010
		if (info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
			owner_nlportid = info->snd_portid;
			is_indoor = !!info->attrs[NL80211_ATTR_REG_INDOOR];
		} else {
			owner_nlportid = 0;
			is_indoor = true;
		}

		return regulatory_hint_indoor(is_indoor, owner_nlportid);
5011 5012 5013
	default:
		return -EINVAL;
	}
5014 5015
}

5016
static int nl80211_get_mesh_config(struct sk_buff *skb,
5017
				   struct genl_info *info)
5018
{
5019 5020
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
5021 5022 5023
	struct wireless_dev *wdev = dev->ieee80211_ptr;
	struct mesh_config cur_params;
	int err = 0;
5024 5025 5026 5027
	void *hdr;
	struct nlattr *pinfoattr;
	struct sk_buff *msg;

5028 5029 5030
	if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
		return -EOPNOTSUPP;

5031
	if (!rdev->ops->get_mesh_config)
5032
		return -EOPNOTSUPP;
5033

5034 5035 5036 5037 5038
	wdev_lock(wdev);
	/* If not connected, get default parameters */
	if (!wdev->mesh_id_len)
		memcpy(&cur_params, &default_mesh_config, sizeof(cur_params));
	else
5039
		err = rdev_get_mesh_config(rdev, dev, &cur_params);
5040 5041
	wdev_unlock(wdev);

5042
	if (err)
5043
		return err;
5044 5045

	/* Draw up a netlink message to send back */
5046
	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
5047 5048
	if (!msg)
		return -ENOMEM;
5049
	hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
5050
			     NL80211_CMD_GET_MESH_CONFIG);
5051
	if (!hdr)
5052
		goto out;
5053
	pinfoattr = nla_nest_start(msg, NL80211_ATTR_MESH_CONFIG);
5054 5055
	if (!pinfoattr)
		goto nla_put_failure;
5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072
	if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
	    nla_put_u16(msg, NL80211_MESHCONF_RETRY_TIMEOUT,
			cur_params.dot11MeshRetryTimeout) ||
	    nla_put_u16(msg, NL80211_MESHCONF_CONFIRM_TIMEOUT,
			cur_params.dot11MeshConfirmTimeout) ||
	    nla_put_u16(msg, NL80211_MESHCONF_HOLDING_TIMEOUT,
			cur_params.dot11MeshHoldingTimeout) ||
	    nla_put_u16(msg, NL80211_MESHCONF_MAX_PEER_LINKS,
			cur_params.dot11MeshMaxPeerLinks) ||
	    nla_put_u8(msg, NL80211_MESHCONF_MAX_RETRIES,
		       cur_params.dot11MeshMaxRetries) ||
	    nla_put_u8(msg, NL80211_MESHCONF_TTL,
		       cur_params.dot11MeshTTL) ||
	    nla_put_u8(msg, NL80211_MESHCONF_ELEMENT_TTL,
		       cur_params.element_ttl) ||
	    nla_put_u8(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS,
		       cur_params.auto_open_plinks) ||
5073 5074
	    nla_put_u32(msg, NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
			cur_params.dot11MeshNbrOffsetMaxNeighbor) ||
5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097
	    nla_put_u8(msg, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
		       cur_params.dot11MeshHWMPmaxPREQretries) ||
	    nla_put_u32(msg, NL80211_MESHCONF_PATH_REFRESH_TIME,
			cur_params.path_refresh_time) ||
	    nla_put_u16(msg, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
			cur_params.min_discovery_timeout) ||
	    nla_put_u32(msg, NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
			cur_params.dot11MeshHWMPactivePathTimeout) ||
	    nla_put_u16(msg, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
			cur_params.dot11MeshHWMPpreqMinInterval) ||
	    nla_put_u16(msg, NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
			cur_params.dot11MeshHWMPperrMinInterval) ||
	    nla_put_u16(msg, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
			cur_params.dot11MeshHWMPnetDiameterTraversalTime) ||
	    nla_put_u8(msg, NL80211_MESHCONF_HWMP_ROOTMODE,
		       cur_params.dot11MeshHWMPRootMode) ||
	    nla_put_u16(msg, NL80211_MESHCONF_HWMP_RANN_INTERVAL,
			cur_params.dot11MeshHWMPRannInterval) ||
	    nla_put_u8(msg, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
		       cur_params.dot11MeshGateAnnouncementProtocol) ||
	    nla_put_u8(msg, NL80211_MESHCONF_FORWARDING,
		       cur_params.dot11MeshForwarding) ||
	    nla_put_u32(msg, NL80211_MESHCONF_RSSI_THRESHOLD,
5098 5099
			cur_params.rssi_threshold) ||
	    nla_put_u32(msg, NL80211_MESHCONF_HT_OPMODE,
5100 5101 5102 5103
			cur_params.ht_opmode) ||
	    nla_put_u32(msg, NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
			cur_params.dot11MeshHWMPactivePathToRootTimeout) ||
	    nla_put_u16(msg, NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
5104 5105
			cur_params.dot11MeshHWMProotInterval) ||
	    nla_put_u16(msg, NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
5106 5107 5108 5109
			cur_params.dot11MeshHWMPconfirmationInterval) ||
	    nla_put_u32(msg, NL80211_MESHCONF_POWER_MODE,
			cur_params.power_mode) ||
	    nla_put_u16(msg, NL80211_MESHCONF_AWAKE_WINDOW,
5110 5111 5112
			cur_params.dot11MeshAwakeWindowDuration) ||
	    nla_put_u32(msg, NL80211_MESHCONF_PLINK_TIMEOUT,
			cur_params.plink_timeout))
5113
		goto nla_put_failure;
5114 5115
	nla_nest_end(msg, pinfoattr);
	genlmsg_end(msg, hdr);
5116
	return genlmsg_reply(msg, info);
5117

Johannes Berg's avatar
Johannes Berg committed
5118
 nla_put_failure:
5119
	genlmsg_cancel(msg, hdr);
5120
 out:
Yuri Ershov's avatar
Yuri Ershov committed
5121
	nlmsg_free(msg);
5122
	return -ENOBUFS;
5123 5124
}

Alexey Dobriyan's avatar
Alexey Dobriyan committed
5125
static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] = {
5126 5127 5128 5129 5130 5131
	[NL80211_MESHCONF_RETRY_TIMEOUT] = { .type = NLA_U16 },
	[NL80211_MESHCONF_CONFIRM_TIMEOUT] = { .type = NLA_U16 },
	[NL80211_MESHCONF_HOLDING_TIMEOUT] = { .type = NLA_U16 },
	[NL80211_MESHCONF_MAX_PEER_LINKS] = { .type = NLA_U16 },
	[NL80211_MESHCONF_MAX_RETRIES] = { .type = NLA_U8 },
	[NL80211_MESHCONF_TTL] = { .type = NLA_U8 },
5132
	[NL80211_MESHCONF_ELEMENT_TTL] = { .type = NLA_U8 },
5133
	[NL80211_MESHCONF_AUTO_OPEN_PLINKS] = { .type = NLA_U8 },
5134
	[NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR] = { .type = NLA_U32 },
5135 5136 5137 5138 5139
	[NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 },
	[NL80211_MESHCONF_PATH_REFRESH_TIME] = { .type = NLA_U32 },
	[NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT] = { .type = NLA_U16 },
	[NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 },
	[NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] = { .type = NLA_U16 },
5140
	[NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL] = { .type = NLA_U16 },
5141
	[NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 },
5142
	[NL80211_MESHCONF_HWMP_ROOTMODE] = { .type = NLA_U8 },
5143
	[NL80211_MESHCONF_HWMP_RANN_INTERVAL] = { .type = NLA_U16 },
5144
	[NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = { .type = NLA_U8 },
5145
	[NL80211_MESHCONF_FORWARDING] = { .type = NLA_U8 },
5146 5147
	[NL80211_MESHCONF_RSSI_THRESHOLD] = { .type = NLA_U32 },
	[NL80211_MESHCONF_HT_OPMODE] = { .type = NLA_U16 },
5148 5149
	[NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT] = { .type = NLA_U32 },
	[NL80211_MESHCONF_HWMP_ROOT_INTERVAL] = { .type = NLA_U16 },
5150
	[NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL] = { .type = NLA_U16 },
5151 5152
	[NL80211_MESHCONF_POWER_MODE] = { .type = NLA_U32 },
	[NL80211_MESHCONF_AWAKE_WINDOW] = { .type = NLA_U16 },
5153
	[NL80211_MESHCONF_PLINK_TIMEOUT] = { .type = NLA_U32 },
5154 5155
};

5156 5157
static const struct nla_policy
	nl80211_mesh_setup_params_policy[NL80211_MESH_SETUP_ATTR_MAX+1] = {
5158
	[NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC] = { .type = NLA_U8 },
5159 5160
	[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 },
	[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 },
5161
	[NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG },
5162
	[NL80211_MESH_SETUP_AUTH_PROTOCOL] = { .type = NLA_U8 },
5163
	[NL80211_MESH_SETUP_USERSPACE_MPM] = { .type = NLA_FLAG },
5164
	[NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY,
5165
				    .len = IEEE80211_MAX_DATA_LEN },
5166
	[NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG },
5167 5168
};

5169
static int nl80211_parse_mesh_config(struct genl_info *info,
5170 5171
				     struct mesh_config *cfg,
				     u32 *mask_out)
5172 5173
{
	struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1];
5174
	u32 mask = 0;
5175

5176 5177 5178 5179 5180 5181 5182 5183 5184
#define FILL_IN_MESH_PARAM_IF_SET(tb, cfg, param, min, max, mask, attr, fn) \
do {									    \
	if (tb[attr]) {							    \
		if (fn(tb[attr]) < min || fn(tb[attr]) > max)		    \
			return -EINVAL;					    \
		cfg->param = fn(tb[attr]);				    \
		mask |= (1 << (attr - 1));				    \
	}								    \
} while (0)
5185 5186


5187
	if (!info->attrs[NL80211_ATTR_MESH_CONFIG])
5188 5189
		return -EINVAL;
	if (nla_parse_nested(tb, NL80211_MESHCONF_ATTR_MAX,
5190
			     info->attrs[NL80211_ATTR_MESH_CONFIG],
5191
			     nl80211_meshconf_params_policy))
5192 5193 5194 5195 5196 5197 5198
		return -EINVAL;

	/* This makes sure that there aren't more than 32 mesh config
	 * parameters (otherwise our bitfield scheme would not work.) */
	BUILD_BUG_ON(NL80211_MESHCONF_ATTR_MAX > 32);

	/* Fill in the params struct */
5199
	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, 1, 255,
5200 5201
				  mask, NL80211_MESHCONF_RETRY_TIMEOUT,
				  nla_get_u16);
5202
	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, 1, 255,
5203 5204
				  mask, NL80211_MESHCONF_CONFIRM_TIMEOUT,
				  nla_get_u16);
5205
	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, 1, 255,
5206 5207
				  mask, NL80211_MESHCONF_HOLDING_TIMEOUT,
				  nla_get_u16);
5208
	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, 0, 255,
5209 5210
				  mask, NL80211_MESHCONF_MAX_PEER_LINKS,
				  nla_get_u16);
5211
	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, 0, 16,
5212 5213
				  mask, NL80211_MESHCONF_MAX_RETRIES,
				  nla_get_u8);
5214
	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, 1, 255,
5215
				  mask, NL80211_MESHCONF_TTL, nla_get_u8);
5216
	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, element_ttl, 1, 255,
5217 5218
				  mask, NL80211_MESHCONF_ELEMENT_TTL,
				  nla_get_u8);
5219
	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, 0, 1,
5220 5221
				  mask, NL80211_MESHCONF_AUTO_OPEN_PLINKS,
				  nla_get_u8);
5222 5223
	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNbrOffsetMaxNeighbor,
				  1, 255, mask,
5224 5225
				  NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
				  nla_get_u32);
5226
	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, 0, 255,
5227 5228
				  mask, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
				  nla_get_u8);
5229
	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, 1, 65535,
5230 5231
				  mask, NL80211_MESHCONF_PATH_REFRESH_TIME,
				  nla_get_u32);
5232
	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout, 1, 65535,
5233 5234
				  mask, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
				  nla_get_u16);
5235 5236
	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout,
				  1, 65535, mask,
5237 5238
				  NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
				  nla_get_u32);
5239
	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval,
5240 5241
				  1, 65535, mask,
				  NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
5242
				  nla_get_u16);
5243
	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPperrMinInterval,
5244 5245
				  1, 65535, mask,
				  NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
5246
				  nla_get_u16);
5247
	FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
5248 5249
				  dot11MeshHWMPnetDiameterTraversalTime,
				  1, 65535, mask,
5250 5251
				  NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
				  nla_get_u16);
5252 5253 5254 5255 5256
	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRootMode, 0, 4,
				  mask, NL80211_MESHCONF_HWMP_ROOTMODE,
				  nla_get_u8);
	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRannInterval, 1, 65535,
				  mask, NL80211_MESHCONF_HWMP_RANN_INTERVAL,
5257
				  nla_get_u16);
5258
	FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
5259 5260
				  dot11MeshGateAnnouncementProtocol, 0, 1,
				  mask, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
5261
				  nla_get_u8);
5262
	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, 0, 1,
5263 5264
				  mask, NL80211_MESHCONF_FORWARDING,
				  nla_get_u8);
5265
	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, -255, 0,
5266
				  mask, NL80211_MESHCONF_RSSI_THRESHOLD,
5267
				  nla_get_s32);
5268
	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, ht_opmode, 0, 16,
5269
				  mask, NL80211_MESHCONF_HT_OPMODE,
5270 5271
				  nla_get_u16);
	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathToRootTimeout,
5272
				  1, 65535, mask,
5273 5274
				  NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
				  nla_get_u32);
5275
	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMProotInterval, 1, 65535,
5276
				  mask, NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
5277 5278
				  nla_get_u16);
	FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
5279 5280
				  dot11MeshHWMPconfirmationInterval,
				  1, 65535, mask,
5281
				  NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
5282
				  nla_get_u16);
5283 5284 5285 5286 5287 5288 5289 5290
	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, power_mode,
				  NL80211_MESH_POWER_ACTIVE,
				  NL80211_MESH_POWER_MAX,
				  mask, NL80211_MESHCONF_POWER_MODE,
				  nla_get_u32);
	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration,
				  0, 65535, mask,
				  NL80211_MESHCONF_AWAKE_WINDOW, nla_get_u16);
5291
	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, plink_timeout, 0, 0xffffffff,
5292 5293
				  mask, NL80211_MESHCONF_PLINK_TIMEOUT,
				  nla_get_u32);
5294 5295
	if (mask_out)
		*mask_out = mask;
5296

5297 5298 5299 5300 5301
	return 0;

#undef FILL_IN_MESH_PARAM_IF_SET
}

5302 5303 5304
static int nl80211_parse_mesh_setup(struct genl_info *info,
				     struct mesh_setup *setup)
{
5305
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
5306 5307 5308 5309 5310 5311 5312 5313 5314
	struct nlattr *tb[NL80211_MESH_SETUP_ATTR_MAX + 1];

	if (!info->attrs[NL80211_ATTR_MESH_SETUP])
		return -EINVAL;
	if (nla_parse_nested(tb, NL80211_MESH_SETUP_ATTR_MAX,
			     info->attrs[NL80211_ATTR_MESH_SETUP],
			     nl80211_mesh_setup_params_policy))
		return -EINVAL;

5315 5316 5317 5318 5319 5320
	if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC])
		setup->sync_method =
		(nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC])) ?
		 IEEE80211_SYNC_METHOD_VENDOR :
		 IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET;

5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332
	if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL])
		setup->path_sel_proto =
		(nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL])) ?
		 IEEE80211_PATH_PROTOCOL_VENDOR :
		 IEEE80211_PATH_PROTOCOL_HWMP;

	if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC])
		setup->path_metric =
		(nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC])) ?
		 IEEE80211_PATH_METRIC_VENDOR :
		 IEEE80211_PATH_METRIC_AIRTIME;

5333 5334

	if (tb[NL80211_MESH_SETUP_IE]) {
5335
		struct nlattr *ieattr =
5336
			tb[NL80211_MESH_SETUP_IE];
5337 5338
		if (!is_valid_ie_attr(ieattr))
			return -EINVAL;
5339 5340
		setup->ie = nla_data(ieattr);
		setup->ie_len = nla_len(ieattr);
5341
	}
5342 5343 5344 5345
	if (tb[NL80211_MESH_SETUP_USERSPACE_MPM] &&
	    !(rdev->wiphy.features & NL80211_FEATURE_USERSPACE_MPM))
		return -EINVAL;
	setup->user_mpm = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_MPM]);
5346 5347
	setup->is_authenticated = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AUTH]);
	setup->is_secure = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AMPE]);
5348 5349
	if (setup->is_secure)
		setup->user_mpm = true;
5350

5351 5352 5353 5354 5355 5356 5357
	if (tb[NL80211_MESH_SETUP_AUTH_PROTOCOL]) {
		if (!setup->user_mpm)
			return -EINVAL;
		setup->auth_id =
			nla_get_u8(tb[NL80211_MESH_SETUP_AUTH_PROTOCOL]);
	}

5358 5359 5360
	return 0;
}

5361
static int nl80211_update_mesh_config(struct sk_buff *skb,
5362
				      struct genl_info *info)
5363 5364 5365
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
5366
	struct wireless_dev *wdev = dev->ieee80211_ptr;
5367 5368 5369 5370
	struct mesh_config cfg;
	u32 mask;
	int err;

5371 5372 5373
	if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
		return -EOPNOTSUPP;

5374
	if (!rdev->ops->update_mesh_config)
5375 5376
		return -EOPNOTSUPP;

5377
	err = nl80211_parse_mesh_config(info, &cfg, &mask);
5378 5379 5380
	if (err)
		return err;

5381 5382 5383 5384 5385
	wdev_lock(wdev);
	if (!wdev->mesh_id_len)
		err = -ENOLINK;

	if (!err)
5386
		err = rdev_update_mesh_config(rdev, dev, mask, &cfg);
5387 5388 5389 5390

	wdev_unlock(wdev);

	return err;
5391 5392
}

5393 5394
static int nl80211_put_regdom(const struct ieee80211_regdomain *regdom,
			      struct sk_buff *msg)
5395 5396 5397 5398
{
	struct nlattr *nl_reg_rules;
	unsigned int i;

5399 5400 5401
	if (nla_put_string(msg, NL80211_ATTR_REG_ALPHA2, regdom->alpha2) ||
	    (regdom->dfs_region &&
	     nla_put_u8(msg, NL80211_ATTR_DFS_REGION, regdom->dfs_region)))
5402
		goto nla_put_failure;
5403

5404 5405
	nl_reg_rules = nla_nest_start(msg, NL80211_ATTR_REG_RULES);
	if (!nl_reg_rules)
5406
		goto nla_put_failure;
5407

5408
	for (i = 0; i < regdom->n_reg_rules; i++) {
5409 5410 5411 5412
		struct nlattr *nl_reg_rule;
		const struct ieee80211_reg_rule *reg_rule;
		const struct ieee80211_freq_range *freq_range;
		const struct ieee80211_power_rule *power_rule;
5413
		unsigned int max_bandwidth_khz;
5414

5415
		reg_rule = &regdom->reg_rules[i];
5416 5417 5418 5419 5420
		freq_range = &reg_rule->freq_range;
		power_rule = &reg_rule->power_rule;

		nl_reg_rule = nla_nest_start(msg, i);
		if (!nl_reg_rule)
5421
			goto nla_put_failure;
5422

5423 5424 5425 5426 5427
		max_bandwidth_khz = freq_range->max_bandwidth_khz;
		if (!max_bandwidth_khz)
			max_bandwidth_khz = reg_get_max_bandwidth(regdom,
								  reg_rule);

5428 5429 5430 5431 5432 5433 5434
		if (nla_put_u32(msg, NL80211_ATTR_REG_RULE_FLAGS,
				reg_rule->flags) ||
		    nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_START,
				freq_range->start_freq_khz) ||
		    nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_END,
				freq_range->end_freq_khz) ||
		    nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_MAX_BW,
5435
				max_bandwidth_khz) ||
5436 5437 5438
		    nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
				power_rule->max_antenna_gain) ||
		    nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP,
5439 5440 5441
				power_rule->max_eirp) ||
		    nla_put_u32(msg, NL80211_ATTR_DFS_CAC_TIME,
				reg_rule->dfs_cac_ms))
5442
			goto nla_put_failure;
5443 5444 5445 5446 5447

		nla_nest_end(msg, nl_reg_rule);
	}

	nla_nest_end(msg, nl_reg_rules);
5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471
	return 0;

nla_put_failure:
	return -EMSGSIZE;
}

static int nl80211_get_reg_do(struct sk_buff *skb, struct genl_info *info)
{
	const struct ieee80211_regdomain *regdom = NULL;
	struct cfg80211_registered_device *rdev;
	struct wiphy *wiphy = NULL;
	struct sk_buff *msg;
	void *hdr;

	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
	if (!msg)
		return -ENOBUFS;

	hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
			     NL80211_CMD_GET_REG);
	if (!hdr)
		goto put_failure;

	if (info->attrs[NL80211_ATTR_WIPHY]) {
5472 5473
		bool self_managed;

5474 5475 5476 5477 5478 5479 5480
		rdev = cfg80211_get_dev_from_info(genl_info_net(info), info);
		if (IS_ERR(rdev)) {
			nlmsg_free(msg);
			return PTR_ERR(rdev);
		}

		wiphy = &rdev->wiphy;
5481 5482
		self_managed = wiphy->regulatory_flags &
			       REGULATORY_WIPHY_SELF_MANAGED;
5483 5484
		regdom = get_wiphy_regdom(wiphy);

5485 5486 5487 5488 5489 5490
		/* a self-managed-reg device must have a private regdom */
		if (WARN_ON(!regdom && self_managed)) {
			nlmsg_free(msg);
			return -EINVAL;
		}

5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509
		if (regdom &&
		    nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
			goto nla_put_failure;
	}

	if (!wiphy && reg_last_request_cell_base() &&
	    nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE,
			NL80211_USER_REG_HINT_CELL_BASE))
		goto nla_put_failure;

	rcu_read_lock();

	if (!regdom)
		regdom = rcu_dereference(cfg80211_regdomain);

	if (nl80211_put_regdom(regdom, msg))
		goto nla_put_failure_rcu;

	rcu_read_unlock();
5510 5511

	genlmsg_end(msg, hdr);
5512
	return genlmsg_reply(msg, info);
5513

5514 5515
nla_put_failure_rcu:
	rcu_read_unlock();
5516 5517
nla_put_failure:
	genlmsg_cancel(msg, hdr);
5518
put_failure:
Yuri Ershov's avatar
Yuri Ershov committed
5519
	nlmsg_free(msg);
5520
	return -EMSGSIZE;
5521 5522
}

5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546
static int nl80211_send_regdom(struct sk_buff *msg, struct netlink_callback *cb,
			       u32 seq, int flags, struct wiphy *wiphy,
			       const struct ieee80211_regdomain *regdom)
{
	void *hdr = nl80211hdr_put(msg, NETLINK_CB(cb->skb).portid, seq, flags,
				   NL80211_CMD_GET_REG);

	if (!hdr)
		return -1;

	genl_dump_check_consistent(cb, hdr, &nl80211_fam);

	if (nl80211_put_regdom(regdom, msg))
		goto nla_put_failure;

	if (!wiphy && reg_last_request_cell_base() &&
	    nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE,
			NL80211_USER_REG_HINT_CELL_BASE))
		goto nla_put_failure;

	if (wiphy &&
	    nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
		goto nla_put_failure;

5547 5548 5549 5550
	if (wiphy && wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
	    nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
		goto nla_put_failure;

5551 5552
	genlmsg_end(msg, hdr);
	return 0;
5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600

nla_put_failure:
	genlmsg_cancel(msg, hdr);
	return -EMSGSIZE;
}

static int nl80211_get_reg_dump(struct sk_buff *skb,
				struct netlink_callback *cb)
{
	const struct ieee80211_regdomain *regdom = NULL;
	struct cfg80211_registered_device *rdev;
	int err, reg_idx, start = cb->args[2];

	rtnl_lock();

	if (cfg80211_regdomain && start == 0) {
		err = nl80211_send_regdom(skb, cb, cb->nlh->nlmsg_seq,
					  NLM_F_MULTI, NULL,
					  rtnl_dereference(cfg80211_regdomain));
		if (err < 0)
			goto out_err;
	}

	/* the global regdom is idx 0 */
	reg_idx = 1;
	list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
		regdom = get_wiphy_regdom(&rdev->wiphy);
		if (!regdom)
			continue;

		if (++reg_idx <= start)
			continue;

		err = nl80211_send_regdom(skb, cb, cb->nlh->nlmsg_seq,
					  NLM_F_MULTI, &rdev->wiphy, regdom);
		if (err < 0) {
			reg_idx--;
			break;
		}
	}

	cb->args[2] = reg_idx;
	err = skb->len;
out_err:
	rtnl_unlock();
	return err;
}

5601 5602 5603 5604
static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
{
	struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1];
	struct nlattr *nl_reg_rule;
5605 5606
	char *alpha2;
	int rem_reg_rules, r;
5607
	u32 num_rules = 0, rule_idx = 0, size_of_regd;
5608
	enum nl80211_dfs_regions dfs_region = NL80211_DFS_UNSET;
5609
	struct ieee80211_regdomain *rd;
5610 5611 5612 5613 5614 5615 5616 5617 5618

	if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
		return -EINVAL;

	if (!info->attrs[NL80211_ATTR_REG_RULES])
		return -EINVAL;

	alpha2 = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);

5619 5620 5621
	if (info->attrs[NL80211_ATTR_DFS_REGION])
		dfs_region = nla_get_u8(info->attrs[NL80211_ATTR_DFS_REGION]);

5622
	nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
Johannes Berg's avatar
Johannes Berg committed
5623
			    rem_reg_rules) {
5624 5625
		num_rules++;
		if (num_rules > NL80211_MAX_SUPP_REG_RULES)
5626
			return -EINVAL;
5627 5628
	}

5629 5630 5631
	if (!reg_is_valid_request(alpha2))
		return -EINVAL;

5632
	size_of_regd = sizeof(struct ieee80211_regdomain) +
Johannes Berg's avatar
Johannes Berg committed
5633
		       num_rules * sizeof(struct ieee80211_reg_rule);
5634 5635

	rd = kzalloc(size_of_regd, GFP_KERNEL);
5636 5637
	if (!rd)
		return -ENOMEM;
5638 5639 5640 5641 5642

	rd->n_reg_rules = num_rules;
	rd->alpha2[0] = alpha2[0];
	rd->alpha2[1] = alpha2[1];

5643 5644 5645 5646 5647 5648 5649
	/*
	 * Disable DFS master mode if the DFS region was
	 * not supported or known on this kernel.
	 */
	if (reg_supported_dfs_region(dfs_region))
		rd->dfs_region = dfs_region;

5650
	nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
Johannes Berg's avatar
Johannes Berg committed
5651
			    rem_reg_rules) {
5652 5653 5654 5655 5656
		r = nla_parse(tb, NL80211_REG_RULE_ATTR_MAX,
			      nla_data(nl_reg_rule), nla_len(nl_reg_rule),
			      reg_rule_policy);
		if (r)
			goto bad_reg;
5657 5658 5659 5660 5661 5662
		r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]);
		if (r)
			goto bad_reg;

		rule_idx++;

5663 5664
		if (rule_idx > NL80211_MAX_SUPP_REG_RULES) {
			r = -EINVAL;
5665
			goto bad_reg;
5666
		}
5667 5668
	}

5669
	r = set_regdom(rd, REGD_SOURCE_CRDA);
5670
	/* set_regdom took ownership */
Johannes Berg's avatar
Johannes Berg committed
5671
	rd = NULL;
5672

5673
 bad_reg:
5674
	kfree(rd);
5675
	return r;
5676 5677
}

5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702
static int validate_scan_freqs(struct nlattr *freqs)
{
	struct nlattr *attr1, *attr2;
	int n_channels = 0, tmp1, tmp2;

	nla_for_each_nested(attr1, freqs, tmp1) {
		n_channels++;
		/*
		 * Some hardware has a limited channel list for
		 * scanning, and it is pretty much nonsensical
		 * to scan for a channel twice, so disallow that
		 * and don't require drivers to check that the
		 * channel list they get isn't longer than what
		 * they can scan, as long as they can scan all
		 * the channels they registered at once.
		 */
		nla_for_each_nested(attr2, freqs, tmp2)
			if (attr1 != attr2 &&
			    nla_get_u32(attr1) == nla_get_u32(attr2))
				return 0;
	}

	return n_channels;
}

5703 5704 5705 5706 5707 5708
static int nl80211_parse_random_mac(struct nlattr **attrs,
				    u8 *mac_addr, u8 *mac_addr_mask)
{
	int i;

	if (!attrs[NL80211_ATTR_MAC] && !attrs[NL80211_ATTR_MAC_MASK]) {
5709 5710
		eth_zero_addr(mac_addr);
		eth_zero_addr(mac_addr_mask);
5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739
		mac_addr[0] = 0x2;
		mac_addr_mask[0] = 0x3;

		return 0;
	}

	/* need both or none */
	if (!attrs[NL80211_ATTR_MAC] || !attrs[NL80211_ATTR_MAC_MASK])
		return -EINVAL;

	memcpy(mac_addr, nla_data(attrs[NL80211_ATTR_MAC]), ETH_ALEN);
	memcpy(mac_addr_mask, nla_data(attrs[NL80211_ATTR_MAC_MASK]), ETH_ALEN);

	/* don't allow or configure an mcast address */
	if (!is_multicast_ether_addr(mac_addr_mask) ||
	    is_multicast_ether_addr(mac_addr))
		return -EINVAL;

	/*
	 * allow users to pass a MAC address that has bits set outside
	 * of the mask, but don't bother drivers with having to deal
	 * with such bits
	 */
	for (i = 0; i < ETH_ALEN; i++)
		mac_addr[i] &= mac_addr_mask[i];

	return 0;
}

5740 5741
static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
{
5742
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
5743
	struct wireless_dev *wdev = info->user_ptr[1];
5744 5745 5746
	struct cfg80211_scan_request *request;
	struct nlattr *attr;
	struct wiphy *wiphy;
5747
	int err, tmp, n_ssids = 0, n_channels, i;
5748
	size_t ie_len;
5749

5750 5751 5752
	if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
		return -EINVAL;

5753
	wiphy = &rdev->wiphy;
5754

5755 5756
	if (!rdev->ops->scan)
		return -EOPNOTSUPP;
5757

5758
	if (rdev->scan_req || rdev->scan_msg) {
5759 5760 5761
		err = -EBUSY;
		goto unlock;
	}
5762 5763

	if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
5764 5765
		n_channels = validate_scan_freqs(
				info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
5766 5767 5768 5769
		if (!n_channels) {
			err = -EINVAL;
			goto unlock;
		}
5770
	} else {
5771
		n_channels = ieee80211_get_num_supported_channels(wiphy);
5772 5773 5774 5775 5776 5777
	}

	if (info->attrs[NL80211_ATTR_SCAN_SSIDS])
		nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp)
			n_ssids++;

5778 5779 5780 5781
	if (n_ssids > wiphy->max_scan_ssids) {
		err = -EINVAL;
		goto unlock;
	}
5782

5783 5784 5785 5786 5787
	if (info->attrs[NL80211_ATTR_IE])
		ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
	else
		ie_len = 0;

5788 5789 5790 5791
	if (ie_len > wiphy->max_scan_ie_len) {
		err = -EINVAL;
		goto unlock;
	}
5792

5793
	request = kzalloc(sizeof(*request)
5794 5795
			+ sizeof(*request->ssids) * n_ssids
			+ sizeof(*request->channels) * n_channels
5796
			+ ie_len, GFP_KERNEL);
5797 5798 5799 5800
	if (!request) {
		err = -ENOMEM;
		goto unlock;
	}
5801 5802

	if (n_ssids)
5803
		request->ssids = (void *)&request->channels[n_channels];
5804
	request->n_ssids = n_ssids;
5805
	if (ie_len) {
5806
		if (n_ssids)
5807 5808 5809 5810
			request->ie = (void *)(request->ssids + n_ssids);
		else
			request->ie = (void *)(request->channels + n_channels);
	}
5811

5812
	i = 0;
5813 5814 5815
	if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
		/* user specified, bail out if channel not found */
		nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_FREQUENCIES], tmp) {
5816 5817 5818 5819 5820
			struct ieee80211_channel *chan;

			chan = ieee80211_get_channel(wiphy, nla_get_u32(attr));

			if (!chan) {
5821 5822 5823
				err = -EINVAL;
				goto out_free;
			}
5824 5825 5826 5827 5828 5829

			/* ignore disabled channels */
			if (chan->flags & IEEE80211_CHAN_DISABLED)
				continue;

			request->channels[i] = chan;
5830 5831 5832
			i++;
		}
	} else {
5833 5834
		enum ieee80211_band band;

5835 5836 5837 5838 5839 5840
		/* all channels */
		for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
			int j;
			if (!wiphy->bands[band])
				continue;
			for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
5841 5842 5843 5844 5845 5846 5847 5848
				struct ieee80211_channel *chan;

				chan = &wiphy->bands[band]->channels[j];

				if (chan->flags & IEEE80211_CHAN_DISABLED)
					continue;

				request->channels[i] = chan;
5849 5850 5851 5852 5853
				i++;
			}
		}
	}

5854 5855 5856 5857 5858 5859 5860
	if (!i) {
		err = -EINVAL;
		goto out_free;
	}

	request->n_channels = i;

5861
	i = 0;
5862
	if (n_ssids) {
5863
		nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) {
5864
			if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) {
5865 5866 5867
				err = -EINVAL;
				goto out_free;
			}
5868
			request->ssids[i].ssid_len = nla_len(attr);
5869 5870 5871 5872 5873
			memcpy(request->ssids[i].ssid, nla_data(attr), nla_len(attr));
			i++;
		}
	}

5874 5875
	if (info->attrs[NL80211_ATTR_IE]) {
		request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
5876 5877
		memcpy((void *)request->ie,
		       nla_data(info->attrs[NL80211_ATTR_IE]),
5878 5879 5880
		       request->ie_len);
	}

5881
	for (i = 0; i < IEEE80211_NUM_BANDS; i++)
5882 5883 5884
		if (wiphy->bands[i])
			request->rates[i] =
				(1 << wiphy->bands[i]->n_bitrates) - 1;
5885 5886 5887 5888 5889 5890 5891

	if (info->attrs[NL80211_ATTR_SCAN_SUPP_RATES]) {
		nla_for_each_nested(attr,
				    info->attrs[NL80211_ATTR_SCAN_SUPP_RATES],
				    tmp) {
			enum ieee80211_band band = nla_type(attr);

5892
			if (band < 0 || band >= IEEE80211_NUM_BANDS) {
5893 5894 5895
				err = -EINVAL;
				goto out_free;
			}
5896 5897 5898 5899

			if (!wiphy->bands[band])
				continue;

5900 5901 5902 5903 5904 5905 5906 5907 5908
			err = ieee80211_get_ratemask(wiphy->bands[band],
						     nla_data(attr),
						     nla_len(attr),
						     &request->rates[band]);
			if (err)
				goto out_free;
		}
	}

5909
	if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) {
5910 5911
		request->flags = nla_get_u32(
			info->attrs[NL80211_ATTR_SCAN_FLAGS]);
5912 5913
		if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
		    !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) {
5914 5915 5916
			err = -EOPNOTSUPP;
			goto out_free;
		}
5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935

		if (request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
			if (!(wiphy->features &
					NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR)) {
				err = -EOPNOTSUPP;
				goto out_free;
			}

			if (wdev->current_bss) {
				err = -EOPNOTSUPP;
				goto out_free;
			}

			err = nl80211_parse_random_mac(info->attrs,
						       request->mac_addr,
						       request->mac_addr_mask);
			if (err)
				goto out_free;
		}
5936
	}
5937

5938 5939 5940
	request->no_cck =
		nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);

5941
	request->wdev = wdev;
5942
	request->wiphy = &rdev->wiphy;
5943
	request->scan_start = jiffies;
5944

5945
	rdev->scan_req = request;
5946
	err = rdev_scan(rdev, request);
5947

5948
	if (!err) {
5949 5950 5951
		nl80211_send_scan_start(rdev, wdev);
		if (wdev->netdev)
			dev_hold(wdev->netdev);
5952
	} else {
5953
 out_free:
5954
		rdev->scan_req = NULL;
5955 5956
		kfree(request);
	}
Johannes Berg's avatar
Johannes Berg committed
5957

5958
 unlock:
5959 5960 5961
	return err;
}

5962
static struct cfg80211_sched_scan_request *
5963
nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
5964
			 struct nlattr **attrs)
5965 5966 5967
{
	struct cfg80211_sched_scan_request *request;
	struct nlattr *attr;
5968
	int err, tmp, n_ssids = 0, n_match_sets = 0, n_channels, i;
5969
	u32 interval;
5970 5971
	enum ieee80211_band band;
	size_t ie_len;
5972
	struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];
5973
	s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF;
5974

5975 5976
	if (!is_valid_ie_attr(attrs[NL80211_ATTR_IE]))
		return ERR_PTR(-EINVAL);
5977

5978 5979
	if (!attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
		return ERR_PTR(-EINVAL);
5980

5981
	interval = nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]);
5982
	if (interval == 0)
5983
		return ERR_PTR(-EINVAL);
5984

5985
	if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
5986
		n_channels = validate_scan_freqs(
5987
				attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
5988
		if (!n_channels)
5989
			return ERR_PTR(-EINVAL);
5990
	} else {
5991
		n_channels = ieee80211_get_num_supported_channels(wiphy);
5992 5993
	}

5994 5995
	if (attrs[NL80211_ATTR_SCAN_SSIDS])
		nla_for_each_nested(attr, attrs[NL80211_ATTR_SCAN_SSIDS],
5996 5997 5998
				    tmp)
			n_ssids++;

5999
	if (n_ssids > wiphy->max_sched_scan_ssids)
6000
		return ERR_PTR(-EINVAL);
6001

6002 6003 6004 6005 6006 6007 6008 6009 6010
	/*
	 * First, count the number of 'real' matchsets. Due to an issue with
	 * the old implementation, matchsets containing only the RSSI attribute
	 * (NL80211_SCHED_SCAN_MATCH_ATTR_RSSI) are considered as the 'default'
	 * RSSI for all matchsets, rather than their own matchset for reporting
	 * all APs with a strong RSSI. This is needed to be compatible with
	 * older userspace that treated a matchset with only the RSSI as the
	 * global RSSI for all other matchsets - if there are other matchsets.
	 */
6011
	if (attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
6012
		nla_for_each_nested(attr,
6013
				    attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
6014 6015 6016 6017 6018 6019 6020
				    tmp) {
			struct nlattr *rssi;

			err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
					nla_data(attr), nla_len(attr),
					nl80211_match_policy);
			if (err)
6021
				return ERR_PTR(err);
6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035
			/* add other standalone attributes here */
			if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID]) {
				n_match_sets++;
				continue;
			}
			rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
			if (rssi)
				default_match_rssi = nla_get_s32(rssi);
		}
	}

	/* However, if there's no other matchset, add the RSSI one */
	if (!n_match_sets && default_match_rssi != NL80211_SCAN_RSSI_THOLD_OFF)
		n_match_sets = 1;
6036 6037

	if (n_match_sets > wiphy->max_match_sets)
6038
		return ERR_PTR(-EINVAL);
6039

6040 6041
	if (attrs[NL80211_ATTR_IE])
		ie_len = nla_len(attrs[NL80211_ATTR_IE]);
6042 6043 6044
	else
		ie_len = 0;

6045
	if (ie_len > wiphy->max_sched_scan_ie_len)
6046
		return ERR_PTR(-EINVAL);
6047

6048
	request = kzalloc(sizeof(*request)
6049
			+ sizeof(*request->ssids) * n_ssids
6050
			+ sizeof(*request->match_sets) * n_match_sets
6051
			+ sizeof(*request->channels) * n_channels
6052
			+ ie_len, GFP_KERNEL);
6053 6054
	if (!request)
		return ERR_PTR(-ENOMEM);
6055 6056 6057 6058 6059

	if (n_ssids)
		request->ssids = (void *)&request->channels[n_channels];
	request->n_ssids = n_ssids;
	if (ie_len) {
6060
		if (n_ssids)
6061 6062 6063 6064 6065
			request->ie = (void *)(request->ssids + n_ssids);
		else
			request->ie = (void *)(request->channels + n_channels);
	}

6066 6067 6068
	if (n_match_sets) {
		if (request->ie)
			request->match_sets = (void *)(request->ie + ie_len);
6069
		else if (n_ssids)
6070 6071 6072 6073 6074 6075 6076 6077
			request->match_sets =
				(void *)(request->ssids + n_ssids);
		else
			request->match_sets =
				(void *)(request->channels + n_channels);
	}
	request->n_match_sets = n_match_sets;

6078
	i = 0;
6079
	if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
6080 6081
		/* user specified, bail out if channel not found */
		nla_for_each_nested(attr,
6082
				    attrs[NL80211_ATTR_SCAN_FREQUENCIES],
6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 6124 6125 6126 6127
				    tmp) {
			struct ieee80211_channel *chan;

			chan = ieee80211_get_channel(wiphy, nla_get_u32(attr));

			if (!chan) {
				err = -EINVAL;
				goto out_free;
			}

			/* ignore disabled channels */
			if (chan->flags & IEEE80211_CHAN_DISABLED)
				continue;

			request->channels[i] = chan;
			i++;
		}
	} else {
		/* all channels */
		for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
			int j;
			if (!wiphy->bands[band])
				continue;
			for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
				struct ieee80211_channel *chan;

				chan = &wiphy->bands[band]->channels[j];

				if (chan->flags & IEEE80211_CHAN_DISABLED)
					continue;

				request->channels[i] = chan;
				i++;
			}
		}
	}

	if (!i) {
		err = -EINVAL;
		goto out_free;
	}

	request->n_channels = i;

	i = 0;
6128
	if (n_ssids) {
6129
		nla_for_each_nested(attr, attrs[NL80211_ATTR_SCAN_SSIDS],
6130
				    tmp) {
6131
			if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) {
6132 6133 6134
				err = -EINVAL;
				goto out_free;
			}
6135
			request->ssids[i].ssid_len = nla_len(attr);
6136 6137 6138 6139 6140 6141
			memcpy(request->ssids[i].ssid, nla_data(attr),
			       nla_len(attr));
			i++;
		}
	}

6142
	i = 0;
6143
	if (attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
6144
		nla_for_each_nested(attr,
6145
				    attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
6146
				    tmp) {
6147
			struct nlattr *ssid, *rssi;
6148

6149 6150 6151 6152 6153
			err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
					nla_data(attr), nla_len(attr),
					nl80211_match_policy);
			if (err)
				goto out_free;
6154
			ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID];
6155
			if (ssid) {
6156 6157 6158 6159 6160 6161 6162 6163 6164
				if (WARN_ON(i >= n_match_sets)) {
					/* this indicates a programming error,
					 * the loop above should have verified
					 * things properly
					 */
					err = -EINVAL;
					goto out_free;
				}

6165 6166 6167 6168 6169 6170 6171 6172
				if (nla_len(ssid) > IEEE80211_MAX_SSID_LEN) {
					err = -EINVAL;
					goto out_free;
				}
				memcpy(request->match_sets[i].ssid.ssid,
				       nla_data(ssid), nla_len(ssid));
				request->match_sets[i].ssid.ssid_len =
					nla_len(ssid);
6173 6174 6175 6176 6177 6178 6179
				/* special attribute - old implemenation w/a */
				request->match_sets[i].rssi_thold =
					default_match_rssi;
				rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
				if (rssi)
					request->match_sets[i].rssi_thold =
						nla_get_s32(rssi);
6180 6181 6182
			}
			i++;
		}
6183 6184

		/* there was no other matchset, so the RSSI one is alone */
6185
		if (i == 0 && n_match_sets)
6186 6187 6188 6189 6190 6191 6192 6193 6194
			request->match_sets[0].rssi_thold = default_match_rssi;

		request->min_rssi_thold = INT_MAX;
		for (i = 0; i < n_match_sets; i++)
			request->min_rssi_thold =
				min(request->match_sets[i].rssi_thold,
				    request->min_rssi_thold);
	} else {
		request->min_rssi_thold = NL80211_SCAN_RSSI_THOLD_OFF;
6195 6196
	}

6197 6198
	if (ie_len) {
		request->ie_len = ie_len;
6199
		memcpy((void *)request->ie,
6200
		       nla_data(attrs[NL80211_ATTR_IE]),
6201 6202 6203
		       request->ie_len);
	}

6204
	if (attrs[NL80211_ATTR_SCAN_FLAGS]) {
6205
		request->flags = nla_get_u32(
6206
			attrs[NL80211_ATTR_SCAN_FLAGS]);
6207 6208
		if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
		    !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) {
6209 6210 6211
			err = -EOPNOTSUPP;
			goto out_free;
		}
6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233

		if (request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
			u32 flg = NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR;

			if (!wdev) /* must be net-detect */
				flg = NL80211_FEATURE_ND_RANDOM_MAC_ADDR;

			if (!(wiphy->features & flg)) {
				err = -EOPNOTSUPP;
				goto out_free;
			}

			if (wdev && wdev->current_bss) {
				err = -EOPNOTSUPP;
				goto out_free;
			}

			err = nl80211_parse_random_mac(attrs, request->mac_addr,
						       request->mac_addr_mask);
			if (err)
				goto out_free;
		}
6234
	}
6235

6236 6237 6238 6239
	if (attrs[NL80211_ATTR_SCHED_SCAN_DELAY])
		request->delay =
			nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_DELAY]);

6240
	request->interval = interval;
6241
	request->scan_start = jiffies;
6242

6243
	return request;
6244 6245 6246

out_free:
	kfree(request);
6247 6248 6249 6250 6251 6252 6253 6254
	return ERR_PTR(err);
}

static int nl80211_start_sched_scan(struct sk_buff *skb,
				    struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
6255
	struct wireless_dev *wdev = dev->ieee80211_ptr;
6256
	struct cfg80211_sched_scan_request *sched_scan_req;
6257 6258 6259 6260 6261 6262 6263 6264 6265
	int err;

	if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
	    !rdev->ops->sched_scan_start)
		return -EOPNOTSUPP;

	if (rdev->sched_scan_req)
		return -EINPROGRESS;

6266 6267 6268 6269
	sched_scan_req = nl80211_parse_sched_scan(&rdev->wiphy, wdev,
						  info->attrs);

	err = PTR_ERR_OR_ZERO(sched_scan_req);
6270 6271 6272
	if (err)
		goto out_err;

6273
	err = rdev_sched_scan_start(rdev, dev, sched_scan_req);
6274 6275 6276
	if (err)
		goto out_free;

6277 6278 6279
	sched_scan_req->dev = dev;
	sched_scan_req->wiphy = &rdev->wiphy;

6280 6281 6282
	if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
		sched_scan_req->owner_nlportid = info->snd_portid;

6283
	rcu_assign_pointer(rdev->sched_scan_req, sched_scan_req);
6284 6285 6286 6287 6288 6289

	nl80211_send_sched_scan(rdev, dev,
				NL80211_CMD_START_SCHED_SCAN);
	return 0;

out_free:
6290
	kfree(sched_scan_req);
6291
out_err:
6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303
	return err;
}

static int nl80211_stop_sched_scan(struct sk_buff *skb,
				   struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];

	if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
	    !rdev->ops->sched_scan_stop)
		return -EOPNOTSUPP;

6304
	return __cfg80211_stop_sched_scan(rdev, false);
6305 6306
}

6307 6308 6309 6310 6311 6312 6313
static int nl80211_start_radar_detection(struct sk_buff *skb,
					 struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
	struct wireless_dev *wdev = dev->ieee80211_ptr;
	struct cfg80211_chan_def chandef;
6314
	enum nl80211_dfs_regions dfs_region;
6315
	unsigned int cac_time_ms;
6316 6317
	int err;

6318 6319 6320 6321
	dfs_region = reg_get_dfs_region(wdev->wiphy);
	if (dfs_region == NL80211_DFS_UNSET)
		return -EINVAL;

6322 6323 6324 6325
	err = nl80211_parse_chandef(rdev, info, &chandef);
	if (err)
		return err;

6326 6327 6328
	if (netif_carrier_ok(dev))
		return -EBUSY;

6329 6330 6331
	if (wdev->cac_started)
		return -EBUSY;

6332
	err = cfg80211_chandef_dfs_required(wdev->wiphy, &chandef,
6333
					    wdev->iftype);
6334 6335 6336 6337 6338 6339
	if (err < 0)
		return err;

	if (err == 0)
		return -EINVAL;

6340
	if (!cfg80211_chandef_dfs_usable(wdev->wiphy, &chandef))
6341 6342 6343 6344 6345
		return -EINVAL;

	if (!rdev->ops->start_radar_detection)
		return -EOPNOTSUPP;

6346 6347 6348 6349 6350 6351
	cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, &chandef);
	if (WARN_ON(!cac_time_ms))
		cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;

	err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef,
					       cac_time_ms);
6352
	if (!err) {
6353
		wdev->chandef = chandef;
6354 6355
		wdev->cac_started = true;
		wdev->cac_start_time = jiffies;
6356
		wdev->cac_time_ms = cac_time_ms;
6357 6358 6359 6360
	}
	return err;
}

6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371
static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
	struct wireless_dev *wdev = dev->ieee80211_ptr;
	struct cfg80211_csa_settings params;
	/* csa_attrs is defined static to avoid waste of stack size - this
	 * function is called under RTNL lock, so this should not be a problem.
	 */
	static struct nlattr *csa_attrs[NL80211_ATTR_MAX+1];
	int err;
6372
	bool need_new_beacon = false;
6373
	int len, i;
6374
	u32 cs_count;
6375 6376 6377 6378 6379

	if (!rdev->ops->channel_switch ||
	    !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH))
		return -EOPNOTSUPP;

6380 6381 6382 6383 6384 6385 6386
	switch (dev->ieee80211_ptr->iftype) {
	case NL80211_IFTYPE_AP:
	case NL80211_IFTYPE_P2P_GO:
		need_new_beacon = true;

		/* useless if AP is not running */
		if (!wdev->beacon_interval)
6387
			return -ENOTCONN;
6388 6389
		break;
	case NL80211_IFTYPE_ADHOC:
6390 6391 6392
		if (!wdev->ssid_len)
			return -ENOTCONN;
		break;
6393
	case NL80211_IFTYPE_MESH_POINT:
6394 6395
		if (!wdev->mesh_id_len)
			return -ENOTCONN;
6396 6397
		break;
	default:
6398
		return -EOPNOTSUPP;
6399
	}
6400 6401 6402 6403 6404 6405 6406 6407

	memset(&params, 0, sizeof(params));

	if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
	    !info->attrs[NL80211_ATTR_CH_SWITCH_COUNT])
		return -EINVAL;

	/* only important for AP, IBSS and mesh create IEs internally */
6408
	if (need_new_beacon && !info->attrs[NL80211_ATTR_CSA_IES])
6409 6410
		return -EINVAL;

6411 6412 6413 6414 6415 6416 6417 6418
	/* Even though the attribute is u32, the specification says
	 * u8, so let's make sure we don't overflow.
	 */
	cs_count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]);
	if (cs_count > 255)
		return -EINVAL;

	params.count = cs_count;
6419

6420 6421 6422
	if (!need_new_beacon)
		goto skip_beacons;

6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439
	err = nl80211_parse_beacon(info->attrs, &params.beacon_after);
	if (err)
		return err;

	err = nla_parse_nested(csa_attrs, NL80211_ATTR_MAX,
			       info->attrs[NL80211_ATTR_CSA_IES],
			       nl80211_policy);
	if (err)
		return err;

	err = nl80211_parse_beacon(csa_attrs, &params.beacon_csa);
	if (err)
		return err;

	if (!csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON])
		return -EINVAL;

6440 6441
	len = nla_len(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]);
	if (!len || (len % sizeof(u16)))
6442 6443
		return -EINVAL;

6444 6445 6446 6447
	params.n_counter_offsets_beacon = len / sizeof(u16);
	if (rdev->wiphy.max_num_csa_counters &&
	    (params.n_counter_offsets_beacon >
	     rdev->wiphy.max_num_csa_counters))
6448 6449
		return -EINVAL;

6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463
	params.counter_offsets_beacon =
		nla_data(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]);

	/* sanity checks - counters should fit and be the same */
	for (i = 0; i < params.n_counter_offsets_beacon; i++) {
		u16 offset = params.counter_offsets_beacon[i];

		if (offset >= params.beacon_csa.tail_len)
			return -EINVAL;

		if (params.beacon_csa.tail[offset] != params.count)
			return -EINVAL;
	}

6464
	if (csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]) {
6465 6466
		len = nla_len(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]);
		if (!len || (len % sizeof(u16)))
6467 6468
			return -EINVAL;

6469 6470 6471 6472
		params.n_counter_offsets_presp = len / sizeof(u16);
		if (rdev->wiphy.max_num_csa_counters &&
		    (params.n_counter_offsets_beacon >
		     rdev->wiphy.max_num_csa_counters))
6473
			return -EINVAL;
6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488

		params.counter_offsets_presp =
			nla_data(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]);

		/* sanity checks - counters should fit and be the same */
		for (i = 0; i < params.n_counter_offsets_presp; i++) {
			u16 offset = params.counter_offsets_presp[i];

			if (offset >= params.beacon_csa.probe_resp_len)
				return -EINVAL;

			if (params.beacon_csa.probe_resp[offset] !=
			    params.count)
				return -EINVAL;
		}
6489 6490
	}

6491
skip_beacons:
6492 6493 6494 6495
	err = nl80211_parse_chandef(rdev, info, &params.chandef);
	if (err)
		return err;

6496 6497
	if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params.chandef,
					   wdev->iftype))
6498 6499
		return -EINVAL;

6500 6501 6502 6503 6504 6505
	err = cfg80211_chandef_dfs_required(wdev->wiphy,
					    &params.chandef,
					    wdev->iftype);
	if (err < 0)
		return err;

6506
	if (err > 0)
6507
		params.radar_required = true;
6508 6509 6510 6511

	if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX])
		params.block_tx = true;

6512 6513 6514 6515 6516
	wdev_lock(wdev);
	err = rdev_channel_switch(rdev, dev, &params);
	wdev_unlock(wdev);

	return err;
6517 6518
}

6519 6520
static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
			    u32 seq, int flags,
6521
			    struct cfg80211_registered_device *rdev,
Johannes Berg's avatar
Johannes Berg committed
6522 6523
			    struct wireless_dev *wdev,
			    struct cfg80211_internal_bss *intbss)
6524
{
Johannes Berg's avatar
Johannes Berg committed
6525
	struct cfg80211_bss *res = &intbss->pub;
6526
	const struct cfg80211_bss_ies *ies;
6527 6528
	void *hdr;
	struct nlattr *bss;
Johannes Berg's avatar
Johannes Berg committed
6529 6530

	ASSERT_WDEV_LOCK(wdev);
6531

6532
	hdr = nl80211hdr_put(msg, NETLINK_CB(cb->skb).portid, seq, flags,
6533 6534 6535 6536
			     NL80211_CMD_NEW_SCAN_RESULTS);
	if (!hdr)
		return -1;

6537 6538
	genl_dump_check_consistent(cb, hdr, &nl80211_fam);

6539 6540 6541
	if (nla_put_u32(msg, NL80211_ATTR_GENERATION, rdev->bss_generation))
		goto nla_put_failure;
	if (wdev->netdev &&
6542 6543
	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex))
		goto nla_put_failure;
6544 6545
	if (nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
		goto nla_put_failure;
6546 6547 6548 6549

	bss = nla_nest_start(msg, NL80211_ATTR_BSS);
	if (!bss)
		goto nla_put_failure;
6550
	if ((!is_zero_ether_addr(res->bssid) &&
6551
	     nla_put(msg, NL80211_BSS_BSSID, ETH_ALEN, res->bssid)))
6552
		goto nla_put_failure;
6553 6554

	rcu_read_lock();
6555 6556 6557 6558 6559 6560 6561 6562
	/* indicate whether we have probe response data or not */
	if (rcu_access_pointer(res->proberesp_ies) &&
	    nla_put_flag(msg, NL80211_BSS_PRESP_DATA))
		goto fail_unlock_rcu;

	/* this pointer prefers to be pointed to probe response data
	 * but is always valid
	 */
6563
	ies = rcu_dereference(res->ies);
Johannes Berg's avatar
Johannes Berg committed
6564 6565 6566 6567 6568 6569
	if (ies) {
		if (nla_put_u64(msg, NL80211_BSS_TSF, ies->tsf))
			goto fail_unlock_rcu;
		if (ies->len && nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS,
					ies->len, ies->data))
			goto fail_unlock_rcu;
6570
	}
6571 6572

	/* and this pointer is always (unless driver didn't know) beacon data */
6573
	ies = rcu_dereference(res->beacon_ies);
6574 6575
	if (ies && ies->from_beacon) {
		if (nla_put_u64(msg, NL80211_BSS_BEACON_TSF, ies->tsf))
Johannes Berg's avatar
Johannes Berg committed
6576 6577 6578 6579
			goto fail_unlock_rcu;
		if (ies->len && nla_put(msg, NL80211_BSS_BEACON_IES,
					ies->len, ies->data))
			goto fail_unlock_rcu;
6580 6581 6582
	}
	rcu_read_unlock();

6583 6584 6585 6586 6587
	if (res->beacon_interval &&
	    nla_put_u16(msg, NL80211_BSS_BEACON_INTERVAL, res->beacon_interval))
		goto nla_put_failure;
	if (nla_put_u16(msg, NL80211_BSS_CAPABILITY, res->capability) ||
	    nla_put_u32(msg, NL80211_BSS_FREQUENCY, res->channel->center_freq) ||
6588
	    nla_put_u32(msg, NL80211_BSS_CHAN_WIDTH, res->scan_width) ||
6589 6590 6591
	    nla_put_u32(msg, NL80211_BSS_SEEN_MS_AGO,
			jiffies_to_msecs(jiffies - intbss->ts)))
		goto nla_put_failure;
6592

6593
	switch (rdev->wiphy.signal_type) {
6594
	case CFG80211_SIGNAL_TYPE_MBM:
6595 6596
		if (nla_put_u32(msg, NL80211_BSS_SIGNAL_MBM, res->signal))
			goto nla_put_failure;
6597 6598
		break;
	case CFG80211_SIGNAL_TYPE_UNSPEC:
6599 6600
		if (nla_put_u8(msg, NL80211_BSS_SIGNAL_UNSPEC, res->signal))
			goto nla_put_failure;
6601 6602 6603 6604 6605
		break;
	default:
		break;
	}

Johannes Berg's avatar
Johannes Berg committed
6606
	switch (wdev->iftype) {
6607
	case NL80211_IFTYPE_P2P_CLIENT:
Johannes Berg's avatar
Johannes Berg committed
6608
	case NL80211_IFTYPE_STATION:
6609 6610 6611 6612
		if (intbss == wdev->current_bss &&
		    nla_put_u32(msg, NL80211_BSS_STATUS,
				NL80211_BSS_STATUS_ASSOCIATED))
			goto nla_put_failure;
Johannes Berg's avatar
Johannes Berg committed
6613 6614
		break;
	case NL80211_IFTYPE_ADHOC:
6615 6616 6617 6618
		if (intbss == wdev->current_bss &&
		    nla_put_u32(msg, NL80211_BSS_STATUS,
				NL80211_BSS_STATUS_IBSS_JOINED))
			goto nla_put_failure;
Johannes Berg's avatar
Johannes Berg committed
6619 6620 6621 6622 6623
		break;
	default:
		break;
	}

6624 6625
	nla_nest_end(msg, bss);

6626 6627
	genlmsg_end(msg, hdr);
	return 0;
6628

Johannes Berg's avatar
Johannes Berg committed
6629 6630
 fail_unlock_rcu:
	rcu_read_unlock();
6631 6632 6633 6634 6635
 nla_put_failure:
	genlmsg_cancel(msg, hdr);
	return -EMSGSIZE;
}

6636
static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb)
6637
{
Johannes Berg's avatar
Johannes Berg committed
6638
	struct cfg80211_registered_device *rdev;
6639
	struct cfg80211_internal_bss *scan;
Johannes Berg's avatar
Johannes Berg committed
6640
	struct wireless_dev *wdev;
6641
	int start = cb->args[2], idx = 0;
6642 6643
	int err;

6644
	err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
6645 6646
	if (err)
		return err;
6647

Johannes Berg's avatar
Johannes Berg committed
6648 6649 6650 6651
	wdev_lock(wdev);
	spin_lock_bh(&rdev->bss_lock);
	cfg80211_bss_expire(rdev);

6652 6653
	cb->seq = rdev->bss_generation;

Johannes Berg's avatar
Johannes Berg committed
6654
	list_for_each_entry(scan, &rdev->bss_list, list) {
6655 6656
		if (++idx <= start)
			continue;
6657
		if (nl80211_send_bss(skb, cb,
6658
				cb->nlh->nlmsg_seq, NLM_F_MULTI,
Johannes Berg's avatar
Johannes Berg committed
6659
				rdev, wdev, scan) < 0) {
6660
			idx--;
6661
			break;
6662 6663 6664
		}
	}

Johannes Berg's avatar
Johannes Berg committed
6665 6666
	spin_unlock_bh(&rdev->bss_lock);
	wdev_unlock(wdev);
6667

6668 6669
	cb->args[2] = idx;
	nl80211_finish_wdev_dump(rdev);
6670

6671
	return skb->len;
6672 6673
}

6674
static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq,
6675 6676 6677
			       int flags, struct net_device *dev,
			       bool allow_radio_stats,
			       struct survey_info *survey)
6678 6679 6680 6681
{
	void *hdr;
	struct nlattr *infoattr;

6682 6683 6684 6685
	/* skip radio stats if userspace didn't request them */
	if (!survey->channel && !allow_radio_stats)
		return 0;

6686
	hdr = nl80211hdr_put(msg, portid, seq, flags,
6687 6688 6689 6690
			     NL80211_CMD_NEW_SURVEY_RESULTS);
	if (!hdr)
		return -ENOMEM;

6691 6692
	if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
		goto nla_put_failure;
6693 6694 6695 6696 6697

	infoattr = nla_nest_start(msg, NL80211_ATTR_SURVEY_INFO);
	if (!infoattr)
		goto nla_put_failure;

6698 6699
	if (survey->channel &&
	    nla_put_u32(msg, NL80211_SURVEY_INFO_FREQUENCY,
6700 6701 6702 6703 6704 6705 6706 6707 6708
			survey->channel->center_freq))
		goto nla_put_failure;

	if ((survey->filled & SURVEY_INFO_NOISE_DBM) &&
	    nla_put_u8(msg, NL80211_SURVEY_INFO_NOISE, survey->noise))
		goto nla_put_failure;
	if ((survey->filled & SURVEY_INFO_IN_USE) &&
	    nla_put_flag(msg, NL80211_SURVEY_INFO_IN_USE))
		goto nla_put_failure;
6709 6710 6711
	if ((survey->filled & SURVEY_INFO_TIME) &&
	    nla_put_u64(msg, NL80211_SURVEY_INFO_TIME,
			survey->time))
6712
		goto nla_put_failure;
6713 6714 6715
	if ((survey->filled & SURVEY_INFO_TIME_BUSY) &&
	    nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_BUSY,
			survey->time_busy))
6716
		goto nla_put_failure;
6717 6718 6719
	if ((survey->filled & SURVEY_INFO_TIME_EXT_BUSY) &&
	    nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_EXT_BUSY,
			survey->time_ext_busy))
6720
		goto nla_put_failure;
6721 6722 6723
	if ((survey->filled & SURVEY_INFO_TIME_RX) &&
	    nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_RX,
			survey->time_rx))
6724
		goto nla_put_failure;
6725 6726 6727
	if ((survey->filled & SURVEY_INFO_TIME_TX) &&
	    nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_TX,
			survey->time_tx))
6728
		goto nla_put_failure;
6729 6730 6731 6732
	if ((survey->filled & SURVEY_INFO_TIME_SCAN) &&
	    nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_SCAN,
			survey->time_scan))
		goto nla_put_failure;
6733 6734 6735

	nla_nest_end(msg, infoattr);

6736 6737
	genlmsg_end(msg, hdr);
	return 0;
6738 6739 6740 6741 6742 6743

 nla_put_failure:
	genlmsg_cancel(msg, hdr);
	return -EMSGSIZE;
}

6744
static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)
6745 6746
{
	struct survey_info survey;
6747
	struct cfg80211_registered_device *rdev;
6748 6749
	struct wireless_dev *wdev;
	int survey_idx = cb->args[2];
6750
	int res;
6751
	bool radio_stats;
6752

6753
	res = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
6754 6755
	if (res)
		return res;
6756

6757 6758 6759
	/* prepare_wdev_dump parsed the attributes */
	radio_stats = nl80211_fam.attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS];

6760 6761 6762 6763 6764
	if (!wdev->netdev) {
		res = -EINVAL;
		goto out_err;
	}

6765
	if (!rdev->ops->dump_survey) {
6766 6767 6768 6769 6770
		res = -EOPNOTSUPP;
		goto out_err;
	}

	while (1) {
6771
		res = rdev_dump_survey(rdev, wdev->netdev, survey_idx, &survey);
6772 6773 6774 6775 6776
		if (res == -ENOENT)
			break;
		if (res)
			goto out_err;

6777 6778 6779
		/* don't send disabled channels, but do send non-channel data */
		if (survey.channel &&
		    survey.channel->flags & IEEE80211_CHAN_DISABLED) {
6780 6781 6782 6783
			survey_idx++;
			continue;
		}

6784
		if (nl80211_send_survey(skb,
6785
				NETLINK_CB(cb->skb).portid,
6786
				cb->nlh->nlmsg_seq, NLM_F_MULTI,
6787
				wdev->netdev, radio_stats, &survey) < 0)
6788 6789 6790 6791 6792
			goto out;
		survey_idx++;
	}

 out:
6793
	cb->args[2] = survey_idx;
6794 6795
	res = skb->len;
 out_err:
6796
	nl80211_finish_wdev_dump(rdev);
6797 6798 6799
	return res;
}

6800 6801 6802 6803 6804 6805
static bool nl80211_valid_wpa_versions(u32 wpa_versions)
{
	return !(wpa_versions & ~(NL80211_WPA_VERSION_1 |
				  NL80211_WPA_VERSION_2));
}

6806 6807
static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
{
6808 6809
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
6810
	struct ieee80211_channel *chan;
6811 6812
	const u8 *bssid, *ssid, *ie = NULL, *sae_data = NULL;
	int err, ssid_len, ie_len = 0, sae_data_len = 0;
6813
	enum nl80211_auth_type auth_type;
6814
	struct key_parse key;
6815
	bool local_state_change;
6816

6817 6818 6819 6820 6821 6822
	if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
		return -EINVAL;

	if (!info->attrs[NL80211_ATTR_MAC])
		return -EINVAL;

6823 6824 6825
	if (!info->attrs[NL80211_ATTR_AUTH_TYPE])
		return -EINVAL;

6826 6827 6828 6829 6830 6831
	if (!info->attrs[NL80211_ATTR_SSID])
		return -EINVAL;

	if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
		return -EINVAL;

6832 6833 6834 6835 6836
	err = nl80211_parse_key(info, &key);
	if (err)
		return err;

	if (key.idx >= 0) {
6837 6838
		if (key.type != -1 && key.type != NL80211_KEYTYPE_GROUP)
			return -EINVAL;
6839 6840 6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852
		if (!key.p.key || !key.p.key_len)
			return -EINVAL;
		if ((key.p.cipher != WLAN_CIPHER_SUITE_WEP40 ||
		     key.p.key_len != WLAN_KEY_LEN_WEP40) &&
		    (key.p.cipher != WLAN_CIPHER_SUITE_WEP104 ||
		     key.p.key_len != WLAN_KEY_LEN_WEP104))
			return -EINVAL;
		if (key.idx > 4)
			return -EINVAL;
	} else {
		key.p.key_len = 0;
		key.p.key = NULL;
	}

6853 6854 6855 6856 6857 6858 6859 6860 6861
	if (key.idx >= 0) {
		int i;
		bool ok = false;
		for (i = 0; i < rdev->wiphy.n_cipher_suites; i++) {
			if (key.p.cipher == rdev->wiphy.cipher_suites[i]) {
				ok = true;
				break;
			}
		}
6862 6863
		if (!ok)
			return -EINVAL;
6864 6865
	}

6866 6867
	if (!rdev->ops->auth)
		return -EOPNOTSUPP;
6868

6869
	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
6870 6871
	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
		return -EOPNOTSUPP;
6872

6873
	bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
6874 6875 6876
	chan = nl80211_get_valid_chan(&rdev->wiphy,
				      info->attrs[NL80211_ATTR_WIPHY_FREQ]);
	if (!chan)
6877
		return -EINVAL;
6878

6879 6880
	ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
	ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
6881 6882

	if (info->attrs[NL80211_ATTR_IE]) {
6883 6884
		ie = nla_data(info->attrs[NL80211_ATTR_IE]);
		ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
6885 6886
	}

6887
	auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
6888
	if (!nl80211_valid_auth_type(rdev, auth_type, NL80211_CMD_AUTHENTICATE))
6889
		return -EINVAL;
6890

6891 6892 6893 6894 6895 6896 6897 6898 6899 6900 6901 6902 6903 6904
	if (auth_type == NL80211_AUTHTYPE_SAE &&
	    !info->attrs[NL80211_ATTR_SAE_DATA])
		return -EINVAL;

	if (info->attrs[NL80211_ATTR_SAE_DATA]) {
		if (auth_type != NL80211_AUTHTYPE_SAE)
			return -EINVAL;
		sae_data = nla_data(info->attrs[NL80211_ATTR_SAE_DATA]);
		sae_data_len = nla_len(info->attrs[NL80211_ATTR_SAE_DATA]);
		/* need to include at least Auth Transaction and Status Code */
		if (sae_data_len < 4)
			return -EINVAL;
	}

6905 6906
	local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];

6907 6908 6909 6910 6911 6912 6913
	/*
	 * Since we no longer track auth state, ignore
	 * requests to only change local state.
	 */
	if (local_state_change)
		return 0;

6914 6915 6916 6917 6918 6919 6920
	wdev_lock(dev->ieee80211_ptr);
	err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
				 ssid, ssid_len, ie, ie_len,
				 key.p.key, key.p.key_len, key.idx,
				 sae_data, sae_data_len);
	wdev_unlock(dev->ieee80211_ptr);
	return err;
6921 6922
}

6923 6924
static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
				   struct genl_info *info,
6925 6926
				   struct cfg80211_crypto_settings *settings,
				   int cipher_limit)
6927
{
6928 6929
	memset(settings, 0, sizeof(*settings));

6930 6931
	settings->control_port = info->attrs[NL80211_ATTR_CONTROL_PORT];

6932 6933 6934 6935 6936 6937 6938 6939 6940 6941 6942 6943 6944
	if (info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]) {
		u16 proto;
		proto = nla_get_u16(
			info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]);
		settings->control_port_ethertype = cpu_to_be16(proto);
		if (!(rdev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) &&
		    proto != ETH_P_PAE)
			return -EINVAL;
		if (info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT])
			settings->control_port_no_encrypt = true;
	} else
		settings->control_port_ethertype = cpu_to_be16(ETH_P_PAE);

6945 6946 6947 6948 6949 6950 6951 6952 6953 6954 6955
	if (info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]) {
		void *data;
		int len, i;

		data = nla_data(info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]);
		len = nla_len(info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]);
		settings->n_ciphers_pairwise = len / sizeof(u32);

		if (len % sizeof(u32))
			return -EINVAL;

6956
		if (settings->n_ciphers_pairwise > cipher_limit)
6957 6958 6959 6960 6961
			return -EINVAL;

		memcpy(settings->ciphers_pairwise, data, len);

		for (i = 0; i < settings->n_ciphers_pairwise; i++)
6962 6963
			if (!cfg80211_supported_cipher_suite(
					&rdev->wiphy,
6964 6965 6966 6967 6968 6969 6970
					settings->ciphers_pairwise[i]))
				return -EINVAL;
	}

	if (info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]) {
		settings->cipher_group =
			nla_get_u32(info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]);
6971 6972
		if (!cfg80211_supported_cipher_suite(&rdev->wiphy,
						     settings->cipher_group))
6973 6974 6975 6976 6977 6978 6979 6980 6981 6982 6983 6984
			return -EINVAL;
	}

	if (info->attrs[NL80211_ATTR_WPA_VERSIONS]) {
		settings->wpa_versions =
			nla_get_u32(info->attrs[NL80211_ATTR_WPA_VERSIONS]);
		if (!nl80211_valid_wpa_versions(settings->wpa_versions))
			return -EINVAL;
	}

	if (info->attrs[NL80211_ATTR_AKM_SUITES]) {
		void *data;
6985
		int len;
6986 6987 6988 6989 6990 6991 6992 6993

		data = nla_data(info->attrs[NL80211_ATTR_AKM_SUITES]);
		len = nla_len(info->attrs[NL80211_ATTR_AKM_SUITES]);
		settings->n_akm_suites = len / sizeof(u32);

		if (len % sizeof(u32))
			return -EINVAL;

6994 6995 6996
		if (settings->n_akm_suites > NL80211_MAX_NR_AKM_SUITES)
			return -EINVAL;

6997 6998 6999 7000 7001 7002
		memcpy(settings->akm_suites, data, len);
	}

	return 0;
}

7003 7004
static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
{
7005 7006
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
7007
	struct ieee80211_channel *chan;
7008 7009 7010
	struct cfg80211_assoc_request req = {};
	const u8 *bssid, *ssid;
	int err, ssid_len = 0;
7011

7012 7013 7014 7015
	if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
		return -EINVAL;

	if (!info->attrs[NL80211_ATTR_MAC] ||
7016 7017
	    !info->attrs[NL80211_ATTR_SSID] ||
	    !info->attrs[NL80211_ATTR_WIPHY_FREQ])
7018 7019
		return -EINVAL;

7020 7021
	if (!rdev->ops->assoc)
		return -EOPNOTSUPP;
7022

7023
	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
7024 7025
	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
		return -EOPNOTSUPP;
7026

7027
	bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
7028

7029 7030 7031
	chan = nl80211_get_valid_chan(&rdev->wiphy,
				      info->attrs[NL80211_ATTR_WIPHY_FREQ]);
	if (!chan)
7032
		return -EINVAL;
7033

7034 7035
	ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
	ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
7036 7037

	if (info->attrs[NL80211_ATTR_IE]) {
7038 7039
		req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
		req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
7040 7041
	}

7042
	if (info->attrs[NL80211_ATTR_USE_MFP]) {
7043
		enum nl80211_mfp mfp =
7044
			nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
7045
		if (mfp == NL80211_MFP_REQUIRED)
7046
			req.use_mfp = true;
7047 7048
		else if (mfp != NL80211_MFP_NO)
			return -EINVAL;
7049 7050
	}

7051
	if (info->attrs[NL80211_ATTR_PREV_BSSID])
7052
		req.prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
7053

7054
	if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
7055
		req.flags |= ASSOC_REQ_DISABLE_HT;
7056 7057

	if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
7058 7059 7060
		memcpy(&req.ht_capa_mask,
		       nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
		       sizeof(req.ht_capa_mask));
7061 7062

	if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
7063
		if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
7064
			return -EINVAL;
7065 7066 7067
		memcpy(&req.ht_capa,
		       nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
		       sizeof(req.ht_capa));
7068 7069
	}

7070
	if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_VHT]))
7071
		req.flags |= ASSOC_REQ_DISABLE_VHT;
7072 7073

	if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
7074 7075 7076
		memcpy(&req.vht_capa_mask,
		       nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]),
		       sizeof(req.vht_capa_mask));
7077 7078

	if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) {
7079
		if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
7080
			return -EINVAL;
7081 7082 7083
		memcpy(&req.vht_capa,
		       nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]),
		       sizeof(req.vht_capa));
7084 7085
	}

7086 7087 7088 7089 7090 7091 7092 7093
	if (nla_get_flag(info->attrs[NL80211_ATTR_USE_RRM])) {
		if (!(rdev->wiphy.features &
		      NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) ||
		    !(rdev->wiphy.features & NL80211_FEATURE_QUIET))
			return -EINVAL;
		req.flags |= ASSOC_REQ_USE_RRM;
	}

7094
	err = nl80211_crypto_settings(rdev, info, &req.crypto, 1);
7095 7096
	if (!err) {
		wdev_lock(dev->ieee80211_ptr);
7097 7098
		err = cfg80211_mlme_assoc(rdev, dev, chan, bssid,
					  ssid, ssid_len, &req);
7099 7100
		wdev_unlock(dev->ieee80211_ptr);
	}
7101 7102 7103 7104 7105 7106

	return err;
}

static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
{
7107 7108
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
7109
	const u8 *ie = NULL, *bssid;
7110
	int ie_len = 0, err;
7111
	u16 reason_code;
7112
	bool local_state_change;
7113

7114 7115 7116 7117 7118 7119 7120 7121 7122
	if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
		return -EINVAL;

	if (!info->attrs[NL80211_ATTR_MAC])
		return -EINVAL;

	if (!info->attrs[NL80211_ATTR_REASON_CODE])
		return -EINVAL;

7123 7124
	if (!rdev->ops->deauth)
		return -EOPNOTSUPP;
7125

7126
	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
7127 7128
	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
		return -EOPNOTSUPP;
7129

7130
	bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
7131

7132 7133
	reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
	if (reason_code == 0) {
7134
		/* Reason Code 0 is reserved */
7135
		return -EINVAL;
7136
	}
7137 7138

	if (info->attrs[NL80211_ATTR_IE]) {
7139 7140
		ie = nla_data(info->attrs[NL80211_ATTR_IE]);
		ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
7141 7142
	}

7143 7144
	local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];

7145 7146 7147 7148 7149
	wdev_lock(dev->ieee80211_ptr);
	err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code,
				   local_state_change);
	wdev_unlock(dev->ieee80211_ptr);
	return err;
7150 7151 7152 7153
}

static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
{
7154 7155
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
7156
	const u8 *ie = NULL, *bssid;
7157
	int ie_len = 0, err;
7158
	u16 reason_code;
7159
	bool local_state_change;
7160

7161 7162 7163 7164 7165 7166 7167 7168 7169
	if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
		return -EINVAL;

	if (!info->attrs[NL80211_ATTR_MAC])
		return -EINVAL;

	if (!info->attrs[NL80211_ATTR_REASON_CODE])
		return -EINVAL;

7170 7171
	if (!rdev->ops->disassoc)
		return -EOPNOTSUPP;
7172

7173
	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
7174 7175
	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
		return -EOPNOTSUPP;
7176

7177
	bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
7178

7179 7180
	reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
	if (reason_code == 0) {
7181
		/* Reason Code 0 is reserved */
7182
		return -EINVAL;
7183
	}
7184 7185

	if (info->attrs[NL80211_ATTR_IE]) {
7186 7187
		ie = nla_data(info->attrs[NL80211_ATTR_IE]);
		ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
7188 7189
	}

7190 7191
	local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];

7192 7193 7194 7195 7196
	wdev_lock(dev->ieee80211_ptr);
	err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code,
				     local_state_change);
	wdev_unlock(dev->ieee80211_ptr);
	return err;
7197 7198
}

7199 7200 7201 7202 7203 7204 7205 7206 7207 7208 7209 7210 7211 7212 7213 7214 7215 7216 7217 7218 7219 7220 7221 7222 7223 7224 7225 7226
static bool
nl80211_parse_mcast_rate(struct cfg80211_registered_device *rdev,
			 int mcast_rate[IEEE80211_NUM_BANDS],
			 int rateval)
{
	struct wiphy *wiphy = &rdev->wiphy;
	bool found = false;
	int band, i;

	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
		struct ieee80211_supported_band *sband;

		sband = wiphy->bands[band];
		if (!sband)
			continue;

		for (i = 0; i < sband->n_bitrates; i++) {
			if (sband->bitrates[i].bitrate == rateval) {
				mcast_rate[band] = i + 1;
				found = true;
				break;
			}
		}
	}

	return found;
}

7227 7228
static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
{
7229 7230
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
7231 7232
	struct cfg80211_ibss_params ibss;
	struct wiphy *wiphy;
7233
	struct cfg80211_cached_keys *connkeys = NULL;
7234 7235
	int err;

7236 7237
	memset(&ibss, 0, sizeof(ibss));

7238 7239 7240
	if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
		return -EINVAL;

7241
	if (!info->attrs[NL80211_ATTR_SSID] ||
7242 7243 7244
	    !nla_len(info->attrs[NL80211_ATTR_SSID]))
		return -EINVAL;

7245 7246 7247 7248 7249 7250 7251 7252 7253
	ibss.beacon_interval = 100;

	if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
		ibss.beacon_interval =
			nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
		if (ibss.beacon_interval < 1 || ibss.beacon_interval > 10000)
			return -EINVAL;
	}

7254 7255
	if (!rdev->ops->join_ibss)
		return -EOPNOTSUPP;
7256

7257 7258
	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
		return -EOPNOTSUPP;
7259

7260
	wiphy = &rdev->wiphy;
7261

7262
	if (info->attrs[NL80211_ATTR_MAC]) {
7263
		ibss.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
7264 7265 7266 7267

		if (!is_valid_ether_addr(ibss.bssid))
			return -EINVAL;
	}
7268 7269 7270 7271 7272 7273 7274 7275
	ibss.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
	ibss.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);

	if (info->attrs[NL80211_ATTR_IE]) {
		ibss.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
		ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
	}

7276 7277 7278
	err = nl80211_parse_chandef(rdev, info, &ibss.chandef);
	if (err)
		return err;
7279

7280 7281
	if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef,
				     NL80211_IFTYPE_ADHOC))
7282 7283
		return -EINVAL;

7284
	switch (ibss.chandef.width) {
7285 7286
	case NL80211_CHAN_WIDTH_5:
	case NL80211_CHAN_WIDTH_10:
7287 7288 7289 7290
	case NL80211_CHAN_WIDTH_20_NOHT:
		break;
	case NL80211_CHAN_WIDTH_20:
	case NL80211_CHAN_WIDTH_40:
7291 7292 7293 7294 7295 7296 7297 7298 7299 7300 7301 7302
		if (!(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS))
			return -EINVAL;
		break;
	case NL80211_CHAN_WIDTH_80:
	case NL80211_CHAN_WIDTH_80P80:
	case NL80211_CHAN_WIDTH_160:
		if (!(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS))
			return -EINVAL;
		if (!wiphy_ext_feature_isset(&rdev->wiphy,
					     NL80211_EXT_FEATURE_VHT_IBSS))
			return -EINVAL;
		break;
7303
	default:
7304
		return -EINVAL;
7305
	}
7306

7307
	ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
7308 7309
	ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];

7310 7311 7312 7313 7314 7315
	if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
		u8 *rates =
			nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
		int n_rates =
			nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
		struct ieee80211_supported_band *sband =
7316
			wiphy->bands[ibss.chandef.chan->band];
7317

7318 7319 7320 7321
		err = ieee80211_get_ratemask(sband, rates, n_rates,
					     &ibss.basic_rates);
		if (err)
			return err;
7322
	}
7323

7324 7325 7326 7327 7328 7329 7330 7331 7332 7333 7334 7335 7336
	if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
		memcpy(&ibss.ht_capa_mask,
		       nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
		       sizeof(ibss.ht_capa_mask));

	if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
		if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
			return -EINVAL;
		memcpy(&ibss.ht_capa,
		       nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
		       sizeof(ibss.ht_capa));
	}

7337 7338 7339 7340
	if (info->attrs[NL80211_ATTR_MCAST_RATE] &&
	    !nl80211_parse_mcast_rate(rdev, ibss.mcast_rate,
			nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE])))
		return -EINVAL;
7341

7342
	if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {
7343 7344
		bool no_ht = false;

7345
		connkeys = nl80211_parse_connkeys(rdev,
7346 7347
					  info->attrs[NL80211_ATTR_KEYS],
					  &no_ht);
7348 7349
		if (IS_ERR(connkeys))
			return PTR_ERR(connkeys);
7350

7351 7352
		if ((ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) &&
		    no_ht) {
7353 7354 7355
			kfree(connkeys);
			return -EINVAL;
		}
7356
	}
7357

7358 7359 7360
	ibss.control_port =
		nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT]);

7361 7362 7363
	ibss.userspace_handles_dfs =
		nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS]);

7364
	err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
7365
	if (err)
7366
		kzfree(connkeys);
7367 7368 7369 7370 7371
	return err;
}

static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info)
{
7372 7373
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
7374

7375 7376
	if (!rdev->ops->leave_ibss)
		return -EOPNOTSUPP;
7377

7378 7379
	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
		return -EOPNOTSUPP;
7380

7381
	return cfg80211_leave_ibss(rdev, dev, false);
7382 7383
}

7384 7385 7386 7387 7388 7389 7390 7391 7392 7393 7394 7395 7396 7397 7398 7399 7400 7401 7402 7403 7404 7405 7406 7407 7408 7409 7410 7411 7412
static int nl80211_set_mcast_rate(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
	int mcast_rate[IEEE80211_NUM_BANDS];
	u32 nla_rate;
	int err;

	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC &&
	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
		return -EOPNOTSUPP;

	if (!rdev->ops->set_mcast_rate)
		return -EOPNOTSUPP;

	memset(mcast_rate, 0, sizeof(mcast_rate));

	if (!info->attrs[NL80211_ATTR_MCAST_RATE])
		return -EINVAL;

	nla_rate = nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE]);
	if (!nl80211_parse_mcast_rate(rdev, mcast_rate, nla_rate))
		return -EINVAL;

	err = rdev->ops->set_mcast_rate(&rdev->wiphy, dev, mcast_rate);

	return err;
}

7413 7414
static struct sk_buff *
__cfg80211_alloc_vendor_skb(struct cfg80211_registered_device *rdev,
7415 7416
			    struct wireless_dev *wdev, int approxlen,
			    u32 portid, u32 seq, enum nl80211_commands cmd,
7417 7418 7419
			    enum nl80211_attrs attr,
			    const struct nl80211_vendor_cmd_info *info,
			    gfp_t gfp)
7420 7421 7422 7423 7424 7425 7426 7427 7428 7429 7430 7431 7432 7433 7434 7435 7436
{
	struct sk_buff *skb;
	void *hdr;
	struct nlattr *data;

	skb = nlmsg_new(approxlen + 100, gfp);
	if (!skb)
		return NULL;

	hdr = nl80211hdr_put(skb, portid, seq, 0, cmd);
	if (!hdr) {
		kfree_skb(skb);
		return NULL;
	}

	if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
		goto nla_put_failure;
7437 7438 7439 7440 7441 7442 7443 7444 7445 7446

	if (info) {
		if (nla_put_u32(skb, NL80211_ATTR_VENDOR_ID,
				info->vendor_id))
			goto nla_put_failure;
		if (nla_put_u32(skb, NL80211_ATTR_VENDOR_SUBCMD,
				info->subcmd))
			goto nla_put_failure;
	}

7447 7448 7449 7450 7451 7452 7453 7454 7455 7456
	if (wdev) {
		if (nla_put_u64(skb, NL80211_ATTR_WDEV,
				wdev_id(wdev)))
			goto nla_put_failure;
		if (wdev->netdev &&
		    nla_put_u32(skb, NL80211_ATTR_IFINDEX,
				wdev->netdev->ifindex))
			goto nla_put_failure;
	}

7457 7458 7459 7460 7461 7462 7463 7464 7465 7466 7467 7468
	data = nla_nest_start(skb, attr);

	((void **)skb->cb)[0] = rdev;
	((void **)skb->cb)[1] = hdr;
	((void **)skb->cb)[2] = data;

	return skb;

 nla_put_failure:
	kfree_skb(skb);
	return NULL;
}
7469

7470
struct sk_buff *__cfg80211_alloc_event_skb(struct wiphy *wiphy,
7471
					   struct wireless_dev *wdev,
7472 7473 7474 7475 7476
					   enum nl80211_commands cmd,
					   enum nl80211_attrs attr,
					   int vendor_event_idx,
					   int approxlen, gfp_t gfp)
{
7477
	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
7478 7479 7480 7481 7482 7483 7484 7485 7486 7487 7488 7489 7490 7491 7492 7493 7494 7495 7496
	const struct nl80211_vendor_cmd_info *info;

	switch (cmd) {
	case NL80211_CMD_TESTMODE:
		if (WARN_ON(vendor_event_idx != -1))
			return NULL;
		info = NULL;
		break;
	case NL80211_CMD_VENDOR:
		if (WARN_ON(vendor_event_idx < 0 ||
			    vendor_event_idx >= wiphy->n_vendor_events))
			return NULL;
		info = &wiphy->vendor_events[vendor_event_idx];
		break;
	default:
		WARN_ON(1);
		return NULL;
	}

7497
	return __cfg80211_alloc_vendor_skb(rdev, wdev, approxlen, 0, 0,
7498 7499 7500 7501 7502 7503 7504 7505 7506 7507 7508
					   cmd, attr, info, gfp);
}
EXPORT_SYMBOL(__cfg80211_alloc_event_skb);

void __cfg80211_send_event_skb(struct sk_buff *skb, gfp_t gfp)
{
	struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
	void *hdr = ((void **)skb->cb)[1];
	struct nlattr *data = ((void **)skb->cb)[2];
	enum nl80211_multicast_groups mcgrp = NL80211_MCGRP_TESTMODE;

7509 7510 7511
	/* clear CB data for netlink core to own from now on */
	memset(skb->cb, 0, sizeof(skb->cb));

7512 7513 7514 7515 7516 7517 7518 7519 7520 7521 7522
	nla_nest_end(skb, data);
	genlmsg_end(skb, hdr);

	if (data->nla_type == NL80211_ATTR_VENDOR_DATA)
		mcgrp = NL80211_MCGRP_VENDOR;

	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), skb, 0,
				mcgrp, gfp);
}
EXPORT_SYMBOL(__cfg80211_send_event_skb);

7523 7524 7525
#ifdef CONFIG_NL80211_TESTMODE
static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
{
7526
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
7527 7528
	struct wireless_dev *wdev =
		__cfg80211_wdev_from_attrs(genl_info_net(info), info->attrs);
7529 7530
	int err;

7531 7532 7533 7534 7535 7536 7537 7538 7539 7540 7541 7542
	if (!rdev->ops->testmode_cmd)
		return -EOPNOTSUPP;

	if (IS_ERR(wdev)) {
		err = PTR_ERR(wdev);
		if (err != -EINVAL)
			return err;
		wdev = NULL;
	} else if (wdev->wiphy != &rdev->wiphy) {
		return -EINVAL;
	}

7543 7544 7545
	if (!info->attrs[NL80211_ATTR_TESTDATA])
		return -EINVAL;

7546
	rdev->cur_cmd_info = info;
7547
	err = rdev_testmode_cmd(rdev, wdev,
7548 7549
				nla_data(info->attrs[NL80211_ATTR_TESTDATA]),
				nla_len(info->attrs[NL80211_ATTR_TESTDATA]));
7550
	rdev->cur_cmd_info = NULL;
7551 7552 7553 7554

	return err;
}

7555 7556 7557
static int nl80211_testmode_dump(struct sk_buff *skb,
				 struct netlink_callback *cb)
{
7558
	struct cfg80211_registered_device *rdev;
7559 7560 7561 7562 7563
	int err;
	long phy_idx;
	void *data = NULL;
	int data_len = 0;

7564 7565
	rtnl_lock();

7566 7567 7568 7569 7570 7571 7572 7573 7574 7575 7576
	if (cb->args[0]) {
		/*
		 * 0 is a valid index, but not valid for args[0],
		 * so we need to offset by 1.
		 */
		phy_idx = cb->args[0] - 1;
	} else {
		err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
				  nl80211_fam.attrbuf, nl80211_fam.maxattr,
				  nl80211_policy);
		if (err)
7577
			goto out_err;
7578

7579 7580 7581
		rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk),
						  nl80211_fam.attrbuf);
		if (IS_ERR(rdev)) {
7582 7583
			err = PTR_ERR(rdev);
			goto out_err;
7584
		}
7585 7586 7587
		phy_idx = rdev->wiphy_idx;
		rdev = NULL;

7588 7589 7590 7591 7592 7593 7594 7595 7596 7597
		if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA])
			cb->args[1] =
				(long)nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA];
	}

	if (cb->args[1]) {
		data = nla_data((void *)cb->args[1]);
		data_len = nla_len((void *)cb->args[1]);
	}

7598 7599
	rdev = cfg80211_rdev_by_wiphy_idx(phy_idx);
	if (!rdev) {
7600 7601
		err = -ENOENT;
		goto out_err;
7602 7603
	}

7604
	if (!rdev->ops->testmode_dump) {
7605 7606 7607 7608 7609
		err = -EOPNOTSUPP;
		goto out_err;
	}

	while (1) {
7610
		void *hdr = nl80211hdr_put(skb, NETLINK_CB(cb->skb).portid,
7611 7612 7613 7614
					   cb->nlh->nlmsg_seq, NLM_F_MULTI,
					   NL80211_CMD_TESTMODE);
		struct nlattr *tmdata;

7615 7616 7617
		if (!hdr)
			break;

7618
		if (nla_put_u32(skb, NL80211_ATTR_WIPHY, phy_idx)) {
7619 7620 7621 7622 7623 7624 7625 7626 7627
			genlmsg_cancel(skb, hdr);
			break;
		}

		tmdata = nla_nest_start(skb, NL80211_ATTR_TESTDATA);
		if (!tmdata) {
			genlmsg_cancel(skb, hdr);
			break;
		}
7628
		err = rdev_testmode_dump(rdev, skb, cb, data, data_len);
7629 7630 7631 7632 7633 7634 7635 7636 7637 7638 7639 7640 7641 7642 7643 7644 7645
		nla_nest_end(skb, tmdata);

		if (err == -ENOBUFS || err == -ENOENT) {
			genlmsg_cancel(skb, hdr);
			break;
		} else if (err) {
			genlmsg_cancel(skb, hdr);
			goto out_err;
		}

		genlmsg_end(skb, hdr);
	}

	err = skb->len;
	/* see above */
	cb->args[0] = phy_idx + 1;
 out_err:
7646
	rtnl_unlock();
7647 7648
	return err;
}
7649 7650
#endif

7651 7652
static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
{
7653 7654
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
7655 7656
	struct cfg80211_connect_params connect;
	struct wiphy *wiphy;
7657
	struct cfg80211_cached_keys *connkeys = NULL;
7658 7659 7660 7661 7662 7663 7664 7665 7666 7667 7668 7669 7670 7671
	int err;

	memset(&connect, 0, sizeof(connect));

	if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
		return -EINVAL;

	if (!info->attrs[NL80211_ATTR_SSID] ||
	    !nla_len(info->attrs[NL80211_ATTR_SSID]))
		return -EINVAL;

	if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
		connect.auth_type =
			nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
7672 7673
		if (!nl80211_valid_auth_type(rdev, connect.auth_type,
					     NL80211_CMD_CONNECT))
7674 7675 7676 7677 7678 7679
			return -EINVAL;
	} else
		connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;

	connect.privacy = info->attrs[NL80211_ATTR_PRIVACY];

7680
	err = nl80211_crypto_settings(rdev, info, &connect.crypto,
7681
				      NL80211_MAX_NR_CIPHER_SUITES);
7682 7683 7684
	if (err)
		return err;

7685
	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
7686 7687
	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
		return -EOPNOTSUPP;
7688

7689
	wiphy = &rdev->wiphy;
7690

7691 7692 7693 7694 7695 7696 7697
	connect.bg_scan_period = -1;
	if (info->attrs[NL80211_ATTR_BG_SCAN_PERIOD] &&
		(wiphy->flags & WIPHY_FLAG_SUPPORTS_FW_ROAM)) {
		connect.bg_scan_period =
			nla_get_u16(info->attrs[NL80211_ATTR_BG_SCAN_PERIOD]);
	}

7698 7699
	if (info->attrs[NL80211_ATTR_MAC])
		connect.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
7700 7701 7702
	else if (info->attrs[NL80211_ATTR_MAC_HINT])
		connect.bssid_hint =
			nla_data(info->attrs[NL80211_ATTR_MAC_HINT]);
7703 7704 7705 7706 7707 7708 7709 7710
	connect.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
	connect.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);

	if (info->attrs[NL80211_ATTR_IE]) {
		connect.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
		connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
	}

7711 7712 7713 7714 7715 7716 7717 7718 7719
	if (info->attrs[NL80211_ATTR_USE_MFP]) {
		connect.mfp = nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
		if (connect.mfp != NL80211_MFP_REQUIRED &&
		    connect.mfp != NL80211_MFP_NO)
			return -EINVAL;
	} else {
		connect.mfp = NL80211_MFP_NO;
	}

7720
	if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
7721 7722 7723
		connect.channel = nl80211_get_valid_chan(
			wiphy, info->attrs[NL80211_ATTR_WIPHY_FREQ]);
		if (!connect.channel)
7724 7725
			return -EINVAL;
	} else if (info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]) {
7726 7727 7728
		connect.channel_hint = nl80211_get_valid_chan(
			wiphy, info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]);
		if (!connect.channel_hint)
7729
			return -EINVAL;
7730 7731
	}

7732 7733
	if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) {
		connkeys = nl80211_parse_connkeys(rdev,
7734
					  info->attrs[NL80211_ATTR_KEYS], NULL);
7735 7736
		if (IS_ERR(connkeys))
			return PTR_ERR(connkeys);
7737 7738
	}

7739 7740 7741 7742 7743 7744 7745 7746 7747
	if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
		connect.flags |= ASSOC_REQ_DISABLE_HT;

	if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
		memcpy(&connect.ht_capa_mask,
		       nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
		       sizeof(connect.ht_capa_mask));

	if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
7748
		if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) {
7749
			kzfree(connkeys);
7750
			return -EINVAL;
7751
		}
7752 7753 7754 7755 7756
		memcpy(&connect.ht_capa,
		       nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
		       sizeof(connect.ht_capa));
	}

7757 7758 7759 7760 7761 7762 7763 7764 7765 7766
	if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_VHT]))
		connect.flags |= ASSOC_REQ_DISABLE_VHT;

	if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
		memcpy(&connect.vht_capa_mask,
		       nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]),
		       sizeof(connect.vht_capa_mask));

	if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) {
		if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) {
7767
			kzfree(connkeys);
7768 7769 7770 7771 7772 7773 7774
			return -EINVAL;
		}
		memcpy(&connect.vht_capa,
		       nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]),
		       sizeof(connect.vht_capa));
	}

7775 7776 7777 7778 7779 7780 7781 7782
	if (nla_get_flag(info->attrs[NL80211_ATTR_USE_RRM])) {
		if (!(rdev->wiphy.features &
		      NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) ||
		    !(rdev->wiphy.features & NL80211_FEATURE_QUIET))
			return -EINVAL;
		connect.flags |= ASSOC_REQ_USE_RRM;
	}

7783 7784 7785
	wdev_lock(dev->ieee80211_ptr);
	err = cfg80211_connect(rdev, dev, &connect, connkeys, NULL);
	wdev_unlock(dev->ieee80211_ptr);
7786
	if (err)
7787
		kzfree(connkeys);
7788 7789 7790 7791 7792
	return err;
}

static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info)
{
7793 7794
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
7795
	u16 reason;
7796
	int ret;
7797 7798 7799 7800 7801 7802 7803 7804 7805

	if (!info->attrs[NL80211_ATTR_REASON_CODE])
		reason = WLAN_REASON_DEAUTH_LEAVING;
	else
		reason = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);

	if (reason == 0)
		return -EINVAL;

7806
	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
7807 7808
	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
		return -EOPNOTSUPP;
7809

7810 7811 7812 7813
	wdev_lock(dev->ieee80211_ptr);
	ret = cfg80211_disconnect(rdev, dev, reason, true);
	wdev_unlock(dev->ieee80211_ptr);
	return ret;
7814 7815
}

7816 7817
static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)
{
7818
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
7819 7820 7821
	struct net *net;
	int err;

7822 7823 7824 7825 7826 7827
	if (info->attrs[NL80211_ATTR_PID]) {
		u32 pid = nla_get_u32(info->attrs[NL80211_ATTR_PID]);

		net = get_net_ns_by_pid(pid);
	} else if (info->attrs[NL80211_ATTR_NETNS_FD]) {
		u32 fd = nla_get_u32(info->attrs[NL80211_ATTR_NETNS_FD]);
7828

7829 7830 7831 7832
		net = get_net_ns_by_fd(fd);
	} else {
		return -EINVAL;
	}
7833

7834 7835
	if (IS_ERR(net))
		return PTR_ERR(net);
7836 7837 7838 7839

	err = 0;

	/* check if anything to do */
7840 7841
	if (!net_eq(wiphy_net(&rdev->wiphy), net))
		err = cfg80211_switch_netns(rdev, net);
7842 7843 7844 7845 7846

	put_net(net);
	return err;
}

7847 7848
static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info)
{
7849
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
7850 7851
	int (*rdev_ops)(struct wiphy *wiphy, struct net_device *dev,
			struct cfg80211_pmksa *pmksa) = NULL;
7852
	struct net_device *dev = info->user_ptr[1];
7853 7854 7855 7856 7857 7858 7859 7860 7861 7862 7863 7864 7865
	struct cfg80211_pmksa pmksa;

	memset(&pmksa, 0, sizeof(struct cfg80211_pmksa));

	if (!info->attrs[NL80211_ATTR_MAC])
		return -EINVAL;

	if (!info->attrs[NL80211_ATTR_PMKID])
		return -EINVAL;

	pmksa.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]);
	pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);

7866
	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
7867 7868
	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
		return -EOPNOTSUPP;
7869 7870 7871 7872 7873 7874 7875 7876 7877 7878 7879 7880 7881

	switch (info->genlhdr->cmd) {
	case NL80211_CMD_SET_PMKSA:
		rdev_ops = rdev->ops->set_pmksa;
		break;
	case NL80211_CMD_DEL_PMKSA:
		rdev_ops = rdev->ops->del_pmksa;
		break;
	default:
		WARN_ON(1);
		break;
	}

7882 7883
	if (!rdev_ops)
		return -EOPNOTSUPP;
7884

7885
	return rdev_ops(&rdev->wiphy, dev, &pmksa);
7886 7887 7888 7889
}

static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info)
{
7890 7891
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
7892

7893
	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
7894 7895
	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
		return -EOPNOTSUPP;
7896

7897 7898
	if (!rdev->ops->flush_pmksa)
		return -EOPNOTSUPP;
7899

7900
	return rdev_flush_pmksa(rdev, dev);
7901 7902
}

7903 7904 7905 7906 7907
static int nl80211_tdls_mgmt(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
	u8 action_code, dialog_token;
7908
	u32 peer_capability = 0;
7909 7910
	u16 status_code;
	u8 *peer;
7911
	bool initiator;
7912 7913 7914 7915 7916 7917 7918 7919 7920 7921 7922 7923 7924 7925 7926 7927

	if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) ||
	    !rdev->ops->tdls_mgmt)
		return -EOPNOTSUPP;

	if (!info->attrs[NL80211_ATTR_TDLS_ACTION] ||
	    !info->attrs[NL80211_ATTR_STATUS_CODE] ||
	    !info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN] ||
	    !info->attrs[NL80211_ATTR_IE] ||
	    !info->attrs[NL80211_ATTR_MAC])
		return -EINVAL;

	peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
	action_code = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_ACTION]);
	status_code = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
	dialog_token = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN]);
7928
	initiator = nla_get_flag(info->attrs[NL80211_ATTR_TDLS_INITIATOR]);
7929 7930 7931
	if (info->attrs[NL80211_ATTR_TDLS_PEER_CAPABILITY])
		peer_capability =
			nla_get_u32(info->attrs[NL80211_ATTR_TDLS_PEER_CAPABILITY]);
7932

7933
	return rdev_tdls_mgmt(rdev, dev, peer, action_code,
7934
			      dialog_token, status_code, peer_capability,
7935
			      initiator,
7936 7937
			      nla_data(info->attrs[NL80211_ATTR_IE]),
			      nla_len(info->attrs[NL80211_ATTR_IE]));
7938 7939 7940 7941 7942 7943 7944 7945 7946 7947 7948 7949 7950 7951 7952 7953 7954 7955 7956 7957
}

static int nl80211_tdls_oper(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
	enum nl80211_tdls_operation operation;
	u8 *peer;

	if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) ||
	    !rdev->ops->tdls_oper)
		return -EOPNOTSUPP;

	if (!info->attrs[NL80211_ATTR_TDLS_OPERATION] ||
	    !info->attrs[NL80211_ATTR_MAC])
		return -EINVAL;

	operation = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_OPERATION]);
	peer = nla_data(info->attrs[NL80211_ATTR_MAC]);

7958
	return rdev_tdls_oper(rdev, dev, peer, operation);
7959 7960
}

7961 7962 7963
static int nl80211_remain_on_channel(struct sk_buff *skb,
				     struct genl_info *info)
{
7964
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
7965
	struct wireless_dev *wdev = info->user_ptr[1];
7966
	struct cfg80211_chan_def chandef;
7967 7968 7969
	struct sk_buff *msg;
	void *hdr;
	u64 cookie;
7970
	u32 duration;
7971 7972 7973 7974 7975 7976 7977 7978
	int err;

	if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
	    !info->attrs[NL80211_ATTR_DURATION])
		return -EINVAL;

	duration = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);

7979 7980 7981 7982
	if (!rdev->ops->remain_on_channel ||
	    !(rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL))
		return -EOPNOTSUPP;

7983
	/*
7984 7985
	 * We should be on that channel for at least a minimum amount of
	 * time (10ms) but no longer than the driver supports.
7986
	 */
7987
	if (duration < NL80211_MIN_REMAIN_ON_CHANNEL_TIME ||
7988
	    duration > rdev->wiphy.max_remain_on_channel_duration)
7989 7990
		return -EINVAL;

7991 7992 7993
	err = nl80211_parse_chandef(rdev, info, &chandef);
	if (err)
		return err;
7994 7995

	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7996 7997
	if (!msg)
		return -ENOMEM;
7998

7999
	hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
8000
			     NL80211_CMD_REMAIN_ON_CHANNEL);
8001 8002
	if (!hdr) {
		err = -ENOBUFS;
8003 8004 8005
		goto free_msg;
	}

8006 8007
	err = rdev_remain_on_channel(rdev, wdev, chandef.chan,
				     duration, &cookie);
8008 8009 8010 8011

	if (err)
		goto free_msg;

8012 8013
	if (nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie))
		goto nla_put_failure;
8014 8015

	genlmsg_end(msg, hdr);
8016 8017

	return genlmsg_reply(msg, info);
8018 8019 8020 8021 8022 8023 8024 8025 8026 8027 8028

 nla_put_failure:
	err = -ENOBUFS;
 free_msg:
	nlmsg_free(msg);
	return err;
}

static int nl80211_cancel_remain_on_channel(struct sk_buff *skb,
					    struct genl_info *info)
{
8029
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
8030
	struct wireless_dev *wdev = info->user_ptr[1];
8031 8032 8033 8034 8035
	u64 cookie;

	if (!info->attrs[NL80211_ATTR_COOKIE])
		return -EINVAL;

8036 8037
	if (!rdev->ops->cancel_remain_on_channel)
		return -EOPNOTSUPP;
8038 8039 8040

	cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);

8041
	return rdev_cancel_remain_on_channel(rdev, wdev, cookie);
8042 8043
}

8044 8045 8046 8047 8048 8049 8050 8051 8052 8053 8054 8055 8056 8057 8058 8059 8060 8061 8062 8063 8064 8065 8066 8067
static u32 rateset_to_mask(struct ieee80211_supported_band *sband,
			   u8 *rates, u8 rates_len)
{
	u8 i;
	u32 mask = 0;

	for (i = 0; i < rates_len; i++) {
		int rate = (rates[i] & 0x7f) * 5;
		int ridx;
		for (ridx = 0; ridx < sband->n_bitrates; ridx++) {
			struct ieee80211_rate *srate =
				&sband->bitrates[ridx];
			if (rate == srate->bitrate) {
				mask |= 1 << ridx;
				break;
			}
		}
		if (ridx == sband->n_bitrates)
			return 0; /* rate not found */
	}

	return mask;
}

8068 8069 8070 8071 8072 8073 8074 8075 8076 8077 8078 8079 8080 8081 8082
static bool ht_rateset_to_mask(struct ieee80211_supported_band *sband,
			       u8 *rates, u8 rates_len,
			       u8 mcs[IEEE80211_HT_MCS_MASK_LEN])
{
	u8 i;

	memset(mcs, 0, IEEE80211_HT_MCS_MASK_LEN);

	for (i = 0; i < rates_len; i++) {
		int ridx, rbit;

		ridx = rates[i] / 8;
		rbit = BIT(rates[i] % 8);

		/* check validity */
8083
		if ((ridx < 0) || (ridx >= IEEE80211_HT_MCS_MASK_LEN))
8084 8085 8086 8087 8088 8089 8090 8091 8092 8093 8094 8095
			return false;

		/* check availability */
		if (sband->ht_cap.mcs.rx_mask[ridx] & rbit)
			mcs[ridx] |= rbit;
		else
			return false;
	}

	return true;
}

8096 8097 8098 8099 8100 8101 8102 8103 8104 8105 8106 8107 8108 8109 8110 8111 8112 8113 8114 8115 8116 8117 8118 8119 8120 8121 8122 8123 8124 8125 8126 8127 8128 8129 8130 8131 8132 8133 8134 8135 8136 8137 8138 8139 8140 8141 8142 8143 8144 8145 8146 8147 8148 8149 8150 8151 8152 8153 8154 8155
static u16 vht_mcs_map_to_mcs_mask(u8 vht_mcs_map)
{
	u16 mcs_mask = 0;

	switch (vht_mcs_map) {
	case IEEE80211_VHT_MCS_NOT_SUPPORTED:
		break;
	case IEEE80211_VHT_MCS_SUPPORT_0_7:
		mcs_mask = 0x00FF;
		break;
	case IEEE80211_VHT_MCS_SUPPORT_0_8:
		mcs_mask = 0x01FF;
		break;
	case IEEE80211_VHT_MCS_SUPPORT_0_9:
		mcs_mask = 0x03FF;
		break;
	default:
		break;
	}

	return mcs_mask;
}

static void vht_build_mcs_mask(u16 vht_mcs_map,
			       u16 vht_mcs_mask[NL80211_VHT_NSS_MAX])
{
	u8 nss;

	for (nss = 0; nss < NL80211_VHT_NSS_MAX; nss++) {
		vht_mcs_mask[nss] = vht_mcs_map_to_mcs_mask(vht_mcs_map & 0x03);
		vht_mcs_map >>= 2;
	}
}

static bool vht_set_mcs_mask(struct ieee80211_supported_band *sband,
			     struct nl80211_txrate_vht *txrate,
			     u16 mcs[NL80211_VHT_NSS_MAX])
{
	u16 tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
	u16 tx_mcs_mask[NL80211_VHT_NSS_MAX] = {};
	u8 i;

	if (!sband->vht_cap.vht_supported)
		return false;

	memset(mcs, 0, sizeof(u16) * NL80211_VHT_NSS_MAX);

	/* Build vht_mcs_mask from VHT capabilities */
	vht_build_mcs_mask(tx_mcs_map, tx_mcs_mask);

	for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
		if ((tx_mcs_mask[i] & txrate->mcs[i]) == txrate->mcs[i])
			mcs[i] = txrate->mcs[i];
		else
			return false;
	}

	return true;
}

Alexey Dobriyan's avatar
Alexey Dobriyan committed
8156
static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = {
8157 8158
	[NL80211_TXRATE_LEGACY] = { .type = NLA_BINARY,
				    .len = NL80211_MAX_SUPP_RATES },
8159 8160
	[NL80211_TXRATE_HT] = { .type = NLA_BINARY,
				.len = NL80211_MAX_SUPP_HT_RATES },
8161
	[NL80211_TXRATE_VHT] = { .len = sizeof(struct nl80211_txrate_vht)},
8162
	[NL80211_TXRATE_GI] = { .type = NLA_U8 },
8163 8164 8165 8166 8167 8168
};

static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
				       struct genl_info *info)
{
	struct nlattr *tb[NL80211_TXRATE_MAX + 1];
8169
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
8170
	struct cfg80211_bitrate_mask mask;
8171 8172
	int rem, i;
	struct net_device *dev = info->user_ptr[1];
8173 8174
	struct nlattr *tx_rates;
	struct ieee80211_supported_band *sband;
8175
	u16 vht_tx_mcs_map;
8176

8177 8178
	if (!rdev->ops->set_bitrate_mask)
		return -EOPNOTSUPP;
8179 8180 8181 8182 8183

	memset(&mask, 0, sizeof(mask));
	/* Default to all rates enabled */
	for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
		sband = rdev->wiphy.bands[i];
8184 8185 8186 8187 8188

		if (!sband)
			continue;

		mask.control[i].legacy = (1 << sband->n_bitrates) - 1;
8189
		memcpy(mask.control[i].ht_mcs,
8190
		       sband->ht_cap.mcs.rx_mask,
8191
		       sizeof(mask.control[i].ht_mcs));
8192 8193 8194 8195 8196 8197

		if (!sband->vht_cap.vht_supported)
			continue;

		vht_tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
		vht_build_mcs_mask(vht_tx_mcs_map, mask.control[i].vht_mcs);
8198 8199
	}

8200 8201 8202 8203
	/* if no rates are given set it back to the defaults */
	if (!info->attrs[NL80211_ATTR_TX_RATES])
		goto out;

8204 8205 8206 8207
	/*
	 * The nested attribute uses enum nl80211_band as the index. This maps
	 * directly to the enum ieee80211_band values used in cfg80211.
	 */
8208
	BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8);
8209
	nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) {
8210
		enum ieee80211_band band = nla_type(tx_rates);
8211 8212
		int err;

8213 8214
		if (band < 0 || band >= IEEE80211_NUM_BANDS)
			return -EINVAL;
8215
		sband = rdev->wiphy.bands[band];
8216 8217
		if (sband == NULL)
			return -EINVAL;
8218 8219 8220 8221
		err = nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates),
				nla_len(tx_rates), nl80211_txattr_policy);
		if (err)
			return err;
8222 8223 8224 8225 8226
		if (tb[NL80211_TXRATE_LEGACY]) {
			mask.control[band].legacy = rateset_to_mask(
				sband,
				nla_data(tb[NL80211_TXRATE_LEGACY]),
				nla_len(tb[NL80211_TXRATE_LEGACY]));
8227 8228 8229
			if ((mask.control[band].legacy == 0) &&
			    nla_len(tb[NL80211_TXRATE_LEGACY]))
				return -EINVAL;
8230
		}
8231
		if (tb[NL80211_TXRATE_HT]) {
8232 8233
			if (!ht_rateset_to_mask(
					sband,
8234 8235 8236
					nla_data(tb[NL80211_TXRATE_HT]),
					nla_len(tb[NL80211_TXRATE_HT]),
					mask.control[band].ht_mcs))
8237 8238
				return -EINVAL;
		}
8239 8240 8241 8242 8243 8244 8245
		if (tb[NL80211_TXRATE_VHT]) {
			if (!vht_set_mcs_mask(
					sband,
					nla_data(tb[NL80211_TXRATE_VHT]),
					mask.control[band].vht_mcs))
				return -EINVAL;
		}
8246 8247 8248 8249 8250 8251
		if (tb[NL80211_TXRATE_GI]) {
			mask.control[band].gi =
				nla_get_u8(tb[NL80211_TXRATE_GI]);
			if (mask.control[band].gi > NL80211_TXRATE_FORCE_LGI)
				return -EINVAL;
		}
8252 8253

		if (mask.control[band].legacy == 0) {
8254 8255 8256 8257 8258
			/* don't allow empty legacy rates if HT or VHT
			 * are not even supported.
			 */
			if (!(rdev->wiphy.bands[band]->ht_cap.ht_supported ||
			      rdev->wiphy.bands[band]->vht_cap.vht_supported))
8259 8260 8261
				return -EINVAL;

			for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++)
8262
				if (mask.control[band].ht_mcs[i])
8263 8264 8265 8266 8267
					goto out;

			for (i = 0; i < NL80211_VHT_NSS_MAX; i++)
				if (mask.control[band].vht_mcs[i])
					goto out;
8268 8269

			/* legacy and mcs rates may not be both empty */
8270
			return -EINVAL;
8271 8272 8273
		}
	}

8274
out:
8275
	return rdev_set_bitrate_mask(rdev, dev, NULL, &mask);
8276 8277
}

8278
static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
8279
{
8280
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
8281
	struct wireless_dev *wdev = info->user_ptr[1];
8282
	u16 frame_type = IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION;
8283 8284 8285 8286

	if (!info->attrs[NL80211_ATTR_FRAME_MATCH])
		return -EINVAL;

8287 8288
	if (info->attrs[NL80211_ATTR_FRAME_TYPE])
		frame_type = nla_get_u16(info->attrs[NL80211_ATTR_FRAME_TYPE]);
8289

8290 8291 8292 8293 8294 8295 8296 8297
	switch (wdev->iftype) {
	case NL80211_IFTYPE_STATION:
	case NL80211_IFTYPE_ADHOC:
	case NL80211_IFTYPE_P2P_CLIENT:
	case NL80211_IFTYPE_AP:
	case NL80211_IFTYPE_AP_VLAN:
	case NL80211_IFTYPE_MESH_POINT:
	case NL80211_IFTYPE_P2P_GO:
8298
	case NL80211_IFTYPE_P2P_DEVICE:
8299 8300
		break;
	default:
8301
		return -EOPNOTSUPP;
8302
	}
8303 8304

	/* not much point in registering if we can't reply */
8305 8306
	if (!rdev->ops->mgmt_tx)
		return -EOPNOTSUPP;
8307

8308
	return cfg80211_mlme_register_mgmt(wdev, info->snd_portid, frame_type,
8309 8310 8311 8312
			nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]),
			nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]));
}

8313
static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
8314
{
8315
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
8316
	struct wireless_dev *wdev = info->user_ptr[1];
8317
	struct cfg80211_chan_def chandef;
8318
	int err;
8319
	void *hdr = NULL;
8320
	u64 cookie;
8321
	struct sk_buff *msg = NULL;
8322 8323 8324 8325
	struct cfg80211_mgmt_tx_params params = {
		.dont_wait_for_ack =
			info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK],
	};
8326

8327
	if (!info->attrs[NL80211_ATTR_FRAME])
8328 8329
		return -EINVAL;

8330 8331
	if (!rdev->ops->mgmt_tx)
		return -EOPNOTSUPP;
8332

8333
	switch (wdev->iftype) {
8334 8335 8336
	case NL80211_IFTYPE_P2P_DEVICE:
		if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
			return -EINVAL;
8337 8338 8339 8340 8341 8342 8343 8344 8345
	case NL80211_IFTYPE_STATION:
	case NL80211_IFTYPE_ADHOC:
	case NL80211_IFTYPE_P2P_CLIENT:
	case NL80211_IFTYPE_AP:
	case NL80211_IFTYPE_AP_VLAN:
	case NL80211_IFTYPE_MESH_POINT:
	case NL80211_IFTYPE_P2P_GO:
		break;
	default:
8346
		return -EOPNOTSUPP;
8347
	}
8348

8349
	if (info->attrs[NL80211_ATTR_DURATION]) {
8350
		if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
8351
			return -EINVAL;
8352
		params.wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
8353 8354 8355 8356 8357

		/*
		 * We should wait on the channel for at least a minimum amount
		 * of time (10ms) but no longer than the driver supports.
		 */
8358 8359
		if (params.wait < NL80211_MIN_REMAIN_ON_CHANNEL_TIME ||
		    params.wait > rdev->wiphy.max_remain_on_channel_duration)
8360 8361
			return -EINVAL;

8362 8363
	}

8364
	params.offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK];
8365

8366
	if (params.offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
8367 8368
		return -EINVAL;

8369
	params.no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
8370

8371 8372 8373 8374 8375 8376 8377 8378 8379 8380
	/* get the channel if any has been specified, otherwise pass NULL to
	 * the driver. The latter will use the current one
	 */
	chandef.chan = NULL;
	if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
		err = nl80211_parse_chandef(rdev, info, &chandef);
		if (err)
			return err;
	}

8381
	if (!chandef.chan && params.offchan)
8382
		return -EINVAL;
8383

8384 8385 8386 8387 8388 8389 8390 8391 8392 8393 8394 8395 8396 8397 8398 8399 8400 8401 8402 8403 8404
	params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
	params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]);

	if (info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]) {
		int len = nla_len(info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]);
		int i;

		if (len % sizeof(u16))
			return -EINVAL;

		params.n_csa_offsets = len / sizeof(u16);
		params.csa_offsets =
			nla_data(info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]);

		/* check that all the offsets fit the frame */
		for (i = 0; i < params.n_csa_offsets; i++) {
			if (params.csa_offsets[i] >= params.len)
				return -EINVAL;
		}
	}

8405
	if (!params.dont_wait_for_ack) {
8406 8407 8408
		msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
		if (!msg)
			return -ENOMEM;
8409

8410
		hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
8411
				     NL80211_CMD_FRAME);
8412 8413
		if (!hdr) {
			err = -ENOBUFS;
8414 8415
			goto free_msg;
		}
8416
	}
8417

8418 8419
	params.chan = chandef.chan;
	err = cfg80211_mlme_mgmt_tx(rdev, wdev, &params, &cookie);
8420 8421 8422
	if (err)
		goto free_msg;

8423
	if (msg) {
8424 8425
		if (nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie))
			goto nla_put_failure;
8426

8427 8428 8429 8430 8431
		genlmsg_end(msg, hdr);
		return genlmsg_reply(msg, info);
	}

	return 0;
8432 8433 8434 8435 8436 8437 8438 8439

 nla_put_failure:
	err = -ENOBUFS;
 free_msg:
	nlmsg_free(msg);
	return err;
}

8440 8441 8442
static int nl80211_tx_mgmt_cancel_wait(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
8443
	struct wireless_dev *wdev = info->user_ptr[1];
8444 8445 8446 8447 8448 8449 8450 8451
	u64 cookie;

	if (!info->attrs[NL80211_ATTR_COOKIE])
		return -EINVAL;

	if (!rdev->ops->mgmt_tx_cancel_wait)
		return -EOPNOTSUPP;

8452 8453 8454 8455 8456 8457 8458
	switch (wdev->iftype) {
	case NL80211_IFTYPE_STATION:
	case NL80211_IFTYPE_ADHOC:
	case NL80211_IFTYPE_P2P_CLIENT:
	case NL80211_IFTYPE_AP:
	case NL80211_IFTYPE_AP_VLAN:
	case NL80211_IFTYPE_P2P_GO:
8459
	case NL80211_IFTYPE_P2P_DEVICE:
8460 8461
		break;
	default:
8462
		return -EOPNOTSUPP;
8463
	}
8464 8465 8466

	cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);

8467
	return rdev_mgmt_tx_cancel_wait(rdev, wdev, cookie);
8468 8469
}

8470 8471
static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info)
{
8472
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
8473
	struct wireless_dev *wdev;
8474
	struct net_device *dev = info->user_ptr[1];
8475 8476 8477 8478
	u8 ps_state;
	bool state;
	int err;

8479 8480
	if (!info->attrs[NL80211_ATTR_PS_STATE])
		return -EINVAL;
8481 8482 8483

	ps_state = nla_get_u32(info->attrs[NL80211_ATTR_PS_STATE]);

8484 8485
	if (ps_state != NL80211_PS_DISABLED && ps_state != NL80211_PS_ENABLED)
		return -EINVAL;
8486 8487 8488

	wdev = dev->ieee80211_ptr;

8489 8490
	if (!rdev->ops->set_power_mgmt)
		return -EOPNOTSUPP;
8491 8492 8493 8494

	state = (ps_state == NL80211_PS_ENABLED) ? true : false;

	if (state == wdev->ps)
8495
		return 0;
8496

8497
	err = rdev_set_power_mgmt(rdev, dev, state, wdev->ps_timeout);
8498 8499
	if (!err)
		wdev->ps = state;
8500 8501 8502 8503 8504
	return err;
}

static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info)
{
8505
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
8506 8507
	enum nl80211_ps_state ps_state;
	struct wireless_dev *wdev;
8508
	struct net_device *dev = info->user_ptr[1];
8509 8510 8511 8512 8513 8514
	struct sk_buff *msg;
	void *hdr;
	int err;

	wdev = dev->ieee80211_ptr;

8515 8516
	if (!rdev->ops->set_power_mgmt)
		return -EOPNOTSUPP;
8517 8518

	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
8519 8520
	if (!msg)
		return -ENOMEM;
8521

8522
	hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
8523 8524
			     NL80211_CMD_GET_POWER_SAVE);
	if (!hdr) {
8525
		err = -ENOBUFS;
8526 8527 8528 8529 8530 8531 8532 8533
		goto free_msg;
	}

	if (wdev->ps)
		ps_state = NL80211_PS_ENABLED;
	else
		ps_state = NL80211_PS_DISABLED;

8534 8535
	if (nla_put_u32(msg, NL80211_ATTR_PS_STATE, ps_state))
		goto nla_put_failure;
8536 8537

	genlmsg_end(msg, hdr);
8538
	return genlmsg_reply(msg, info);
8539

8540
 nla_put_failure:
8541
	err = -ENOBUFS;
8542
 free_msg:
8543 8544 8545 8546
	nlmsg_free(msg);
	return err;
}

8547 8548
static const struct nla_policy
nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
8549 8550 8551
	[NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 },
	[NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 },
	[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },
8552 8553 8554
	[NL80211_ATTR_CQM_TXE_RATE] = { .type = NLA_U32 },
	[NL80211_ATTR_CQM_TXE_PKTS] = { .type = NLA_U32 },
	[NL80211_ATTR_CQM_TXE_INTVL] = { .type = NLA_U32 },
8555 8556
};

8557
static int nl80211_set_cqm_txe(struct genl_info *info,
8558
			       u32 rate, u32 pkts, u32 intvl)
8559 8560 8561
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
8562
	struct wireless_dev *wdev = dev->ieee80211_ptr;
8563

8564
	if (rate > 100 || intvl > NL80211_CQM_TXE_MAX_INTVL)
8565 8566 8567 8568 8569 8570 8571 8572 8573
		return -EINVAL;

	if (!rdev->ops->set_cqm_txe_config)
		return -EOPNOTSUPP;

	if (wdev->iftype != NL80211_IFTYPE_STATION &&
	    wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
		return -EOPNOTSUPP;

8574
	return rdev_set_cqm_txe_config(rdev, dev, rate, pkts, intvl);
8575 8576
}

8577 8578 8579
static int nl80211_set_cqm_rssi(struct genl_info *info,
				s32 threshold, u32 hysteresis)
{
8580 8581
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
8582
	struct wireless_dev *wdev = dev->ieee80211_ptr;
8583 8584 8585 8586

	if (threshold > 0)
		return -EINVAL;

8587 8588 8589
	/* disabling - hysteresis should also be zero then */
	if (threshold == 0)
		hysteresis = 0;
8590

8591 8592
	if (!rdev->ops->set_cqm_rssi_config)
		return -EOPNOTSUPP;
8593

8594
	if (wdev->iftype != NL80211_IFTYPE_STATION &&
8595 8596
	    wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
		return -EOPNOTSUPP;
8597

8598
	return rdev_set_cqm_rssi_config(rdev, dev, threshold, hysteresis);
8599 8600 8601 8602 8603 8604 8605 8606 8607
}

static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info)
{
	struct nlattr *attrs[NL80211_ATTR_CQM_MAX + 1];
	struct nlattr *cqm;
	int err;

	cqm = info->attrs[NL80211_ATTR_CQM];
8608 8609
	if (!cqm)
		return -EINVAL;
8610 8611 8612 8613

	err = nla_parse_nested(attrs, NL80211_ATTR_CQM_MAX, cqm,
			       nl80211_attr_cqm_policy);
	if (err)
8614
		return err;
8615 8616 8617

	if (attrs[NL80211_ATTR_CQM_RSSI_THOLD] &&
	    attrs[NL80211_ATTR_CQM_RSSI_HYST]) {
8618 8619
		s32 threshold = nla_get_s32(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
		u32 hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]);
8620

8621 8622 8623 8624 8625 8626 8627 8628 8629 8630 8631 8632 8633 8634
		return nl80211_set_cqm_rssi(info, threshold, hysteresis);
	}

	if (attrs[NL80211_ATTR_CQM_TXE_RATE] &&
	    attrs[NL80211_ATTR_CQM_TXE_PKTS] &&
	    attrs[NL80211_ATTR_CQM_TXE_INTVL]) {
		u32 rate = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_RATE]);
		u32 pkts = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_PKTS]);
		u32 intvl = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_INTVL]);

		return nl80211_set_cqm_txe(info, rate, pkts, intvl);
	}

	return -EINVAL;
8635 8636
}

8637 8638 8639 8640 8641 8642 8643 8644 8645 8646 8647 8648 8649 8650 8651 8652 8653 8654 8655 8656 8657 8658
static int nl80211_join_ocb(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
	struct ocb_setup setup = {};
	int err;

	err = nl80211_parse_chandef(rdev, info, &setup.chandef);
	if (err)
		return err;

	return cfg80211_join_ocb(rdev, dev, &setup);
}

static int nl80211_leave_ocb(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];

	return cfg80211_leave_ocb(rdev, dev);
}

8659 8660 8661 8662 8663
static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
	struct mesh_config cfg;
8664
	struct mesh_setup setup;
8665 8666 8667 8668
	int err;

	/* start with default */
	memcpy(&cfg, &default_mesh_config, sizeof(cfg));
8669
	memcpy(&setup, &default_mesh_setup, sizeof(setup));
8670

8671
	if (info->attrs[NL80211_ATTR_MESH_CONFIG]) {
8672
		/* and parse parameters if given */
8673
		err = nl80211_parse_mesh_config(info, &cfg, NULL);
8674 8675 8676 8677 8678 8679 8680 8681
		if (err)
			return err;
	}

	if (!info->attrs[NL80211_ATTR_MESH_ID] ||
	    !nla_len(info->attrs[NL80211_ATTR_MESH_ID]))
		return -EINVAL;

8682 8683 8684
	setup.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
	setup.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);

8685 8686 8687 8688 8689
	if (info->attrs[NL80211_ATTR_MCAST_RATE] &&
	    !nl80211_parse_mcast_rate(rdev, setup.mcast_rate,
			    nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE])))
			return -EINVAL;

8690 8691 8692 8693 8694 8695 8696 8697 8698 8699 8700 8701 8702 8703 8704
	if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
		setup.beacon_interval =
			nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
		if (setup.beacon_interval < 10 ||
		    setup.beacon_interval > 10000)
			return -EINVAL;
	}

	if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) {
		setup.dtim_period =
			nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
		if (setup.dtim_period < 1 || setup.dtim_period > 100)
			return -EINVAL;
	}

8705 8706 8707 8708 8709 8710 8711
	if (info->attrs[NL80211_ATTR_MESH_SETUP]) {
		/* parse additional setup parameters if given */
		err = nl80211_parse_mesh_setup(info, &setup);
		if (err)
			return err;
	}

8712 8713 8714
	if (setup.user_mpm)
		cfg.auto_open_plinks = false;

8715
	if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
8716 8717 8718
		err = nl80211_parse_chandef(rdev, info, &setup.chandef);
		if (err)
			return err;
8719 8720
	} else {
		/* cfg80211_join_mesh() will sort it out */
8721
		setup.chandef.chan = NULL;
8722 8723
	}

8724 8725 8726 8727 8728 8729 8730 8731 8732 8733 8734 8735 8736 8737 8738 8739 8740
	if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
		u8 *rates = nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
		int n_rates =
			nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
		struct ieee80211_supported_band *sband;

		if (!setup.chandef.chan)
			return -EINVAL;

		sband = rdev->wiphy.bands[setup.chandef.chan->band];

		err = ieee80211_get_ratemask(sband, rates, n_rates,
					     &setup.basic_rates);
		if (err)
			return err;
	}

8741
	return cfg80211_join_mesh(rdev, dev, &setup, &cfg);
8742 8743 8744 8745 8746 8747 8748 8749 8750 8751
}

static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];

	return cfg80211_leave_mesh(rdev, dev);
}

8752
#ifdef CONFIG_PM
8753 8754 8755
static int nl80211_send_wowlan_patterns(struct sk_buff *msg,
					struct cfg80211_registered_device *rdev)
{
8756
	struct cfg80211_wowlan *wowlan = rdev->wiphy.wowlan_config;
8757 8758 8759
	struct nlattr *nl_pats, *nl_pat;
	int i, pat_len;

8760
	if (!wowlan->n_patterns)
8761 8762 8763 8764 8765 8766
		return 0;

	nl_pats = nla_nest_start(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN);
	if (!nl_pats)
		return -ENOBUFS;

8767
	for (i = 0; i < wowlan->n_patterns; i++) {
8768 8769 8770
		nl_pat = nla_nest_start(msg, i + 1);
		if (!nl_pat)
			return -ENOBUFS;
8771
		pat_len = wowlan->patterns[i].pattern_len;
8772
		if (nla_put(msg, NL80211_PKTPAT_MASK, DIV_ROUND_UP(pat_len, 8),
8773
			    wowlan->patterns[i].mask) ||
8774 8775 8776
		    nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len,
			    wowlan->patterns[i].pattern) ||
		    nla_put_u32(msg, NL80211_PKTPAT_OFFSET,
8777
				wowlan->patterns[i].pkt_offset))
8778 8779 8780 8781 8782 8783 8784 8785
			return -ENOBUFS;
		nla_nest_end(msg, nl_pat);
	}
	nla_nest_end(msg, nl_pats);

	return 0;
}

8786 8787 8788 8789 8790 8791 8792 8793 8794 8795 8796 8797
static int nl80211_send_wowlan_tcp(struct sk_buff *msg,
				   struct cfg80211_wowlan_tcp *tcp)
{
	struct nlattr *nl_tcp;

	if (!tcp)
		return 0;

	nl_tcp = nla_nest_start(msg, NL80211_WOWLAN_TRIG_TCP_CONNECTION);
	if (!nl_tcp)
		return -ENOBUFS;

8798 8799
	if (nla_put_in_addr(msg, NL80211_WOWLAN_TCP_SRC_IPV4, tcp->src) ||
	    nla_put_in_addr(msg, NL80211_WOWLAN_TCP_DST_IPV4, tcp->dst) ||
8800 8801 8802 8803 8804 8805 8806 8807 8808 8809 8810 8811 8812 8813 8814 8815 8816 8817 8818 8819 8820 8821 8822 8823
	    nla_put(msg, NL80211_WOWLAN_TCP_DST_MAC, ETH_ALEN, tcp->dst_mac) ||
	    nla_put_u16(msg, NL80211_WOWLAN_TCP_SRC_PORT, tcp->src_port) ||
	    nla_put_u16(msg, NL80211_WOWLAN_TCP_DST_PORT, tcp->dst_port) ||
	    nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
		    tcp->payload_len, tcp->payload) ||
	    nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL,
			tcp->data_interval) ||
	    nla_put(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD,
		    tcp->wake_len, tcp->wake_data) ||
	    nla_put(msg, NL80211_WOWLAN_TCP_WAKE_MASK,
		    DIV_ROUND_UP(tcp->wake_len, 8), tcp->wake_mask))
		return -ENOBUFS;

	if (tcp->payload_seq.len &&
	    nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ,
		    sizeof(tcp->payload_seq), &tcp->payload_seq))
		return -ENOBUFS;

	if (tcp->payload_tok.len &&
	    nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN,
		    sizeof(tcp->payload_tok) + tcp->tokens_size,
		    &tcp->payload_tok))
		return -ENOBUFS;

8824 8825
	nla_nest_end(msg, nl_tcp);

8826 8827 8828
	return 0;
}

8829 8830 8831 8832 8833 8834 8835 8836 8837 8838 8839 8840 8841 8842 8843 8844
static int nl80211_send_wowlan_nd(struct sk_buff *msg,
				  struct cfg80211_sched_scan_request *req)
{
	struct nlattr *nd, *freqs, *matches, *match;
	int i;

	if (!req)
		return 0;

	nd = nla_nest_start(msg, NL80211_WOWLAN_TRIG_NET_DETECT);
	if (!nd)
		return -ENOBUFS;

	if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL, req->interval))
		return -ENOBUFS;

8845 8846 8847
	if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_DELAY, req->delay))
		return -ENOBUFS;

8848 8849 8850 8851 8852 8853 8854 8855 8856 8857 8858 8859 8860 8861 8862 8863 8864 8865 8866 8867 8868 8869 8870 8871 8872 8873
	freqs = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES);
	if (!freqs)
		return -ENOBUFS;

	for (i = 0; i < req->n_channels; i++)
		nla_put_u32(msg, i, req->channels[i]->center_freq);

	nla_nest_end(msg, freqs);

	if (req->n_match_sets) {
		matches = nla_nest_start(msg, NL80211_ATTR_SCHED_SCAN_MATCH);
		for (i = 0; i < req->n_match_sets; i++) {
			match = nla_nest_start(msg, i);
			nla_put(msg, NL80211_SCHED_SCAN_MATCH_ATTR_SSID,
				req->match_sets[i].ssid.ssid_len,
				req->match_sets[i].ssid.ssid);
			nla_nest_end(msg, match);
		}
		nla_nest_end(msg, matches);
	}

	nla_nest_end(msg, nd);

	return 0;
}

8874 8875 8876 8877 8878
static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct sk_buff *msg;
	void *hdr;
8879
	u32 size = NLMSG_DEFAULT_SIZE;
8880

8881
	if (!rdev->wiphy.wowlan)
8882 8883
		return -EOPNOTSUPP;

8884
	if (rdev->wiphy.wowlan_config && rdev->wiphy.wowlan_config->tcp) {
8885
		/* adjust size to have room for all the data */
8886 8887 8888 8889
		size += rdev->wiphy.wowlan_config->tcp->tokens_size +
			rdev->wiphy.wowlan_config->tcp->payload_len +
			rdev->wiphy.wowlan_config->tcp->wake_len +
			rdev->wiphy.wowlan_config->tcp->wake_len / 8;
8890 8891 8892
	}

	msg = nlmsg_new(size, GFP_KERNEL);
8893 8894 8895
	if (!msg)
		return -ENOMEM;

8896
	hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
8897 8898 8899 8900
			     NL80211_CMD_GET_WOWLAN);
	if (!hdr)
		goto nla_put_failure;

8901
	if (rdev->wiphy.wowlan_config) {
8902 8903 8904 8905 8906 8907
		struct nlattr *nl_wowlan;

		nl_wowlan = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS);
		if (!nl_wowlan)
			goto nla_put_failure;

8908
		if ((rdev->wiphy.wowlan_config->any &&
8909
		     nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) ||
8910
		    (rdev->wiphy.wowlan_config->disconnect &&
8911
		     nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) ||
8912
		    (rdev->wiphy.wowlan_config->magic_pkt &&
8913
		     nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) ||
8914
		    (rdev->wiphy.wowlan_config->gtk_rekey_failure &&
8915
		     nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) ||
8916
		    (rdev->wiphy.wowlan_config->eap_identity_req &&
8917
		     nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) ||
8918
		    (rdev->wiphy.wowlan_config->four_way_handshake &&
8919
		     nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) ||
8920
		    (rdev->wiphy.wowlan_config->rfkill_release &&
8921 8922
		     nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)))
			goto nla_put_failure;
8923

8924 8925
		if (nl80211_send_wowlan_patterns(msg, rdev))
			goto nla_put_failure;
8926

8927 8928
		if (nl80211_send_wowlan_tcp(msg,
					    rdev->wiphy.wowlan_config->tcp))
8929
			goto nla_put_failure;
8930 8931 8932 8933 8934

		if (nl80211_send_wowlan_nd(
			    msg,
			    rdev->wiphy.wowlan_config->nd_config))
			goto nla_put_failure;
8935

8936 8937 8938 8939 8940 8941 8942 8943 8944 8945 8946
		nla_nest_end(msg, nl_wowlan);
	}

	genlmsg_end(msg, hdr);
	return genlmsg_reply(msg, info);

nla_put_failure:
	nlmsg_free(msg);
	return -ENOBUFS;
}

8947 8948 8949 8950 8951 8952 8953 8954 8955 8956 8957 8958
static int nl80211_parse_wowlan_tcp(struct cfg80211_registered_device *rdev,
				    struct nlattr *attr,
				    struct cfg80211_wowlan *trig)
{
	struct nlattr *tb[NUM_NL80211_WOWLAN_TCP];
	struct cfg80211_wowlan_tcp *cfg;
	struct nl80211_wowlan_tcp_data_token *tok = NULL;
	struct nl80211_wowlan_tcp_data_seq *seq = NULL;
	u32 size;
	u32 data_size, wake_size, tokens_size = 0, wake_mask_size;
	int err, port;

8959
	if (!rdev->wiphy.wowlan->tcp)
8960 8961 8962 8963 8964 8965 8966 8967 8968 8969 8970 8971 8972 8973 8974 8975 8976 8977 8978
		return -EINVAL;

	err = nla_parse(tb, MAX_NL80211_WOWLAN_TCP,
			nla_data(attr), nla_len(attr),
			nl80211_wowlan_tcp_policy);
	if (err)
		return err;

	if (!tb[NL80211_WOWLAN_TCP_SRC_IPV4] ||
	    !tb[NL80211_WOWLAN_TCP_DST_IPV4] ||
	    !tb[NL80211_WOWLAN_TCP_DST_MAC] ||
	    !tb[NL80211_WOWLAN_TCP_DST_PORT] ||
	    !tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD] ||
	    !tb[NL80211_WOWLAN_TCP_DATA_INTERVAL] ||
	    !tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD] ||
	    !tb[NL80211_WOWLAN_TCP_WAKE_MASK])
		return -EINVAL;

	data_size = nla_len(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD]);
8979
	if (data_size > rdev->wiphy.wowlan->tcp->data_payload_max)
8980 8981 8982
		return -EINVAL;

	if (nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) >
8983
			rdev->wiphy.wowlan->tcp->data_interval_max ||
8984
	    nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) == 0)
8985 8986 8987
		return -EINVAL;

	wake_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD]);
8988
	if (wake_size > rdev->wiphy.wowlan->tcp->wake_payload_max)
8989 8990 8991 8992 8993 8994 8995 8996 8997 8998 8999 9000 9001 9002
		return -EINVAL;

	wake_mask_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_MASK]);
	if (wake_mask_size != DIV_ROUND_UP(wake_size, 8))
		return -EINVAL;

	if (tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]) {
		u32 tokln = nla_len(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]);

		tok = nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]);
		tokens_size = tokln - sizeof(*tok);

		if (!tok->len || tokens_size % tok->len)
			return -EINVAL;
9003
		if (!rdev->wiphy.wowlan->tcp->tok)
9004
			return -EINVAL;
9005
		if (tok->len > rdev->wiphy.wowlan->tcp->tok->max_len)
9006
			return -EINVAL;
9007
		if (tok->len < rdev->wiphy.wowlan->tcp->tok->min_len)
9008
			return -EINVAL;
9009
		if (tokens_size > rdev->wiphy.wowlan->tcp->tok->bufsize)
9010 9011 9012 9013 9014 9015 9016
			return -EINVAL;
		if (tok->offset + tok->len > data_size)
			return -EINVAL;
	}

	if (tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ]) {
		seq = nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ]);
9017
		if (!rdev->wiphy.wowlan->tcp->seq)
9018 9019 9020 9021 9022 9023 9024 9025 9026 9027 9028 9029 9030 9031 9032
			return -EINVAL;
		if (seq->len == 0 || seq->len > 4)
			return -EINVAL;
		if (seq->len + seq->offset > data_size)
			return -EINVAL;
	}

	size = sizeof(*cfg);
	size += data_size;
	size += wake_size + wake_mask_size;
	size += tokens_size;

	cfg = kzalloc(size, GFP_KERNEL);
	if (!cfg)
		return -ENOMEM;
9033 9034
	cfg->src = nla_get_in_addr(tb[NL80211_WOWLAN_TCP_SRC_IPV4]);
	cfg->dst = nla_get_in_addr(tb[NL80211_WOWLAN_TCP_DST_IPV4]);
9035 9036 9037 9038 9039 9040 9041 9042 9043 9044 9045 9046 9047 9048 9049 9050 9051 9052 9053 9054 9055 9056 9057 9058 9059 9060 9061 9062 9063 9064 9065 9066 9067 9068 9069 9070 9071 9072 9073 9074 9075 9076 9077 9078 9079 9080 9081 9082 9083 9084 9085 9086 9087 9088 9089 9090 9091
	memcpy(cfg->dst_mac, nla_data(tb[NL80211_WOWLAN_TCP_DST_MAC]),
	       ETH_ALEN);
	if (tb[NL80211_WOWLAN_TCP_SRC_PORT])
		port = nla_get_u16(tb[NL80211_WOWLAN_TCP_SRC_PORT]);
	else
		port = 0;
#ifdef CONFIG_INET
	/* allocate a socket and port for it and use it */
	err = __sock_create(wiphy_net(&rdev->wiphy), PF_INET, SOCK_STREAM,
			    IPPROTO_TCP, &cfg->sock, 1);
	if (err) {
		kfree(cfg);
		return err;
	}
	if (inet_csk_get_port(cfg->sock->sk, port)) {
		sock_release(cfg->sock);
		kfree(cfg);
		return -EADDRINUSE;
	}
	cfg->src_port = inet_sk(cfg->sock->sk)->inet_num;
#else
	if (!port) {
		kfree(cfg);
		return -EINVAL;
	}
	cfg->src_port = port;
#endif

	cfg->dst_port = nla_get_u16(tb[NL80211_WOWLAN_TCP_DST_PORT]);
	cfg->payload_len = data_size;
	cfg->payload = (u8 *)cfg + sizeof(*cfg) + tokens_size;
	memcpy((void *)cfg->payload,
	       nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD]),
	       data_size);
	if (seq)
		cfg->payload_seq = *seq;
	cfg->data_interval = nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]);
	cfg->wake_len = wake_size;
	cfg->wake_data = (u8 *)cfg + sizeof(*cfg) + tokens_size + data_size;
	memcpy((void *)cfg->wake_data,
	       nla_data(tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD]),
	       wake_size);
	cfg->wake_mask = (u8 *)cfg + sizeof(*cfg) + tokens_size +
			 data_size + wake_size;
	memcpy((void *)cfg->wake_mask,
	       nla_data(tb[NL80211_WOWLAN_TCP_WAKE_MASK]),
	       wake_mask_size);
	if (tok) {
		cfg->tokens_size = tokens_size;
		memcpy(&cfg->payload_tok, tok, sizeof(*tok) + tokens_size);
	}

	trig->tcp = cfg;

	return 0;
}

9092 9093 9094 9095 9096 9097 9098 9099 9100 9101 9102 9103 9104 9105 9106 9107 9108 9109 9110 9111 9112 9113 9114
static int nl80211_parse_wowlan_nd(struct cfg80211_registered_device *rdev,
				   const struct wiphy_wowlan_support *wowlan,
				   struct nlattr *attr,
				   struct cfg80211_wowlan *trig)
{
	struct nlattr **tb;
	int err;

	tb = kzalloc(NUM_NL80211_ATTR * sizeof(*tb), GFP_KERNEL);
	if (!tb)
		return -ENOMEM;

	if (!(wowlan->flags & WIPHY_WOWLAN_NET_DETECT)) {
		err = -EOPNOTSUPP;
		goto out;
	}

	err = nla_parse(tb, NL80211_ATTR_MAX,
			nla_data(attr), nla_len(attr),
			nl80211_policy);
	if (err)
		goto out;

9115
	trig->nd_config = nl80211_parse_sched_scan(&rdev->wiphy, NULL, tb);
9116 9117 9118 9119 9120 9121 9122 9123 9124
	err = PTR_ERR_OR_ZERO(trig->nd_config);
	if (err)
		trig->nd_config = NULL;

out:
	kfree(tb);
	return err;
}

9125 9126 9127 9128 9129
static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct nlattr *tb[NUM_NL80211_WOWLAN_TRIG];
	struct cfg80211_wowlan new_triggers = {};
9130
	struct cfg80211_wowlan *ntrig;
9131
	const struct wiphy_wowlan_support *wowlan = rdev->wiphy.wowlan;
9132
	int err, i;
9133
	bool prev_enabled = rdev->wiphy.wowlan_config;
9134
	bool regular = false;
9135

9136
	if (!wowlan)
9137 9138
		return -EOPNOTSUPP;

9139 9140
	if (!info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) {
		cfg80211_rdev_free_wowlan(rdev);
9141
		rdev->wiphy.wowlan_config = NULL;
9142 9143
		goto set_wakeup;
	}
9144 9145 9146 9147 9148 9149 9150 9151 9152 9153 9154 9155 9156 9157 9158 9159 9160 9161

	err = nla_parse(tb, MAX_NL80211_WOWLAN_TRIG,
			nla_data(info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]),
			nla_len(info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]),
			nl80211_wowlan_policy);
	if (err)
		return err;

	if (tb[NL80211_WOWLAN_TRIG_ANY]) {
		if (!(wowlan->flags & WIPHY_WOWLAN_ANY))
			return -EINVAL;
		new_triggers.any = true;
	}

	if (tb[NL80211_WOWLAN_TRIG_DISCONNECT]) {
		if (!(wowlan->flags & WIPHY_WOWLAN_DISCONNECT))
			return -EINVAL;
		new_triggers.disconnect = true;
9162
		regular = true;
9163 9164 9165 9166 9167 9168
	}

	if (tb[NL80211_WOWLAN_TRIG_MAGIC_PKT]) {
		if (!(wowlan->flags & WIPHY_WOWLAN_MAGIC_PKT))
			return -EINVAL;
		new_triggers.magic_pkt = true;
9169
		regular = true;
9170 9171
	}

9172 9173 9174 9175 9176 9177 9178
	if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED])
		return -EINVAL;

	if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE]) {
		if (!(wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE))
			return -EINVAL;
		new_triggers.gtk_rekey_failure = true;
9179
		regular = true;
9180 9181 9182 9183 9184 9185
	}

	if (tb[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST]) {
		if (!(wowlan->flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ))
			return -EINVAL;
		new_triggers.eap_identity_req = true;
9186
		regular = true;
9187 9188 9189 9190 9191 9192
	}

	if (tb[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE]) {
		if (!(wowlan->flags & WIPHY_WOWLAN_4WAY_HANDSHAKE))
			return -EINVAL;
		new_triggers.four_way_handshake = true;
9193
		regular = true;
9194 9195 9196 9197 9198 9199
	}

	if (tb[NL80211_WOWLAN_TRIG_RFKILL_RELEASE]) {
		if (!(wowlan->flags & WIPHY_WOWLAN_RFKILL_RELEASE))
			return -EINVAL;
		new_triggers.rfkill_release = true;
9200
		regular = true;
9201 9202
	}

9203 9204 9205
	if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) {
		struct nlattr *pat;
		int n_patterns = 0;
9206
		int rem, pat_len, mask_len, pkt_offset;
9207
		struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
9208

9209 9210
		regular = true;

9211 9212 9213 9214 9215 9216 9217 9218 9219 9220 9221 9222 9223 9224 9225 9226 9227
		nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
				    rem)
			n_patterns++;
		if (n_patterns > wowlan->n_patterns)
			return -EINVAL;

		new_triggers.patterns = kcalloc(n_patterns,
						sizeof(new_triggers.patterns[0]),
						GFP_KERNEL);
		if (!new_triggers.patterns)
			return -ENOMEM;

		new_triggers.n_patterns = n_patterns;
		i = 0;

		nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
				    rem) {
9228 9229
			u8 *mask_pat;

9230 9231
			nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat),
				  nla_len(pat), NULL);
9232
			err = -EINVAL;
9233 9234
			if (!pat_tb[NL80211_PKTPAT_MASK] ||
			    !pat_tb[NL80211_PKTPAT_PATTERN])
9235
				goto error;
9236
			pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]);
9237
			mask_len = DIV_ROUND_UP(pat_len, 8);
9238
			if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) != mask_len)
9239 9240 9241 9242 9243
				goto error;
			if (pat_len > wowlan->pattern_max_len ||
			    pat_len < wowlan->pattern_min_len)
				goto error;

9244
			if (!pat_tb[NL80211_PKTPAT_OFFSET])
9245 9246 9247
				pkt_offset = 0;
			else
				pkt_offset = nla_get_u32(
9248
					pat_tb[NL80211_PKTPAT_OFFSET]);
9249 9250 9251 9252
			if (pkt_offset > wowlan->max_pkt_offset)
				goto error;
			new_triggers.patterns[i].pkt_offset = pkt_offset;

9253 9254
			mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL);
			if (!mask_pat) {
9255 9256 9257
				err = -ENOMEM;
				goto error;
			}
9258 9259
			new_triggers.patterns[i].mask = mask_pat;
			memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]),
9260
			       mask_len);
9261 9262
			mask_pat += mask_len;
			new_triggers.patterns[i].pattern = mask_pat;
9263
			new_triggers.patterns[i].pattern_len = pat_len;
9264
			memcpy(mask_pat,
9265
			       nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
9266 9267 9268 9269 9270
			       pat_len);
			i++;
		}
	}

9271
	if (tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION]) {
9272
		regular = true;
9273 9274 9275 9276 9277 9278 9279
		err = nl80211_parse_wowlan_tcp(
			rdev, tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION],
			&new_triggers);
		if (err)
			goto error;
	}

9280
	if (tb[NL80211_WOWLAN_TRIG_NET_DETECT]) {
9281
		regular = true;
9282 9283 9284 9285 9286 9287 9288
		err = nl80211_parse_wowlan_nd(
			rdev, wowlan, tb[NL80211_WOWLAN_TRIG_NET_DETECT],
			&new_triggers);
		if (err)
			goto error;
	}

9289 9290 9291 9292 9293 9294 9295 9296 9297 9298 9299
	/* The 'any' trigger means the device continues operating more or less
	 * as in its normal operation mode and wakes up the host on most of the
	 * normal interrupts (like packet RX, ...)
	 * It therefore makes little sense to combine with the more constrained
	 * wakeup trigger modes.
	 */
	if (new_triggers.any && regular) {
		err = -EINVAL;
		goto error;
	}

9300 9301 9302 9303
	ntrig = kmemdup(&new_triggers, sizeof(new_triggers), GFP_KERNEL);
	if (!ntrig) {
		err = -ENOMEM;
		goto error;
9304
	}
9305
	cfg80211_rdev_free_wowlan(rdev);
9306
	rdev->wiphy.wowlan_config = ntrig;
9307

9308
 set_wakeup:
9309 9310 9311
	if (rdev->ops->set_wakeup &&
	    prev_enabled != !!rdev->wiphy.wowlan_config)
		rdev_set_wakeup(rdev, rdev->wiphy.wowlan_config);
9312

9313 9314 9315 9316 9317
	return 0;
 error:
	for (i = 0; i < new_triggers.n_patterns; i++)
		kfree(new_triggers.patterns[i].mask);
	kfree(new_triggers.patterns);
9318 9319 9320
	if (new_triggers.tcp && new_triggers.tcp->sock)
		sock_release(new_triggers.tcp->sock);
	kfree(new_triggers.tcp);
9321 9322
	return err;
}
9323
#endif
9324

9325 9326 9327 9328 9329 9330 9331 9332 9333 9334 9335 9336 9337 9338 9339 9340 9341 9342 9343 9344 9345 9346 9347 9348 9349 9350 9351 9352 9353 9354 9355 9356 9357 9358 9359 9360 9361 9362 9363 9364 9365 9366 9367 9368 9369 9370 9371 9372 9373 9374 9375 9376 9377 9378 9379 9380 9381 9382 9383 9384 9385 9386 9387 9388 9389 9390 9391 9392 9393 9394 9395 9396 9397 9398 9399 9400 9401 9402 9403 9404 9405 9406 9407 9408 9409 9410 9411 9412 9413 9414 9415 9416 9417 9418 9419 9420 9421 9422 9423 9424 9425 9426 9427 9428 9429 9430 9431 9432 9433 9434 9435 9436 9437 9438 9439 9440 9441 9442 9443 9444 9445 9446 9447 9448 9449 9450 9451 9452 9453 9454 9455 9456 9457 9458 9459 9460 9461 9462 9463 9464 9465 9466 9467 9468 9469 9470 9471 9472 9473 9474 9475 9476
static int nl80211_send_coalesce_rules(struct sk_buff *msg,
				       struct cfg80211_registered_device *rdev)
{
	struct nlattr *nl_pats, *nl_pat, *nl_rule, *nl_rules;
	int i, j, pat_len;
	struct cfg80211_coalesce_rules *rule;

	if (!rdev->coalesce->n_rules)
		return 0;

	nl_rules = nla_nest_start(msg, NL80211_ATTR_COALESCE_RULE);
	if (!nl_rules)
		return -ENOBUFS;

	for (i = 0; i < rdev->coalesce->n_rules; i++) {
		nl_rule = nla_nest_start(msg, i + 1);
		if (!nl_rule)
			return -ENOBUFS;

		rule = &rdev->coalesce->rules[i];
		if (nla_put_u32(msg, NL80211_ATTR_COALESCE_RULE_DELAY,
				rule->delay))
			return -ENOBUFS;

		if (nla_put_u32(msg, NL80211_ATTR_COALESCE_RULE_CONDITION,
				rule->condition))
			return -ENOBUFS;

		nl_pats = nla_nest_start(msg,
				NL80211_ATTR_COALESCE_RULE_PKT_PATTERN);
		if (!nl_pats)
			return -ENOBUFS;

		for (j = 0; j < rule->n_patterns; j++) {
			nl_pat = nla_nest_start(msg, j + 1);
			if (!nl_pat)
				return -ENOBUFS;
			pat_len = rule->patterns[j].pattern_len;
			if (nla_put(msg, NL80211_PKTPAT_MASK,
				    DIV_ROUND_UP(pat_len, 8),
				    rule->patterns[j].mask) ||
			    nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len,
				    rule->patterns[j].pattern) ||
			    nla_put_u32(msg, NL80211_PKTPAT_OFFSET,
					rule->patterns[j].pkt_offset))
				return -ENOBUFS;
			nla_nest_end(msg, nl_pat);
		}
		nla_nest_end(msg, nl_pats);
		nla_nest_end(msg, nl_rule);
	}
	nla_nest_end(msg, nl_rules);

	return 0;
}

static int nl80211_get_coalesce(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct sk_buff *msg;
	void *hdr;

	if (!rdev->wiphy.coalesce)
		return -EOPNOTSUPP;

	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
	if (!msg)
		return -ENOMEM;

	hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
			     NL80211_CMD_GET_COALESCE);
	if (!hdr)
		goto nla_put_failure;

	if (rdev->coalesce && nl80211_send_coalesce_rules(msg, rdev))
		goto nla_put_failure;

	genlmsg_end(msg, hdr);
	return genlmsg_reply(msg, info);

nla_put_failure:
	nlmsg_free(msg);
	return -ENOBUFS;
}

void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev)
{
	struct cfg80211_coalesce *coalesce = rdev->coalesce;
	int i, j;
	struct cfg80211_coalesce_rules *rule;

	if (!coalesce)
		return;

	for (i = 0; i < coalesce->n_rules; i++) {
		rule = &coalesce->rules[i];
		for (j = 0; j < rule->n_patterns; j++)
			kfree(rule->patterns[j].mask);
		kfree(rule->patterns);
	}
	kfree(coalesce->rules);
	kfree(coalesce);
	rdev->coalesce = NULL;
}

static int nl80211_parse_coalesce_rule(struct cfg80211_registered_device *rdev,
				       struct nlattr *rule,
				       struct cfg80211_coalesce_rules *new_rule)
{
	int err, i;
	const struct wiphy_coalesce_support *coalesce = rdev->wiphy.coalesce;
	struct nlattr *tb[NUM_NL80211_ATTR_COALESCE_RULE], *pat;
	int rem, pat_len, mask_len, pkt_offset, n_patterns = 0;
	struct nlattr *pat_tb[NUM_NL80211_PKTPAT];

	err = nla_parse(tb, NL80211_ATTR_COALESCE_RULE_MAX, nla_data(rule),
			nla_len(rule), nl80211_coalesce_policy);
	if (err)
		return err;

	if (tb[NL80211_ATTR_COALESCE_RULE_DELAY])
		new_rule->delay =
			nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_DELAY]);
	if (new_rule->delay > coalesce->max_delay)
		return -EINVAL;

	if (tb[NL80211_ATTR_COALESCE_RULE_CONDITION])
		new_rule->condition =
			nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_CONDITION]);
	if (new_rule->condition != NL80211_COALESCE_CONDITION_MATCH &&
	    new_rule->condition != NL80211_COALESCE_CONDITION_NO_MATCH)
		return -EINVAL;

	if (!tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN])
		return -EINVAL;

	nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
			    rem)
		n_patterns++;
	if (n_patterns > coalesce->n_patterns)
		return -EINVAL;

	new_rule->patterns = kcalloc(n_patterns, sizeof(new_rule->patterns[0]),
				     GFP_KERNEL);
	if (!new_rule->patterns)
		return -ENOMEM;

	new_rule->n_patterns = n_patterns;
	i = 0;

	nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
			    rem) {
9477 9478
		u8 *mask_pat;

9479 9480 9481 9482 9483 9484 9485 9486 9487 9488 9489 9490 9491 9492 9493 9494 9495 9496 9497 9498 9499
		nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat),
			  nla_len(pat), NULL);
		if (!pat_tb[NL80211_PKTPAT_MASK] ||
		    !pat_tb[NL80211_PKTPAT_PATTERN])
			return -EINVAL;
		pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]);
		mask_len = DIV_ROUND_UP(pat_len, 8);
		if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) != mask_len)
			return -EINVAL;
		if (pat_len > coalesce->pattern_max_len ||
		    pat_len < coalesce->pattern_min_len)
			return -EINVAL;

		if (!pat_tb[NL80211_PKTPAT_OFFSET])
			pkt_offset = 0;
		else
			pkt_offset = nla_get_u32(pat_tb[NL80211_PKTPAT_OFFSET]);
		if (pkt_offset > coalesce->max_pkt_offset)
			return -EINVAL;
		new_rule->patterns[i].pkt_offset = pkt_offset;

9500 9501
		mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL);
		if (!mask_pat)
9502
			return -ENOMEM;
9503 9504 9505 9506 9507 9508 9509

		new_rule->patterns[i].mask = mask_pat;
		memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]),
		       mask_len);

		mask_pat += mask_len;
		new_rule->patterns[i].pattern = mask_pat;
9510
		new_rule->patterns[i].pattern_len = pat_len;
9511 9512
		memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
		       pat_len);
9513 9514 9515 9516 9517 9518 9519 9520 9521 9522 9523 9524 9525 9526 9527 9528 9529 9530 9531 9532 9533 9534 9535 9536 9537 9538 9539 9540 9541 9542 9543 9544 9545 9546 9547 9548 9549 9550 9551 9552 9553 9554 9555 9556 9557 9558 9559 9560 9561 9562 9563 9564 9565 9566 9567 9568 9569 9570 9571 9572 9573 9574 9575 9576 9577 9578 9579 9580 9581 9582 9583 9584 9585 9586
		i++;
	}

	return 0;
}

static int nl80211_set_coalesce(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	const struct wiphy_coalesce_support *coalesce = rdev->wiphy.coalesce;
	struct cfg80211_coalesce new_coalesce = {};
	struct cfg80211_coalesce *n_coalesce;
	int err, rem_rule, n_rules = 0, i, j;
	struct nlattr *rule;
	struct cfg80211_coalesce_rules *tmp_rule;

	if (!rdev->wiphy.coalesce || !rdev->ops->set_coalesce)
		return -EOPNOTSUPP;

	if (!info->attrs[NL80211_ATTR_COALESCE_RULE]) {
		cfg80211_rdev_free_coalesce(rdev);
		rdev->ops->set_coalesce(&rdev->wiphy, NULL);
		return 0;
	}

	nla_for_each_nested(rule, info->attrs[NL80211_ATTR_COALESCE_RULE],
			    rem_rule)
		n_rules++;
	if (n_rules > coalesce->n_rules)
		return -EINVAL;

	new_coalesce.rules = kcalloc(n_rules, sizeof(new_coalesce.rules[0]),
				     GFP_KERNEL);
	if (!new_coalesce.rules)
		return -ENOMEM;

	new_coalesce.n_rules = n_rules;
	i = 0;

	nla_for_each_nested(rule, info->attrs[NL80211_ATTR_COALESCE_RULE],
			    rem_rule) {
		err = nl80211_parse_coalesce_rule(rdev, rule,
						  &new_coalesce.rules[i]);
		if (err)
			goto error;

		i++;
	}

	err = rdev->ops->set_coalesce(&rdev->wiphy, &new_coalesce);
	if (err)
		goto error;

	n_coalesce = kmemdup(&new_coalesce, sizeof(new_coalesce), GFP_KERNEL);
	if (!n_coalesce) {
		err = -ENOMEM;
		goto error;
	}
	cfg80211_rdev_free_coalesce(rdev);
	rdev->coalesce = n_coalesce;

	return 0;
error:
	for (i = 0; i < new_coalesce.n_rules; i++) {
		tmp_rule = &new_coalesce.rules[i];
		for (j = 0; j < tmp_rule->n_patterns; j++)
			kfree(tmp_rule->patterns[j].mask);
		kfree(tmp_rule->patterns);
	}
	kfree(new_coalesce.rules);

	return err;
}

9587 9588 9589 9590 9591 9592 9593 9594 9595 9596 9597 9598 9599 9600 9601 9602 9603 9604 9605 9606 9607 9608 9609 9610 9611 9612
static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
	struct wireless_dev *wdev = dev->ieee80211_ptr;
	struct nlattr *tb[NUM_NL80211_REKEY_DATA];
	struct cfg80211_gtk_rekey_data rekey_data;
	int err;

	if (!info->attrs[NL80211_ATTR_REKEY_DATA])
		return -EINVAL;

	err = nla_parse(tb, MAX_NL80211_REKEY_DATA,
			nla_data(info->attrs[NL80211_ATTR_REKEY_DATA]),
			nla_len(info->attrs[NL80211_ATTR_REKEY_DATA]),
			nl80211_rekey_policy);
	if (err)
		return err;

	if (nla_len(tb[NL80211_REKEY_DATA_REPLAY_CTR]) != NL80211_REPLAY_CTR_LEN)
		return -ERANGE;
	if (nla_len(tb[NL80211_REKEY_DATA_KEK]) != NL80211_KEK_LEN)
		return -ERANGE;
	if (nla_len(tb[NL80211_REKEY_DATA_KCK]) != NL80211_KCK_LEN)
		return -ERANGE;

9613 9614 9615
	rekey_data.kek = nla_data(tb[NL80211_REKEY_DATA_KEK]);
	rekey_data.kck = nla_data(tb[NL80211_REKEY_DATA_KCK]);
	rekey_data.replay_ctr = nla_data(tb[NL80211_REKEY_DATA_REPLAY_CTR]);
9616 9617 9618 9619 9620 9621 9622 9623 9624 9625 9626 9627

	wdev_lock(wdev);
	if (!wdev->current_bss) {
		err = -ENOTCONN;
		goto out;
	}

	if (!rdev->ops->set_rekey_data) {
		err = -EOPNOTSUPP;
		goto out;
	}

9628
	err = rdev_set_rekey_data(rdev, dev, &rekey_data);
9629 9630 9631 9632 9633
 out:
	wdev_unlock(wdev);
	return err;
}

9634 9635 9636 9637 9638 9639 9640 9641 9642 9643
static int nl80211_register_unexpected_frame(struct sk_buff *skb,
					     struct genl_info *info)
{
	struct net_device *dev = info->user_ptr[1];
	struct wireless_dev *wdev = dev->ieee80211_ptr;

	if (wdev->iftype != NL80211_IFTYPE_AP &&
	    wdev->iftype != NL80211_IFTYPE_P2P_GO)
		return -EINVAL;

9644
	if (wdev->ap_unexpected_nlportid)
9645 9646
		return -EBUSY;

9647
	wdev->ap_unexpected_nlportid = info->snd_portid;
9648 9649 9650
	return 0;
}

9651 9652 9653 9654 9655 9656 9657 9658 9659 9660 9661 9662 9663 9664 9665 9666 9667 9668 9669 9670 9671 9672 9673 9674 9675 9676
static int nl80211_probe_client(struct sk_buff *skb,
				struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
	struct wireless_dev *wdev = dev->ieee80211_ptr;
	struct sk_buff *msg;
	void *hdr;
	const u8 *addr;
	u64 cookie;
	int err;

	if (wdev->iftype != NL80211_IFTYPE_AP &&
	    wdev->iftype != NL80211_IFTYPE_P2P_GO)
		return -EOPNOTSUPP;

	if (!info->attrs[NL80211_ATTR_MAC])
		return -EINVAL;

	if (!rdev->ops->probe_client)
		return -EOPNOTSUPP;

	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
	if (!msg)
		return -ENOMEM;

9677
	hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
9678
			     NL80211_CMD_PROBE_CLIENT);
9679 9680
	if (!hdr) {
		err = -ENOBUFS;
9681 9682 9683 9684 9685
		goto free_msg;
	}

	addr = nla_data(info->attrs[NL80211_ATTR_MAC]);

9686
	err = rdev_probe_client(rdev, dev, addr, &cookie);
9687 9688 9689
	if (err)
		goto free_msg;

9690 9691
	if (nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie))
		goto nla_put_failure;
9692 9693 9694 9695 9696 9697 9698 9699 9700 9701 9702 9703

	genlmsg_end(msg, hdr);

	return genlmsg_reply(msg, info);

 nla_put_failure:
	err = -ENOBUFS;
 free_msg:
	nlmsg_free(msg);
	return err;
}

9704 9705 9706
static int nl80211_register_beacons(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
9707 9708
	struct cfg80211_beacon_registration *reg, *nreg;
	int rv;
9709 9710 9711 9712

	if (!(rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS))
		return -EOPNOTSUPP;

9713 9714 9715 9716 9717 9718 9719 9720 9721 9722 9723 9724 9725 9726 9727
	nreg = kzalloc(sizeof(*nreg), GFP_KERNEL);
	if (!nreg)
		return -ENOMEM;

	/* First, check if already registered. */
	spin_lock_bh(&rdev->beacon_registrations_lock);
	list_for_each_entry(reg, &rdev->beacon_registrations, list) {
		if (reg->nlportid == info->snd_portid) {
			rv = -EALREADY;
			goto out_err;
		}
	}
	/* Add it to the list */
	nreg->nlportid = info->snd_portid;
	list_add(&nreg->list, &rdev->beacon_registrations);
9728

9729
	spin_unlock_bh(&rdev->beacon_registrations_lock);
9730 9731

	return 0;
9732 9733 9734 9735
out_err:
	spin_unlock_bh(&rdev->beacon_registrations_lock);
	kfree(nreg);
	return rv;
9736 9737
}

9738 9739 9740 9741 9742 9743 9744 9745 9746 9747 9748 9749 9750 9751 9752
static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct wireless_dev *wdev = info->user_ptr[1];
	int err;

	if (!rdev->ops->start_p2p_device)
		return -EOPNOTSUPP;

	if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)
		return -EOPNOTSUPP;

	if (wdev->p2p_started)
		return 0;

9753 9754
	if (rfkill_blocked(rdev->rfkill))
		return -ERFKILL;
9755

9756
	err = rdev_start_p2p_device(rdev, wdev);
9757 9758 9759 9760 9761 9762 9763 9764 9765 9766 9767 9768 9769 9770 9771 9772 9773 9774 9775 9776
	if (err)
		return err;

	wdev->p2p_started = true;
	rdev->opencount++;

	return 0;
}

static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct wireless_dev *wdev = info->user_ptr[1];

	if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)
		return -EOPNOTSUPP;

	if (!rdev->ops->stop_p2p_device)
		return -EOPNOTSUPP;

9777
	cfg80211_stop_p2p_device(rdev, wdev);
9778 9779 9780 9781

	return 0;
}

9782 9783 9784 9785 9786 9787 9788 9789 9790 9791 9792 9793 9794 9795 9796 9797 9798 9799 9800 9801 9802 9803 9804 9805 9806 9807 9808
static int nl80211_get_protocol_features(struct sk_buff *skb,
					 struct genl_info *info)
{
	void *hdr;
	struct sk_buff *msg;

	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
	if (!msg)
		return -ENOMEM;

	hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
			     NL80211_CMD_GET_PROTOCOL_FEATURES);
	if (!hdr)
		goto nla_put_failure;

	if (nla_put_u32(msg, NL80211_ATTR_PROTOCOL_FEATURES,
			NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP))
		goto nla_put_failure;

	genlmsg_end(msg, hdr);
	return genlmsg_reply(msg, info);

 nla_put_failure:
	kfree_skb(msg);
	return -ENOBUFS;
}

9809 9810 9811 9812 9813 9814 9815 9816 9817 9818 9819 9820 9821 9822 9823 9824 9825 9826 9827 9828 9829
static int nl80211_update_ft_ies(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct cfg80211_update_ft_ies_params ft_params;
	struct net_device *dev = info->user_ptr[1];

	if (!rdev->ops->update_ft_ies)
		return -EOPNOTSUPP;

	if (!info->attrs[NL80211_ATTR_MDID] ||
	    !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
		return -EINVAL;

	memset(&ft_params, 0, sizeof(ft_params));
	ft_params.md = nla_get_u16(info->attrs[NL80211_ATTR_MDID]);
	ft_params.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
	ft_params.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);

	return rdev_update_ft_ies(rdev, dev, &ft_params);
}

9830 9831 9832 9833 9834 9835 9836 9837 9838 9839 9840 9841 9842 9843 9844 9845 9846 9847 9848 9849 9850 9851 9852 9853 9854 9855 9856 9857 9858 9859 9860 9861 9862 9863 9864 9865 9866 9867 9868 9869 9870 9871 9872 9873 9874 9875 9876 9877 9878 9879 9880 9881 9882 9883 9884 9885 9886 9887
static int nl80211_crit_protocol_start(struct sk_buff *skb,
				       struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct wireless_dev *wdev = info->user_ptr[1];
	enum nl80211_crit_proto_id proto = NL80211_CRIT_PROTO_UNSPEC;
	u16 duration;
	int ret;

	if (!rdev->ops->crit_proto_start)
		return -EOPNOTSUPP;

	if (WARN_ON(!rdev->ops->crit_proto_stop))
		return -EINVAL;

	if (rdev->crit_proto_nlportid)
		return -EBUSY;

	/* determine protocol if provided */
	if (info->attrs[NL80211_ATTR_CRIT_PROT_ID])
		proto = nla_get_u16(info->attrs[NL80211_ATTR_CRIT_PROT_ID]);

	if (proto >= NUM_NL80211_CRIT_PROTO)
		return -EINVAL;

	/* timeout must be provided */
	if (!info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION])
		return -EINVAL;

	duration =
		nla_get_u16(info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION]);

	if (duration > NL80211_CRIT_PROTO_MAX_DURATION)
		return -ERANGE;

	ret = rdev_crit_proto_start(rdev, wdev, proto, duration);
	if (!ret)
		rdev->crit_proto_nlportid = info->snd_portid;

	return ret;
}

static int nl80211_crit_protocol_stop(struct sk_buff *skb,
				      struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct wireless_dev *wdev = info->user_ptr[1];

	if (!rdev->ops->crit_proto_stop)
		return -EOPNOTSUPP;

	if (rdev->crit_proto_nlportid) {
		rdev->crit_proto_nlportid = 0;
		rdev_crit_proto_stop(rdev, wdev);
	}
	return 0;
}

9888 9889 9890 9891 9892 9893 9894 9895 9896 9897 9898 9899 9900 9901 9902 9903 9904 9905 9906 9907 9908 9909 9910 9911 9912 9913 9914 9915 9916 9917 9918 9919 9920 9921 9922 9923 9924 9925 9926 9927 9928 9929 9930 9931 9932 9933 9934 9935 9936 9937 9938 9939 9940 9941 9942 9943 9944 9945 9946 9947 9948 9949 9950 9951 9952 9953 9954 9955 9956 9957 9958 9959 9960 9961 9962
static int nl80211_vendor_cmd(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct wireless_dev *wdev =
		__cfg80211_wdev_from_attrs(genl_info_net(info), info->attrs);
	int i, err;
	u32 vid, subcmd;

	if (!rdev->wiphy.vendor_commands)
		return -EOPNOTSUPP;

	if (IS_ERR(wdev)) {
		err = PTR_ERR(wdev);
		if (err != -EINVAL)
			return err;
		wdev = NULL;
	} else if (wdev->wiphy != &rdev->wiphy) {
		return -EINVAL;
	}

	if (!info->attrs[NL80211_ATTR_VENDOR_ID] ||
	    !info->attrs[NL80211_ATTR_VENDOR_SUBCMD])
		return -EINVAL;

	vid = nla_get_u32(info->attrs[NL80211_ATTR_VENDOR_ID]);
	subcmd = nla_get_u32(info->attrs[NL80211_ATTR_VENDOR_SUBCMD]);
	for (i = 0; i < rdev->wiphy.n_vendor_commands; i++) {
		const struct wiphy_vendor_command *vcmd;
		void *data = NULL;
		int len = 0;

		vcmd = &rdev->wiphy.vendor_commands[i];

		if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd)
			continue;

		if (vcmd->flags & (WIPHY_VENDOR_CMD_NEED_WDEV |
				   WIPHY_VENDOR_CMD_NEED_NETDEV)) {
			if (!wdev)
				return -EINVAL;
			if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_NETDEV &&
			    !wdev->netdev)
				return -EINVAL;

			if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) {
				if (wdev->netdev &&
				    !netif_running(wdev->netdev))
					return -ENETDOWN;
				if (!wdev->netdev && !wdev->p2p_started)
					return -ENETDOWN;
			}
		} else {
			wdev = NULL;
		}

		if (info->attrs[NL80211_ATTR_VENDOR_DATA]) {
			data = nla_data(info->attrs[NL80211_ATTR_VENDOR_DATA]);
			len = nla_len(info->attrs[NL80211_ATTR_VENDOR_DATA]);
		}

		rdev->cur_cmd_info = info;
		err = rdev->wiphy.vendor_commands[i].doit(&rdev->wiphy, wdev,
							  data, len);
		rdev->cur_cmd_info = NULL;
		return err;
	}

	return -EOPNOTSUPP;
}

struct sk_buff *__cfg80211_alloc_reply_skb(struct wiphy *wiphy,
					   enum nl80211_commands cmd,
					   enum nl80211_attrs attr,
					   int approxlen)
{
9963
	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
9964 9965 9966 9967

	if (WARN_ON(!rdev->cur_cmd_info))
		return NULL;

9968
	return __cfg80211_alloc_vendor_skb(rdev, NULL, approxlen,
9969 9970
					   rdev->cur_cmd_info->snd_portid,
					   rdev->cur_cmd_info->snd_seq,
9971
					   cmd, attr, NULL, GFP_KERNEL);
9972 9973 9974 9975 9976 9977 9978 9979 9980
}
EXPORT_SYMBOL(__cfg80211_alloc_reply_skb);

int cfg80211_vendor_cmd_reply(struct sk_buff *skb)
{
	struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
	void *hdr = ((void **)skb->cb)[1];
	struct nlattr *data = ((void **)skb->cb)[2];

9981 9982 9983
	/* clear CB data for netlink core to own from now on */
	memset(skb->cb, 0, sizeof(skb->cb));

9984 9985 9986 9987 9988 9989 9990 9991 9992 9993 9994 9995
	if (WARN_ON(!rdev->cur_cmd_info)) {
		kfree_skb(skb);
		return -EINVAL;
	}

	nla_nest_end(skb, data);
	genlmsg_end(skb, hdr);
	return genlmsg_reply(skb, rdev->cur_cmd_info);
}
EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_reply);


9996 9997 9998 9999 10000 10001 10002 10003 10004 10005 10006 10007 10008 10009 10010 10011 10012 10013 10014 10015 10016 10017 10018 10019 10020 10021 10022 10023 10024 10025 10026 10027 10028 10029 10030 10031 10032 10033 10034 10035 10036 10037 10038 10039 10040 10041 10042 10043 10044 10045 10046
static int nl80211_set_qos_map(struct sk_buff *skb,
			       struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct cfg80211_qos_map *qos_map = NULL;
	struct net_device *dev = info->user_ptr[1];
	u8 *pos, len, num_des, des_len, des;
	int ret;

	if (!rdev->ops->set_qos_map)
		return -EOPNOTSUPP;

	if (info->attrs[NL80211_ATTR_QOS_MAP]) {
		pos = nla_data(info->attrs[NL80211_ATTR_QOS_MAP]);
		len = nla_len(info->attrs[NL80211_ATTR_QOS_MAP]);

		if (len % 2 || len < IEEE80211_QOS_MAP_LEN_MIN ||
		    len > IEEE80211_QOS_MAP_LEN_MAX)
			return -EINVAL;

		qos_map = kzalloc(sizeof(struct cfg80211_qos_map), GFP_KERNEL);
		if (!qos_map)
			return -ENOMEM;

		num_des = (len - IEEE80211_QOS_MAP_LEN_MIN) >> 1;
		if (num_des) {
			des_len = num_des *
				sizeof(struct cfg80211_dscp_exception);
			memcpy(qos_map->dscp_exception, pos, des_len);
			qos_map->num_des = num_des;
			for (des = 0; des < num_des; des++) {
				if (qos_map->dscp_exception[des].up > 7) {
					kfree(qos_map);
					return -EINVAL;
				}
			}
			pos += des_len;
		}
		memcpy(qos_map->up, pos, IEEE80211_QOS_MAP_LEN_MIN);
	}

	wdev_lock(dev->ieee80211_ptr);
	ret = nl80211_key_allowed(dev->ieee80211_ptr);
	if (!ret)
		ret = rdev_set_qos_map(rdev, dev, qos_map);
	wdev_unlock(dev->ieee80211_ptr);

	kfree(qos_map);
	return ret;
}

10047 10048 10049 10050 10051 10052 10053 10054 10055 10056
static int nl80211_add_tx_ts(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
	struct wireless_dev *wdev = dev->ieee80211_ptr;
	const u8 *peer;
	u8 tsid, up;
	u16 admitted_time = 0;
	int err;

10057
	if (!(rdev->wiphy.features & NL80211_FEATURE_SUPPORTS_WMM_ADMISSION))
10058 10059 10060 10061 10062 10063 10064 10065 10066 10067 10068 10069 10070 10071 10072
		return -EOPNOTSUPP;

	if (!info->attrs[NL80211_ATTR_TSID] || !info->attrs[NL80211_ATTR_MAC] ||
	    !info->attrs[NL80211_ATTR_USER_PRIO])
		return -EINVAL;

	tsid = nla_get_u8(info->attrs[NL80211_ATTR_TSID]);
	if (tsid >= IEEE80211_NUM_TIDS)
		return -EINVAL;

	up = nla_get_u8(info->attrs[NL80211_ATTR_USER_PRIO]);
	if (up >= IEEE80211_NUM_UPS)
		return -EINVAL;

	/* WMM uses TIDs 0-7 even for TSPEC */
10073
	if (tsid >= IEEE80211_FIRST_TSPEC_TSID) {
10074
		/* TODO: handle 802.11 TSPEC/admission control
10075 10076
		 * need more attributes for that (e.g. BA session requirement);
		 * change the WMM adminssion test above to allow both then
10077 10078 10079 10080 10081 10082 10083 10084 10085 10086 10087 10088 10089 10090 10091 10092 10093 10094 10095 10096 10097 10098 10099 10100 10101 10102 10103 10104 10105 10106 10107 10108 10109 10110 10111 10112 10113 10114 10115 10116 10117 10118 10119 10120 10121 10122 10123 10124 10125 10126 10127 10128 10129 10130 10131
		 */
		return -EINVAL;
	}

	peer = nla_data(info->attrs[NL80211_ATTR_MAC]);

	if (info->attrs[NL80211_ATTR_ADMITTED_TIME]) {
		admitted_time =
			nla_get_u16(info->attrs[NL80211_ATTR_ADMITTED_TIME]);
		if (!admitted_time)
			return -EINVAL;
	}

	wdev_lock(wdev);
	switch (wdev->iftype) {
	case NL80211_IFTYPE_STATION:
	case NL80211_IFTYPE_P2P_CLIENT:
		if (wdev->current_bss)
			break;
		err = -ENOTCONN;
		goto out;
	default:
		err = -EOPNOTSUPP;
		goto out;
	}

	err = rdev_add_tx_ts(rdev, dev, tsid, peer, up, admitted_time);

 out:
	wdev_unlock(wdev);
	return err;
}

static int nl80211_del_tx_ts(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
	struct wireless_dev *wdev = dev->ieee80211_ptr;
	const u8 *peer;
	u8 tsid;
	int err;

	if (!info->attrs[NL80211_ATTR_TSID] || !info->attrs[NL80211_ATTR_MAC])
		return -EINVAL;

	tsid = nla_get_u8(info->attrs[NL80211_ATTR_TSID]);
	peer = nla_data(info->attrs[NL80211_ATTR_MAC]);

	wdev_lock(wdev);
	err = rdev_del_tx_ts(rdev, dev, tsid, peer);
	wdev_unlock(wdev);

	return err;
}

10132 10133 10134 10135 10136 10137 10138 10139 10140 10141 10142 10143 10144 10145 10146 10147 10148 10149 10150 10151 10152 10153 10154 10155 10156 10157 10158 10159 10160 10161 10162 10163 10164 10165 10166 10167 10168 10169 10170 10171 10172 10173
static int nl80211_tdls_channel_switch(struct sk_buff *skb,
				       struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
	struct wireless_dev *wdev = dev->ieee80211_ptr;
	struct cfg80211_chan_def chandef = {};
	const u8 *addr;
	u8 oper_class;
	int err;

	if (!rdev->ops->tdls_channel_switch ||
	    !(rdev->wiphy.features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH))
		return -EOPNOTSUPP;

	switch (dev->ieee80211_ptr->iftype) {
	case NL80211_IFTYPE_STATION:
	case NL80211_IFTYPE_P2P_CLIENT:
		break;
	default:
		return -EOPNOTSUPP;
	}

	if (!info->attrs[NL80211_ATTR_MAC] ||
	    !info->attrs[NL80211_ATTR_OPER_CLASS])
		return -EINVAL;

	err = nl80211_parse_chandef(rdev, info, &chandef);
	if (err)
		return err;

	/*
	 * Don't allow wide channels on the 2.4Ghz band, as per IEEE802.11-2012
	 * section 10.22.6.2.1. Disallow 5/10Mhz channels as well for now, the
	 * specification is not defined for them.
	 */
	if (chandef.chan->band == IEEE80211_BAND_2GHZ &&
	    chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
	    chandef.width != NL80211_CHAN_WIDTH_20)
		return -EINVAL;

	/* we will be active on the TDLS link */
10174 10175
	if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef,
					   wdev->iftype))
10176 10177 10178 10179 10180 10181 10182 10183 10184 10185 10186 10187 10188 10189 10190 10191 10192 10193 10194 10195 10196 10197 10198 10199 10200 10201 10202 10203 10204 10205 10206 10207 10208 10209 10210 10211 10212 10213 10214 10215 10216 10217 10218 10219 10220 10221 10222 10223 10224
		return -EINVAL;

	/* don't allow switching to DFS channels */
	if (cfg80211_chandef_dfs_required(wdev->wiphy, &chandef, wdev->iftype))
		return -EINVAL;

	addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
	oper_class = nla_get_u8(info->attrs[NL80211_ATTR_OPER_CLASS]);

	wdev_lock(wdev);
	err = rdev_tdls_channel_switch(rdev, dev, addr, oper_class, &chandef);
	wdev_unlock(wdev);

	return err;
}

static int nl80211_tdls_cancel_channel_switch(struct sk_buff *skb,
					      struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
	struct net_device *dev = info->user_ptr[1];
	struct wireless_dev *wdev = dev->ieee80211_ptr;
	const u8 *addr;

	if (!rdev->ops->tdls_channel_switch ||
	    !rdev->ops->tdls_cancel_channel_switch ||
	    !(rdev->wiphy.features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH))
		return -EOPNOTSUPP;

	switch (dev->ieee80211_ptr->iftype) {
	case NL80211_IFTYPE_STATION:
	case NL80211_IFTYPE_P2P_CLIENT:
		break;
	default:
		return -EOPNOTSUPP;
	}

	if (!info->attrs[NL80211_ATTR_MAC])
		return -EINVAL;

	addr = nla_data(info->attrs[NL80211_ATTR_MAC]);

	wdev_lock(wdev);
	rdev_tdls_cancel_channel_switch(rdev, dev, addr);
	wdev_unlock(wdev);

	return 0;
}

10225 10226 10227
#define NL80211_FLAG_NEED_WIPHY		0x01
#define NL80211_FLAG_NEED_NETDEV	0x02
#define NL80211_FLAG_NEED_RTNL		0x04
10228 10229 10230
#define NL80211_FLAG_CHECK_NETDEV_UP	0x08
#define NL80211_FLAG_NEED_NETDEV_UP	(NL80211_FLAG_NEED_NETDEV |\
					 NL80211_FLAG_CHECK_NETDEV_UP)
10231
#define NL80211_FLAG_NEED_WDEV		0x10
10232
/* If a netdev is associated, it must be UP, P2P must be started */
10233 10234
#define NL80211_FLAG_NEED_WDEV_UP	(NL80211_FLAG_NEED_WDEV |\
					 NL80211_FLAG_CHECK_NETDEV_UP)
10235
#define NL80211_FLAG_CLEAR_SKB		0x20
10236

10237
static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
10238 10239 10240
			    struct genl_info *info)
{
	struct cfg80211_registered_device *rdev;
10241
	struct wireless_dev *wdev;
10242 10243 10244 10245 10246 10247 10248
	struct net_device *dev;
	bool rtnl = ops->internal_flags & NL80211_FLAG_NEED_RTNL;

	if (rtnl)
		rtnl_lock();

	if (ops->internal_flags & NL80211_FLAG_NEED_WIPHY) {
10249
		rdev = cfg80211_get_dev_from_info(genl_info_net(info), info);
10250 10251 10252 10253 10254 10255
		if (IS_ERR(rdev)) {
			if (rtnl)
				rtnl_unlock();
			return PTR_ERR(rdev);
		}
		info->user_ptr[0] = rdev;
10256 10257
	} else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV ||
		   ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
10258 10259
		ASSERT_RTNL();

10260 10261 10262
		wdev = __cfg80211_wdev_from_attrs(genl_info_net(info),
						  info->attrs);
		if (IS_ERR(wdev)) {
10263 10264
			if (rtnl)
				rtnl_unlock();
10265
			return PTR_ERR(wdev);
10266
		}
10267 10268

		dev = wdev->netdev;
10269
		rdev = wiphy_to_rdev(wdev->wiphy);
10270

10271 10272 10273 10274 10275 10276 10277 10278 10279 10280
		if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) {
			if (!dev) {
				if (rtnl)
					rtnl_unlock();
				return -EINVAL;
			}

			info->user_ptr[1] = dev;
		} else {
			info->user_ptr[1] = wdev;
10281
		}
10282 10283 10284 10285 10286 10287 10288 10289 10290 10291

		if (dev) {
			if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
			    !netif_running(dev)) {
				if (rtnl)
					rtnl_unlock();
				return -ENETDOWN;
			}

			dev_hold(dev);
10292 10293 10294 10295 10296 10297
		} else if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP) {
			if (!wdev->p2p_started) {
				if (rtnl)
					rtnl_unlock();
				return -ENETDOWN;
			}
10298
		}
10299

10300 10301 10302 10303 10304 10305
		info->user_ptr[0] = rdev;
	}

	return 0;
}

10306
static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
10307 10308
			      struct genl_info *info)
{
10309 10310 10311 10312 10313 10314 10315 10316 10317 10318
	if (info->user_ptr[1]) {
		if (ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
			struct wireless_dev *wdev = info->user_ptr[1];

			if (wdev->netdev)
				dev_put(wdev->netdev);
		} else {
			dev_put(info->user_ptr[1]);
		}
	}
10319

10320 10321
	if (ops->internal_flags & NL80211_FLAG_NEED_RTNL)
		rtnl_unlock();
10322 10323 10324 10325 10326 10327 10328 10329 10330 10331 10332

	/* If needed, clear the netlink message payload from the SKB
	 * as it might contain key data that shouldn't stick around on
	 * the heap after the SKB is freed. The netlink message header
	 * is still needed for further processing, so leave it intact.
	 */
	if (ops->internal_flags & NL80211_FLAG_CLEAR_SKB) {
		struct nlmsghdr *nlh = nlmsg_hdr(skb);

		memset(nlmsg_data(nlh), 0, nlmsg_len(nlh));
	}
10333 10334
}

10335
static const struct genl_ops nl80211_ops[] = {
10336 10337 10338 10339
	{
		.cmd = NL80211_CMD_GET_WIPHY,
		.doit = nl80211_get_wiphy,
		.dumpit = nl80211_dump_wiphy,
10340
		.done = nl80211_dump_wiphy_done,
10341 10342
		.policy = nl80211_policy,
		/* can be retrieved by unprivileged users */
10343 10344
		.internal_flags = NL80211_FLAG_NEED_WIPHY |
				  NL80211_FLAG_NEED_RTNL,
10345 10346 10347 10348 10349 10350
	},
	{
		.cmd = NL80211_CMD_SET_WIPHY,
		.doit = nl80211_set_wiphy,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10351
		.internal_flags = NL80211_FLAG_NEED_RTNL,
10352 10353 10354 10355 10356 10357 10358
	},
	{
		.cmd = NL80211_CMD_GET_INTERFACE,
		.doit = nl80211_get_interface,
		.dumpit = nl80211_dump_interface,
		.policy = nl80211_policy,
		/* can be retrieved by unprivileged users */
10359 10360
		.internal_flags = NL80211_FLAG_NEED_WDEV |
				  NL80211_FLAG_NEED_RTNL,
10361 10362 10363 10364 10365 10366
	},
	{
		.cmd = NL80211_CMD_SET_INTERFACE,
		.doit = nl80211_set_interface,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10367 10368
		.internal_flags = NL80211_FLAG_NEED_NETDEV |
				  NL80211_FLAG_NEED_RTNL,
10369 10370 10371 10372 10373 10374
	},
	{
		.cmd = NL80211_CMD_NEW_INTERFACE,
		.doit = nl80211_new_interface,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10375 10376
		.internal_flags = NL80211_FLAG_NEED_WIPHY |
				  NL80211_FLAG_NEED_RTNL,
10377 10378 10379 10380 10381
	},
	{
		.cmd = NL80211_CMD_DEL_INTERFACE,
		.doit = nl80211_del_interface,
		.policy = nl80211_policy,
10382
		.flags = GENL_ADMIN_PERM,
10383
		.internal_flags = NL80211_FLAG_NEED_WDEV |
10384
				  NL80211_FLAG_NEED_RTNL,
10385 10386 10387 10388 10389 10390
	},
	{
		.cmd = NL80211_CMD_GET_KEY,
		.doit = nl80211_get_key,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10391
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10392
				  NL80211_FLAG_NEED_RTNL,
10393 10394 10395 10396 10397 10398
	},
	{
		.cmd = NL80211_CMD_SET_KEY,
		.doit = nl80211_set_key,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10399
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10400 10401
				  NL80211_FLAG_NEED_RTNL |
				  NL80211_FLAG_CLEAR_SKB,
10402 10403 10404 10405 10406 10407
	},
	{
		.cmd = NL80211_CMD_NEW_KEY,
		.doit = nl80211_new_key,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10408
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10409 10410
				  NL80211_FLAG_NEED_RTNL |
				  NL80211_FLAG_CLEAR_SKB,
10411 10412 10413 10414 10415
	},
	{
		.cmd = NL80211_CMD_DEL_KEY,
		.doit = nl80211_del_key,
		.policy = nl80211_policy,
10416
		.flags = GENL_ADMIN_PERM,
10417
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10418
				  NL80211_FLAG_NEED_RTNL,
10419
	},
10420 10421 10422 10423
	{
		.cmd = NL80211_CMD_SET_BEACON,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10424
		.doit = nl80211_set_beacon,
10425
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10426
				  NL80211_FLAG_NEED_RTNL,
10427 10428
	},
	{
10429
		.cmd = NL80211_CMD_START_AP,
10430 10431
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10432
		.doit = nl80211_start_ap,
10433
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10434
				  NL80211_FLAG_NEED_RTNL,
10435 10436
	},
	{
10437
		.cmd = NL80211_CMD_STOP_AP,
10438 10439
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10440
		.doit = nl80211_stop_ap,
10441
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10442
				  NL80211_FLAG_NEED_RTNL,
10443
	},
10444 10445 10446
	{
		.cmd = NL80211_CMD_GET_STATION,
		.doit = nl80211_get_station,
10447
		.dumpit = nl80211_dump_station,
10448
		.policy = nl80211_policy,
10449 10450
		.internal_flags = NL80211_FLAG_NEED_NETDEV |
				  NL80211_FLAG_NEED_RTNL,
10451 10452 10453 10454 10455 10456
	},
	{
		.cmd = NL80211_CMD_SET_STATION,
		.doit = nl80211_set_station,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10457
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10458
				  NL80211_FLAG_NEED_RTNL,
10459 10460 10461 10462 10463 10464
	},
	{
		.cmd = NL80211_CMD_NEW_STATION,
		.doit = nl80211_new_station,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10465
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10466
				  NL80211_FLAG_NEED_RTNL,
10467 10468 10469 10470 10471
	},
	{
		.cmd = NL80211_CMD_DEL_STATION,
		.doit = nl80211_del_station,
		.policy = nl80211_policy,
10472
		.flags = GENL_ADMIN_PERM,
10473
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10474
				  NL80211_FLAG_NEED_RTNL,
10475 10476 10477 10478 10479 10480 10481
	},
	{
		.cmd = NL80211_CMD_GET_MPATH,
		.doit = nl80211_get_mpath,
		.dumpit = nl80211_dump_mpath,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10482
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10483
				  NL80211_FLAG_NEED_RTNL,
10484
	},
10485 10486 10487 10488 10489 10490 10491 10492 10493
	{
		.cmd = NL80211_CMD_GET_MPP,
		.doit = nl80211_get_mpp,
		.dumpit = nl80211_dump_mpp,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
				  NL80211_FLAG_NEED_RTNL,
	},
10494 10495 10496 10497 10498
	{
		.cmd = NL80211_CMD_SET_MPATH,
		.doit = nl80211_set_mpath,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10499
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10500
				  NL80211_FLAG_NEED_RTNL,
10501 10502 10503 10504 10505 10506
	},
	{
		.cmd = NL80211_CMD_NEW_MPATH,
		.doit = nl80211_new_mpath,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10507
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10508
				  NL80211_FLAG_NEED_RTNL,
10509 10510 10511 10512 10513
	},
	{
		.cmd = NL80211_CMD_DEL_MPATH,
		.doit = nl80211_del_mpath,
		.policy = nl80211_policy,
10514
		.flags = GENL_ADMIN_PERM,
10515
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10516
				  NL80211_FLAG_NEED_RTNL,
10517 10518 10519 10520 10521
	},
	{
		.cmd = NL80211_CMD_SET_BSS,
		.doit = nl80211_set_bss,
		.policy = nl80211_policy,
10522
		.flags = GENL_ADMIN_PERM,
10523
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10524
				  NL80211_FLAG_NEED_RTNL,
10525
	},
10526 10527
	{
		.cmd = NL80211_CMD_GET_REG,
10528 10529
		.doit = nl80211_get_reg_do,
		.dumpit = nl80211_get_reg_dump,
10530
		.policy = nl80211_policy,
10531
		.internal_flags = NL80211_FLAG_NEED_RTNL,
10532 10533
		/* can be retrieved by unprivileged users */
	},
10534 10535 10536 10537 10538
	{
		.cmd = NL80211_CMD_SET_REG,
		.doit = nl80211_set_reg,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10539
		.internal_flags = NL80211_FLAG_NEED_RTNL,
10540 10541 10542 10543 10544
	},
	{
		.cmd = NL80211_CMD_REQ_SET_REG,
		.doit = nl80211_req_set_reg,
		.policy = nl80211_policy,
10545 10546 10547
		.flags = GENL_ADMIN_PERM,
	},
	{
10548 10549
		.cmd = NL80211_CMD_GET_MESH_CONFIG,
		.doit = nl80211_get_mesh_config,
10550 10551
		.policy = nl80211_policy,
		/* can be retrieved by unprivileged users */
10552
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10553
				  NL80211_FLAG_NEED_RTNL,
10554 10555
	},
	{
10556 10557
		.cmd = NL80211_CMD_SET_MESH_CONFIG,
		.doit = nl80211_update_mesh_config,
10558
		.policy = nl80211_policy,
10559
		.flags = GENL_ADMIN_PERM,
10560
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10561
				  NL80211_FLAG_NEED_RTNL,
10562
	},
10563 10564 10565 10566 10567
	{
		.cmd = NL80211_CMD_TRIGGER_SCAN,
		.doit = nl80211_trigger_scan,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10568
		.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
10569
				  NL80211_FLAG_NEED_RTNL,
10570 10571 10572 10573 10574 10575
	},
	{
		.cmd = NL80211_CMD_GET_SCAN,
		.policy = nl80211_policy,
		.dumpit = nl80211_dump_scan,
	},
10576 10577 10578 10579 10580 10581 10582 10583 10584 10585 10586 10587 10588 10589 10590 10591
	{
		.cmd = NL80211_CMD_START_SCHED_SCAN,
		.doit = nl80211_start_sched_scan,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
				  NL80211_FLAG_NEED_RTNL,
	},
	{
		.cmd = NL80211_CMD_STOP_SCHED_SCAN,
		.doit = nl80211_stop_sched_scan,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
				  NL80211_FLAG_NEED_RTNL,
	},
10592 10593 10594 10595 10596
	{
		.cmd = NL80211_CMD_AUTHENTICATE,
		.doit = nl80211_authenticate,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10597
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10598 10599
				  NL80211_FLAG_NEED_RTNL |
				  NL80211_FLAG_CLEAR_SKB,
10600 10601 10602 10603 10604 10605
	},
	{
		.cmd = NL80211_CMD_ASSOCIATE,
		.doit = nl80211_associate,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10606
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10607
				  NL80211_FLAG_NEED_RTNL,
10608 10609 10610 10611 10612 10613
	},
	{
		.cmd = NL80211_CMD_DEAUTHENTICATE,
		.doit = nl80211_deauthenticate,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10614
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10615
				  NL80211_FLAG_NEED_RTNL,
10616 10617 10618 10619 10620 10621
	},
	{
		.cmd = NL80211_CMD_DISASSOCIATE,
		.doit = nl80211_disassociate,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10622
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10623
				  NL80211_FLAG_NEED_RTNL,
10624
	},
10625 10626 10627 10628 10629
	{
		.cmd = NL80211_CMD_JOIN_IBSS,
		.doit = nl80211_join_ibss,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10630
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10631
				  NL80211_FLAG_NEED_RTNL,
10632 10633 10634 10635 10636 10637
	},
	{
		.cmd = NL80211_CMD_LEAVE_IBSS,
		.doit = nl80211_leave_ibss,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10638
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10639
				  NL80211_FLAG_NEED_RTNL,
10640
	},
10641 10642 10643 10644
#ifdef CONFIG_NL80211_TESTMODE
	{
		.cmd = NL80211_CMD_TESTMODE,
		.doit = nl80211_testmode_do,
10645
		.dumpit = nl80211_testmode_dump,
10646 10647
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10648 10649
		.internal_flags = NL80211_FLAG_NEED_WIPHY |
				  NL80211_FLAG_NEED_RTNL,
10650 10651
	},
#endif
10652 10653 10654 10655 10656
	{
		.cmd = NL80211_CMD_CONNECT,
		.doit = nl80211_connect,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10657
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10658
				  NL80211_FLAG_NEED_RTNL,
10659 10660 10661 10662 10663 10664
	},
	{
		.cmd = NL80211_CMD_DISCONNECT,
		.doit = nl80211_disconnect,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10665
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10666
				  NL80211_FLAG_NEED_RTNL,
10667
	},
10668 10669 10670 10671 10672
	{
		.cmd = NL80211_CMD_SET_WIPHY_NETNS,
		.doit = nl80211_wiphy_netns,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10673 10674
		.internal_flags = NL80211_FLAG_NEED_WIPHY |
				  NL80211_FLAG_NEED_RTNL,
10675
	},
10676 10677 10678 10679 10680
	{
		.cmd = NL80211_CMD_GET_SURVEY,
		.policy = nl80211_policy,
		.dumpit = nl80211_dump_survey,
	},
10681 10682 10683 10684 10685
	{
		.cmd = NL80211_CMD_SET_PMKSA,
		.doit = nl80211_setdel_pmksa,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10686
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10687
				  NL80211_FLAG_NEED_RTNL,
10688 10689 10690 10691 10692 10693
	},
	{
		.cmd = NL80211_CMD_DEL_PMKSA,
		.doit = nl80211_setdel_pmksa,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10694
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10695
				  NL80211_FLAG_NEED_RTNL,
10696 10697 10698 10699 10700 10701
	},
	{
		.cmd = NL80211_CMD_FLUSH_PMKSA,
		.doit = nl80211_flush_pmksa,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10702
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10703
				  NL80211_FLAG_NEED_RTNL,
10704
	},
10705 10706 10707 10708 10709
	{
		.cmd = NL80211_CMD_REMAIN_ON_CHANNEL,
		.doit = nl80211_remain_on_channel,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10710
		.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
10711
				  NL80211_FLAG_NEED_RTNL,
10712 10713 10714 10715 10716 10717
	},
	{
		.cmd = NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
		.doit = nl80211_cancel_remain_on_channel,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10718
		.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
10719
				  NL80211_FLAG_NEED_RTNL,
10720
	},
10721 10722 10723 10724 10725
	{
		.cmd = NL80211_CMD_SET_TX_BITRATE_MASK,
		.doit = nl80211_set_tx_bitrate_mask,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10726 10727
		.internal_flags = NL80211_FLAG_NEED_NETDEV |
				  NL80211_FLAG_NEED_RTNL,
10728
	},
10729
	{
10730 10731
		.cmd = NL80211_CMD_REGISTER_FRAME,
		.doit = nl80211_register_mgmt,
10732 10733
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10734
		.internal_flags = NL80211_FLAG_NEED_WDEV |
10735
				  NL80211_FLAG_NEED_RTNL,
10736 10737
	},
	{
10738 10739
		.cmd = NL80211_CMD_FRAME,
		.doit = nl80211_tx_mgmt,
10740
		.policy = nl80211_policy,
10741
		.flags = GENL_ADMIN_PERM,
10742
		.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
10743 10744 10745 10746 10747 10748
				  NL80211_FLAG_NEED_RTNL,
	},
	{
		.cmd = NL80211_CMD_FRAME_WAIT_CANCEL,
		.doit = nl80211_tx_mgmt_cancel_wait,
		.policy = nl80211_policy,
10749
		.flags = GENL_ADMIN_PERM,
10750
		.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
10751
				  NL80211_FLAG_NEED_RTNL,
10752
	},
10753 10754 10755 10756 10757
	{
		.cmd = NL80211_CMD_SET_POWER_SAVE,
		.doit = nl80211_set_power_save,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10758 10759
		.internal_flags = NL80211_FLAG_NEED_NETDEV |
				  NL80211_FLAG_NEED_RTNL,
10760 10761 10762 10763 10764 10765
	},
	{
		.cmd = NL80211_CMD_GET_POWER_SAVE,
		.doit = nl80211_get_power_save,
		.policy = nl80211_policy,
		/* can be retrieved by unprivileged users */
10766 10767
		.internal_flags = NL80211_FLAG_NEED_NETDEV |
				  NL80211_FLAG_NEED_RTNL,
10768
	},
10769 10770 10771 10772 10773
	{
		.cmd = NL80211_CMD_SET_CQM,
		.doit = nl80211_set_cqm,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10774 10775
		.internal_flags = NL80211_FLAG_NEED_NETDEV |
				  NL80211_FLAG_NEED_RTNL,
10776
	},
10777 10778 10779 10780 10781
	{
		.cmd = NL80211_CMD_SET_CHANNEL,
		.doit = nl80211_set_channel,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10782 10783
		.internal_flags = NL80211_FLAG_NEED_NETDEV |
				  NL80211_FLAG_NEED_RTNL,
10784
	},
10785 10786 10787 10788 10789
	{
		.cmd = NL80211_CMD_SET_WDS_PEER,
		.doit = nl80211_set_wds_peer,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10790 10791
		.internal_flags = NL80211_FLAG_NEED_NETDEV |
				  NL80211_FLAG_NEED_RTNL,
10792
	},
10793 10794 10795 10796 10797 10798 10799 10800 10801 10802 10803 10804 10805 10806 10807 10808
	{
		.cmd = NL80211_CMD_JOIN_MESH,
		.doit = nl80211_join_mesh,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
				  NL80211_FLAG_NEED_RTNL,
	},
	{
		.cmd = NL80211_CMD_LEAVE_MESH,
		.doit = nl80211_leave_mesh,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
				  NL80211_FLAG_NEED_RTNL,
	},
10809 10810 10811 10812 10813 10814 10815 10816 10817 10818 10819 10820 10821 10822 10823 10824
	{
		.cmd = NL80211_CMD_JOIN_OCB,
		.doit = nl80211_join_ocb,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
				  NL80211_FLAG_NEED_RTNL,
	},
	{
		.cmd = NL80211_CMD_LEAVE_OCB,
		.doit = nl80211_leave_ocb,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
				  NL80211_FLAG_NEED_RTNL,
	},
10825
#ifdef CONFIG_PM
10826 10827 10828 10829 10830 10831 10832 10833 10834 10835 10836 10837 10838 10839 10840 10841
	{
		.cmd = NL80211_CMD_GET_WOWLAN,
		.doit = nl80211_get_wowlan,
		.policy = nl80211_policy,
		/* can be retrieved by unprivileged users */
		.internal_flags = NL80211_FLAG_NEED_WIPHY |
				  NL80211_FLAG_NEED_RTNL,
	},
	{
		.cmd = NL80211_CMD_SET_WOWLAN,
		.doit = nl80211_set_wowlan,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_WIPHY |
				  NL80211_FLAG_NEED_RTNL,
	},
10842
#endif
10843 10844 10845 10846 10847 10848
	{
		.cmd = NL80211_CMD_SET_REKEY_OFFLOAD,
		.doit = nl80211_set_rekey_data,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10849 10850
				  NL80211_FLAG_NEED_RTNL |
				  NL80211_FLAG_CLEAR_SKB,
10851
	},
10852 10853 10854 10855 10856 10857 10858 10859 10860 10861 10862 10863 10864 10865 10866 10867
	{
		.cmd = NL80211_CMD_TDLS_MGMT,
		.doit = nl80211_tdls_mgmt,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
				  NL80211_FLAG_NEED_RTNL,
	},
	{
		.cmd = NL80211_CMD_TDLS_OPER,
		.doit = nl80211_tdls_oper,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
				  NL80211_FLAG_NEED_RTNL,
	},
10868 10869 10870 10871 10872 10873 10874 10875
	{
		.cmd = NL80211_CMD_UNEXPECTED_FRAME,
		.doit = nl80211_register_unexpected_frame,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_NETDEV |
				  NL80211_FLAG_NEED_RTNL,
	},
10876 10877 10878 10879 10880
	{
		.cmd = NL80211_CMD_PROBE_CLIENT,
		.doit = nl80211_probe_client,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
10881
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10882 10883
				  NL80211_FLAG_NEED_RTNL,
	},
10884 10885 10886 10887 10888 10889 10890 10891
	{
		.cmd = NL80211_CMD_REGISTER_BEACONS,
		.doit = nl80211_register_beacons,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_WIPHY |
				  NL80211_FLAG_NEED_RTNL,
	},
10892 10893 10894 10895 10896 10897 10898 10899
	{
		.cmd = NL80211_CMD_SET_NOACK_MAP,
		.doit = nl80211_set_noack_map,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_NETDEV |
				  NL80211_FLAG_NEED_RTNL,
	},
10900 10901 10902 10903 10904 10905 10906 10907 10908 10909 10910 10911 10912 10913 10914 10915
	{
		.cmd = NL80211_CMD_START_P2P_DEVICE,
		.doit = nl80211_start_p2p_device,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_WDEV |
				  NL80211_FLAG_NEED_RTNL,
	},
	{
		.cmd = NL80211_CMD_STOP_P2P_DEVICE,
		.doit = nl80211_stop_p2p_device,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
				  NL80211_FLAG_NEED_RTNL,
	},
10916 10917 10918
	{
		.cmd = NL80211_CMD_SET_MCAST_RATE,
		.doit = nl80211_set_mcast_rate,
10919 10920 10921 10922 10923 10924 10925 10926
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_NETDEV |
				  NL80211_FLAG_NEED_RTNL,
	},
	{
		.cmd = NL80211_CMD_SET_MAC_ACL,
		.doit = nl80211_set_mac_acl,
10927 10928 10929 10930 10931
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_NETDEV |
				  NL80211_FLAG_NEED_RTNL,
	},
10932 10933 10934 10935 10936 10937 10938 10939
	{
		.cmd = NL80211_CMD_RADAR_DETECT,
		.doit = nl80211_start_radar_detection,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
				  NL80211_FLAG_NEED_RTNL,
	},
10940 10941 10942 10943 10944
	{
		.cmd = NL80211_CMD_GET_PROTOCOL_FEATURES,
		.doit = nl80211_get_protocol_features,
		.policy = nl80211_policy,
	},
10945 10946 10947 10948 10949 10950 10951 10952
	{
		.cmd = NL80211_CMD_UPDATE_FT_IES,
		.doit = nl80211_update_ft_ies,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
				  NL80211_FLAG_NEED_RTNL,
	},
10953 10954 10955 10956 10957 10958 10959 10960 10961 10962 10963 10964 10965 10966 10967
	{
		.cmd = NL80211_CMD_CRIT_PROTOCOL_START,
		.doit = nl80211_crit_protocol_start,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
				  NL80211_FLAG_NEED_RTNL,
	},
	{
		.cmd = NL80211_CMD_CRIT_PROTOCOL_STOP,
		.doit = nl80211_crit_protocol_stop,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
				  NL80211_FLAG_NEED_RTNL,
10968 10969 10970 10971 10972 10973 10974 10975 10976 10977 10978 10979 10980 10981 10982
	},
	{
		.cmd = NL80211_CMD_GET_COALESCE,
		.doit = nl80211_get_coalesce,
		.policy = nl80211_policy,
		.internal_flags = NL80211_FLAG_NEED_WIPHY |
				  NL80211_FLAG_NEED_RTNL,
	},
	{
		.cmd = NL80211_CMD_SET_COALESCE,
		.doit = nl80211_set_coalesce,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_WIPHY |
				  NL80211_FLAG_NEED_RTNL,
10983 10984 10985 10986 10987 10988 10989 10990 10991
	},
	{
		.cmd = NL80211_CMD_CHANNEL_SWITCH,
		.doit = nl80211_channel_switch,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
				  NL80211_FLAG_NEED_RTNL,
	},
10992 10993 10994 10995 10996 10997 10998 10999
	{
		.cmd = NL80211_CMD_VENDOR,
		.doit = nl80211_vendor_cmd,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_WIPHY |
				  NL80211_FLAG_NEED_RTNL,
	},
11000 11001 11002 11003 11004 11005 11006 11007
	{
		.cmd = NL80211_CMD_SET_QOS_MAP,
		.doit = nl80211_set_qos_map,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
				  NL80211_FLAG_NEED_RTNL,
	},
11008 11009 11010 11011 11012 11013 11014 11015 11016 11017 11018 11019 11020 11021 11022 11023
	{
		.cmd = NL80211_CMD_ADD_TX_TS,
		.doit = nl80211_add_tx_ts,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
				  NL80211_FLAG_NEED_RTNL,
	},
	{
		.cmd = NL80211_CMD_DEL_TX_TS,
		.doit = nl80211_del_tx_ts,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
				  NL80211_FLAG_NEED_RTNL,
	},
11024 11025 11026 11027 11028 11029 11030 11031 11032 11033 11034 11035 11036 11037 11038 11039
	{
		.cmd = NL80211_CMD_TDLS_CHANNEL_SWITCH,
		.doit = nl80211_tdls_channel_switch,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
				  NL80211_FLAG_NEED_RTNL,
	},
	{
		.cmd = NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH,
		.doit = nl80211_tdls_cancel_channel_switch,
		.policy = nl80211_policy,
		.flags = GENL_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
				  NL80211_FLAG_NEED_RTNL,
	},
11040
};
11041

11042 11043
/* notification functions */

11044 11045
void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev,
			  enum nl80211_commands cmd)
11046 11047
{
	struct sk_buff *msg;
11048
	struct nl80211_dump_wiphy_state state = {};
11049

11050 11051 11052
	WARN_ON(cmd != NL80211_CMD_NEW_WIPHY &&
		cmd != NL80211_CMD_DEL_WIPHY);

11053
	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
11054 11055 11056
	if (!msg)
		return;

11057
	if (nl80211_send_wiphy(rdev, cmd, msg, 0, 0, 0, &state) < 0) {
11058 11059 11060 11061
		nlmsg_free(msg);
		return;
	}

11062
	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
11063
				NL80211_MCGRP_CONFIG, GFP_KERNEL);
11064 11065
}

11066 11067 11068 11069 11070 11071 11072 11073 11074 11075 11076 11077 11078
static int nl80211_add_scan_req(struct sk_buff *msg,
				struct cfg80211_registered_device *rdev)
{
	struct cfg80211_scan_request *req = rdev->scan_req;
	struct nlattr *nest;
	int i;

	if (WARN_ON(!req))
		return 0;

	nest = nla_nest_start(msg, NL80211_ATTR_SCAN_SSIDS);
	if (!nest)
		goto nla_put_failure;
11079 11080 11081 11082
	for (i = 0; i < req->n_ssids; i++) {
		if (nla_put(msg, i, req->ssids[i].ssid_len, req->ssids[i].ssid))
			goto nla_put_failure;
	}
11083 11084 11085 11086 11087
	nla_nest_end(msg, nest);

	nest = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES);
	if (!nest)
		goto nla_put_failure;
11088 11089 11090 11091
	for (i = 0; i < req->n_channels; i++) {
		if (nla_put_u32(msg, i, req->channels[i]->center_freq))
			goto nla_put_failure;
	}
11092 11093
	nla_nest_end(msg, nest);

11094 11095 11096
	if (req->ie &&
	    nla_put(msg, NL80211_ATTR_IE, req->ie_len, req->ie))
		goto nla_put_failure;
11097

11098 11099 11100
	if (req->flags &&
	    nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags))
		goto nla_put_failure;
11101

11102 11103 11104 11105 11106
	return 0;
 nla_put_failure:
	return -ENOBUFS;
}

11107 11108
static int nl80211_send_scan_msg(struct sk_buff *msg,
				 struct cfg80211_registered_device *rdev,
11109
				 struct wireless_dev *wdev,
11110
				 u32 portid, u32 seq, int flags,
11111
				 u32 cmd)
11112 11113 11114
{
	void *hdr;

11115
	hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
11116 11117 11118
	if (!hdr)
		return -1;

11119
	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
11120 11121 11122
	    (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
					 wdev->netdev->ifindex)) ||
	    nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
11123
		goto nla_put_failure;
11124

11125 11126
	/* ignore errors and send incomplete event anyway */
	nl80211_add_scan_req(msg, rdev);
11127

11128 11129
	genlmsg_end(msg, hdr);
	return 0;
11130 11131 11132 11133 11134 11135

 nla_put_failure:
	genlmsg_cancel(msg, hdr);
	return -EMSGSIZE;
}

11136 11137 11138 11139
static int
nl80211_send_sched_scan_msg(struct sk_buff *msg,
			    struct cfg80211_registered_device *rdev,
			    struct net_device *netdev,
11140
			    u32 portid, u32 seq, int flags, u32 cmd)
11141 11142 11143
{
	void *hdr;

11144
	hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
11145 11146 11147
	if (!hdr)
		return -1;

11148 11149 11150
	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex))
		goto nla_put_failure;
11151

11152 11153
	genlmsg_end(msg, hdr);
	return 0;
11154 11155 11156 11157 11158 11159

 nla_put_failure:
	genlmsg_cancel(msg, hdr);
	return -EMSGSIZE;
}

11160
void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
11161
			     struct wireless_dev *wdev)
11162 11163 11164
{
	struct sk_buff *msg;

11165
	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
11166 11167 11168
	if (!msg)
		return;

11169
	if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0,
11170 11171 11172 11173 11174
				  NL80211_CMD_TRIGGER_SCAN) < 0) {
		nlmsg_free(msg);
		return;
	}

11175
	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
11176
				NL80211_MCGRP_SCAN, GFP_KERNEL);
11177 11178
}

11179 11180
struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
				       struct wireless_dev *wdev, bool aborted)
11181 11182 11183
{
	struct sk_buff *msg;

11184
	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
11185
	if (!msg)
11186
		return NULL;
11187

11188
	if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0,
11189 11190
				  aborted ? NL80211_CMD_SCAN_ABORTED :
					    NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
11191
		nlmsg_free(msg);
11192
		return NULL;
11193 11194
	}

11195
	return msg;
11196 11197
}

11198 11199
void nl80211_send_scan_result(struct cfg80211_registered_device *rdev,
			      struct sk_buff *msg)
11200 11201 11202 11203
{
	if (!msg)
		return;

11204
	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
11205
				NL80211_MCGRP_SCAN, GFP_KERNEL);
11206 11207
}

11208 11209 11210 11211 11212 11213 11214 11215 11216 11217 11218 11219 11220 11221 11222
void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev,
				     struct net_device *netdev)
{
	struct sk_buff *msg;

	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
	if (!msg)
		return;

	if (nl80211_send_sched_scan_msg(msg, rdev, netdev, 0, 0, 0,
					NL80211_CMD_SCHED_SCAN_RESULTS) < 0) {
		nlmsg_free(msg);
		return;
	}

11223
	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
11224
				NL80211_MCGRP_SCAN, GFP_KERNEL);
11225 11226 11227 11228 11229 11230 11231
}

void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev,
			     struct net_device *netdev, u32 cmd)
{
	struct sk_buff *msg;

11232
	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
11233 11234 11235 11236 11237 11238 11239 11240
	if (!msg)
		return;

	if (nl80211_send_sched_scan_msg(msg, rdev, netdev, 0, 0, 0, cmd) < 0) {
		nlmsg_free(msg);
		return;
	}

11241
	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
11242
				NL80211_MCGRP_SCAN, GFP_KERNEL);
11243 11244
}

11245 11246
static bool nl80211_reg_change_event_fill(struct sk_buff *msg,
					  struct regulatory_request *request)
11247 11248
{
	/* Userspace can always count this one always being set */
11249 11250 11251 11252 11253 11254 11255 11256 11257 11258 11259 11260 11261 11262 11263 11264 11265 11266 11267 11268 11269 11270 11271 11272
	if (nla_put_u8(msg, NL80211_ATTR_REG_INITIATOR, request->initiator))
		goto nla_put_failure;

	if (request->alpha2[0] == '0' && request->alpha2[1] == '0') {
		if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
			       NL80211_REGDOM_TYPE_WORLD))
			goto nla_put_failure;
	} else if (request->alpha2[0] == '9' && request->alpha2[1] == '9') {
		if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
			       NL80211_REGDOM_TYPE_CUSTOM_WORLD))
			goto nla_put_failure;
	} else if ((request->alpha2[0] == '9' && request->alpha2[1] == '8') ||
		   request->intersect) {
		if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
			       NL80211_REGDOM_TYPE_INTERSECTION))
			goto nla_put_failure;
	} else {
		if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
			       NL80211_REGDOM_TYPE_COUNTRY) ||
		    nla_put_string(msg, NL80211_ATTR_REG_ALPHA2,
				   request->alpha2))
			goto nla_put_failure;
	}

11273 11274 11275 11276 11277 11278
	if (request->wiphy_idx != WIPHY_IDX_INVALID) {
		struct wiphy *wiphy = wiphy_idx_to_wiphy(request->wiphy_idx);

		if (wiphy &&
		    nla_put_u32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx))
			goto nla_put_failure;
11279 11280 11281 11282 11283

		if (wiphy &&
		    wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
		    nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
			goto nla_put_failure;
11284
	}
11285

11286 11287 11288 11289 11290 11291 11292 11293 11294 11295 11296 11297 11298 11299 11300 11301 11302 11303 11304 11305 11306 11307 11308 11309 11310 11311 11312 11313 11314
	return true;

nla_put_failure:
	return false;
}

/*
 * This can happen on global regulatory changes or device specific settings
 * based on custom regulatory domains.
 */
void nl80211_common_reg_change_event(enum nl80211_commands cmd_id,
				     struct regulatory_request *request)
{
	struct sk_buff *msg;
	void *hdr;

	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
	if (!msg)
		return;

	hdr = nl80211hdr_put(msg, 0, 0, 0, cmd_id);
	if (!hdr) {
		nlmsg_free(msg);
		return;
	}

	if (nl80211_reg_change_event_fill(msg, request) == false)
		goto nla_put_failure;

11315
	genlmsg_end(msg, hdr);
11316

11317
	rcu_read_lock();
11318
	genlmsg_multicast_allns(&nl80211_fam, msg, 0,
11319
				NL80211_MCGRP_REGULATORY, GFP_ATOMIC);
11320
	rcu_read_unlock();
11321 11322 11323 11324 11325 11326 11327 11328

	return;

nla_put_failure:
	genlmsg_cancel(msg, hdr);
	nlmsg_free(msg);
}

11329 11330 11331
static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
				    struct net_device *netdev,
				    const u8 *buf, size_t len,
11332 11333
				    enum nl80211_commands cmd, gfp_t gfp,
				    int uapsd_queues)
11334 11335 11336 11337
{
	struct sk_buff *msg;
	void *hdr;

11338
	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
11339 11340 11341 11342 11343 11344 11345 11346 11347
	if (!msg)
		return;

	hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
	if (!hdr) {
		nlmsg_free(msg);
		return;
	}

11348 11349 11350 11351
	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
	    nla_put(msg, NL80211_ATTR_FRAME, len, buf))
		goto nla_put_failure;
11352

11353 11354 11355 11356 11357 11358 11359 11360 11361 11362 11363 11364 11365
	if (uapsd_queues >= 0) {
		struct nlattr *nla_wmm =
			nla_nest_start(msg, NL80211_ATTR_STA_WME);
		if (!nla_wmm)
			goto nla_put_failure;

		if (nla_put_u8(msg, NL80211_STA_WME_UAPSD_QUEUES,
			       uapsd_queues))
			goto nla_put_failure;

		nla_nest_end(msg, nla_wmm);
	}

11366
	genlmsg_end(msg, hdr);
11367

11368
	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
11369
				NL80211_MCGRP_MLME, gfp);
11370 11371 11372 11373 11374 11375 11376 11377
	return;

 nla_put_failure:
	genlmsg_cancel(msg, hdr);
	nlmsg_free(msg);
}

void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
11378 11379
			  struct net_device *netdev, const u8 *buf,
			  size_t len, gfp_t gfp)
11380 11381
{
	nl80211_send_mlme_event(rdev, netdev, buf, len,
11382
				NL80211_CMD_AUTHENTICATE, gfp, -1);
11383 11384 11385 11386
}

void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
			   struct net_device *netdev, const u8 *buf,
11387
			   size_t len, gfp_t gfp, int uapsd_queues)
11388
{
11389
	nl80211_send_mlme_event(rdev, netdev, buf, len,
11390
				NL80211_CMD_ASSOCIATE, gfp, uapsd_queues);
11391 11392
}

11393
void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
11394 11395
			 struct net_device *netdev, const u8 *buf,
			 size_t len, gfp_t gfp)
11396 11397
{
	nl80211_send_mlme_event(rdev, netdev, buf, len,
11398
				NL80211_CMD_DEAUTHENTICATE, gfp, -1);
11399 11400
}

11401 11402
void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
			   struct net_device *netdev, const u8 *buf,
11403
			   size_t len, gfp_t gfp)
11404 11405
{
	nl80211_send_mlme_event(rdev, netdev, buf, len,
11406
				NL80211_CMD_DISASSOCIATE, gfp, -1);
11407 11408
}

11409 11410
void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf,
				  size_t len)
11411
{
11412 11413
	struct wireless_dev *wdev = dev->ieee80211_ptr;
	struct wiphy *wiphy = wdev->wiphy;
11414
	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
11415 11416
	const struct ieee80211_mgmt *mgmt = (void *)buf;
	u32 cmd;
11417

11418 11419
	if (WARN_ON(len < 2))
		return;
11420

11421 11422 11423 11424
	if (ieee80211_is_deauth(mgmt->frame_control))
		cmd = NL80211_CMD_UNPROT_DEAUTHENTICATE;
	else
		cmd = NL80211_CMD_UNPROT_DISASSOCIATE;
11425

11426
	trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len);
11427
	nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC, -1);
11428
}
11429
EXPORT_SYMBOL(cfg80211_rx_unprot_mlme_mgmt);
11430

11431 11432
static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev,
				      struct net_device *netdev, int cmd,
11433
				      const u8 *addr, gfp_t gfp)
11434 11435 11436 11437
{
	struct sk_buff *msg;
	void *hdr;

11438
	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
11439 11440 11441 11442 11443 11444 11445 11446 11447
	if (!msg)
		return;

	hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
	if (!hdr) {
		nlmsg_free(msg);
		return;
	}

11448 11449 11450 11451 11452
	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
	    nla_put_flag(msg, NL80211_ATTR_TIMED_OUT) ||
	    nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
		goto nla_put_failure;
11453

11454
	genlmsg_end(msg, hdr);
11455

11456
	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
11457
				NL80211_MCGRP_MLME, gfp);
11458 11459 11460 11461 11462 11463 11464 11465
	return;

 nla_put_failure:
	genlmsg_cancel(msg, hdr);
	nlmsg_free(msg);
}

void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev,
11466 11467
			       struct net_device *netdev, const u8 *addr,
			       gfp_t gfp)
11468 11469
{
	nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_AUTHENTICATE,
11470
				  addr, gfp);
11471 11472 11473
}

void nl80211_send_assoc_timeout(struct cfg80211_registered_device *rdev,
11474 11475
				struct net_device *netdev, const u8 *addr,
				gfp_t gfp)
11476
{
11477 11478
	nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_ASSOCIATE,
				  addr, gfp);
11479 11480
}

11481 11482 11483 11484 11485 11486 11487 11488 11489
void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
				 struct net_device *netdev, const u8 *bssid,
				 const u8 *req_ie, size_t req_ie_len,
				 const u8 *resp_ie, size_t resp_ie_len,
				 u16 status, gfp_t gfp)
{
	struct sk_buff *msg;
	void *hdr;

11490
	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
11491 11492 11493 11494 11495 11496 11497 11498 11499
	if (!msg)
		return;

	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONNECT);
	if (!hdr) {
		nlmsg_free(msg);
		return;
	}

11500 11501 11502 11503 11504 11505 11506 11507 11508
	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
	    (bssid && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid)) ||
	    nla_put_u16(msg, NL80211_ATTR_STATUS_CODE, status) ||
	    (req_ie &&
	     nla_put(msg, NL80211_ATTR_REQ_IE, req_ie_len, req_ie)) ||
	    (resp_ie &&
	     nla_put(msg, NL80211_ATTR_RESP_IE, resp_ie_len, resp_ie)))
		goto nla_put_failure;
11509

11510
	genlmsg_end(msg, hdr);
11511

11512
	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
11513
				NL80211_MCGRP_MLME, gfp);
11514 11515 11516 11517 11518 11519 11520 11521 11522 11523 11524 11525 11526 11527 11528 11529
	return;

 nla_put_failure:
	genlmsg_cancel(msg, hdr);
	nlmsg_free(msg);

}

void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
			 struct net_device *netdev, const u8 *bssid,
			 const u8 *req_ie, size_t req_ie_len,
			 const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp)
{
	struct sk_buff *msg;
	void *hdr;

11530
	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
11531 11532 11533 11534 11535 11536 11537 11538 11539
	if (!msg)
		return;

	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ROAM);
	if (!hdr) {
		nlmsg_free(msg);
		return;
	}

11540 11541 11542 11543 11544 11545 11546 11547
	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
	    nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid) ||
	    (req_ie &&
	     nla_put(msg, NL80211_ATTR_REQ_IE, req_ie_len, req_ie)) ||
	    (resp_ie &&
	     nla_put(msg, NL80211_ATTR_RESP_IE, resp_ie_len, resp_ie)))
		goto nla_put_failure;
11548

11549
	genlmsg_end(msg, hdr);
11550

11551
	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
11552
				NL80211_MCGRP_MLME, gfp);
11553 11554 11555 11556 11557 11558 11559 11560 11561 11562
	return;

 nla_put_failure:
	genlmsg_cancel(msg, hdr);
	nlmsg_free(msg);

}

void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
			       struct net_device *netdev, u16 reason,
Johannes Berg's avatar
Johannes Berg committed
11563
			       const u8 *ie, size_t ie_len, bool from_ap)
11564 11565 11566 11567
{
	struct sk_buff *msg;
	void *hdr;

11568
	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
11569 11570 11571 11572 11573 11574 11575 11576 11577
	if (!msg)
		return;

	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_DISCONNECT);
	if (!hdr) {
		nlmsg_free(msg);
		return;
	}

11578 11579 11580 11581 11582 11583 11584 11585
	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
	    (from_ap && reason &&
	     nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason)) ||
	    (from_ap &&
	     nla_put_flag(msg, NL80211_ATTR_DISCONNECTED_BY_AP)) ||
	    (ie && nla_put(msg, NL80211_ATTR_IE, ie_len, ie)))
		goto nla_put_failure;
11586

11587
	genlmsg_end(msg, hdr);
11588

11589
	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
11590
				NL80211_MCGRP_MLME, GFP_KERNEL);
11591 11592 11593 11594 11595 11596 11597 11598
	return;

 nla_put_failure:
	genlmsg_cancel(msg, hdr);
	nlmsg_free(msg);

}

11599 11600 11601 11602 11603 11604 11605
void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
			     struct net_device *netdev, const u8 *bssid,
			     gfp_t gfp)
{
	struct sk_buff *msg;
	void *hdr;

11606
	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
11607 11608 11609 11610 11611 11612 11613 11614 11615
	if (!msg)
		return;

	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_JOIN_IBSS);
	if (!hdr) {
		nlmsg_free(msg);
		return;
	}

11616 11617 11618 11619
	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
	    nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))
		goto nla_put_failure;
11620

11621
	genlmsg_end(msg, hdr);
11622

11623
	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
11624
				NL80211_MCGRP_MLME, gfp);
11625 11626 11627 11628 11629 11630 11631
	return;

 nla_put_failure:
	genlmsg_cancel(msg, hdr);
	nlmsg_free(msg);
}

11632 11633
void cfg80211_notify_new_peer_candidate(struct net_device *dev, const u8 *addr,
					const u8* ie, u8 ie_len, gfp_t gfp)
11634
{
11635
	struct wireless_dev *wdev = dev->ieee80211_ptr;
11636
	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
11637 11638 11639
	struct sk_buff *msg;
	void *hdr;

11640 11641 11642 11643 11644
	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_MESH_POINT))
		return;

	trace_cfg80211_notify_new_peer_candidate(dev, addr);

11645 11646 11647 11648 11649 11650 11651 11652 11653 11654
	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
	if (!msg)
		return;

	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NEW_PEER_CANDIDATE);
	if (!hdr) {
		nlmsg_free(msg);
		return;
	}

11655
	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
11656 11657
	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
	    nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
11658 11659 11660
	    (ie_len && ie &&
	     nla_put(msg, NL80211_ATTR_IE, ie_len , ie)))
		goto nla_put_failure;
11661

11662
	genlmsg_end(msg, hdr);
11663

11664
	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
11665
				NL80211_MCGRP_MLME, gfp);
11666 11667 11668 11669 11670 11671
	return;

 nla_put_failure:
	genlmsg_cancel(msg, hdr);
	nlmsg_free(msg);
}
11672
EXPORT_SYMBOL(cfg80211_notify_new_peer_candidate);
11673

11674 11675 11676
void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
				 struct net_device *netdev, const u8 *addr,
				 enum nl80211_key_type key_type, int key_id,
11677
				 const u8 *tsc, gfp_t gfp)
11678 11679 11680 11681
{
	struct sk_buff *msg;
	void *hdr;

11682
	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
11683 11684 11685 11686 11687 11688 11689 11690 11691
	if (!msg)
		return;

	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_MICHAEL_MIC_FAILURE);
	if (!hdr) {
		nlmsg_free(msg);
		return;
	}

11692 11693 11694 11695 11696 11697 11698 11699
	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
	    (addr && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) ||
	    nla_put_u32(msg, NL80211_ATTR_KEY_TYPE, key_type) ||
	    (key_id != -1 &&
	     nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_id)) ||
	    (tsc && nla_put(msg, NL80211_ATTR_KEY_SEQ, 6, tsc)))
		goto nla_put_failure;
11700

11701
	genlmsg_end(msg, hdr);
11702

11703
	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
11704
				NL80211_MCGRP_MLME, gfp);
11705 11706 11707 11708 11709 11710 11711
	return;

 nla_put_failure:
	genlmsg_cancel(msg, hdr);
	nlmsg_free(msg);
}

11712 11713 11714 11715 11716 11717 11718 11719
void nl80211_send_beacon_hint_event(struct wiphy *wiphy,
				    struct ieee80211_channel *channel_before,
				    struct ieee80211_channel *channel_after)
{
	struct sk_buff *msg;
	void *hdr;
	struct nlattr *nl_freq;

11720
	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
11721 11722 11723 11724 11725 11726 11727 11728 11729 11730 11731 11732 11733
	if (!msg)
		return;

	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_REG_BEACON_HINT);
	if (!hdr) {
		nlmsg_free(msg);
		return;
	}

	/*
	 * Since we are applying the beacon hint to a wiphy we know its
	 * wiphy_idx is valid
	 */
11734 11735
	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
		goto nla_put_failure;
11736 11737 11738 11739 11740

	/* Before */
	nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_BEFORE);
	if (!nl_freq)
		goto nla_put_failure;
11741
	if (nl80211_msg_put_channel(msg, channel_before, false))
11742 11743 11744 11745 11746 11747 11748
		goto nla_put_failure;
	nla_nest_end(msg, nl_freq);

	/* After */
	nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_AFTER);
	if (!nl_freq)
		goto nla_put_failure;
11749
	if (nl80211_msg_put_channel(msg, channel_after, false))
11750 11751 11752
		goto nla_put_failure;
	nla_nest_end(msg, nl_freq);

11753
	genlmsg_end(msg, hdr);
11754

11755
	rcu_read_lock();
11756
	genlmsg_multicast_allns(&nl80211_fam, msg, 0,
11757
				NL80211_MCGRP_REGULATORY, GFP_ATOMIC);
11758
	rcu_read_unlock();
11759 11760 11761 11762 11763 11764 11765 11766

	return;

nla_put_failure:
	genlmsg_cancel(msg, hdr);
	nlmsg_free(msg);
}

11767 11768
static void nl80211_send_remain_on_chan_event(
	int cmd, struct cfg80211_registered_device *rdev,
11769
	struct wireless_dev *wdev, u64 cookie,
11770 11771 11772 11773 11774 11775 11776 11777 11778 11779 11780 11781 11782 11783 11784 11785
	struct ieee80211_channel *chan,
	unsigned int duration, gfp_t gfp)
{
	struct sk_buff *msg;
	void *hdr;

	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
	if (!msg)
		return;

	hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
	if (!hdr) {
		nlmsg_free(msg);
		return;
	}

11786
	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
11787 11788
	    (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
					 wdev->netdev->ifindex)) ||
11789
	    nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) ||
11790
	    nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, chan->center_freq) ||
11791 11792
	    nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
			NL80211_CHAN_NO_HT) ||
11793 11794
	    nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie))
		goto nla_put_failure;
11795

11796 11797 11798
	if (cmd == NL80211_CMD_REMAIN_ON_CHANNEL &&
	    nla_put_u32(msg, NL80211_ATTR_DURATION, duration))
		goto nla_put_failure;
11799

11800
	genlmsg_end(msg, hdr);
11801

11802
	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
11803
				NL80211_MCGRP_MLME, gfp);
11804 11805 11806 11807 11808 11809 11810
	return;

 nla_put_failure:
	genlmsg_cancel(msg, hdr);
	nlmsg_free(msg);
}

11811 11812 11813
void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
			       struct ieee80211_channel *chan,
			       unsigned int duration, gfp_t gfp)
11814
{
11815
	struct wiphy *wiphy = wdev->wiphy;
11816
	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
11817 11818

	trace_cfg80211_ready_on_channel(wdev, cookie, chan, duration);
11819
	nl80211_send_remain_on_chan_event(NL80211_CMD_REMAIN_ON_CHANNEL,
11820
					  rdev, wdev, cookie, chan,
11821
					  duration, gfp);
11822
}
11823
EXPORT_SYMBOL(cfg80211_ready_on_channel);
11824

11825 11826 11827
void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,
					struct ieee80211_channel *chan,
					gfp_t gfp)
11828
{
11829
	struct wiphy *wiphy = wdev->wiphy;
11830
	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
11831 11832

	trace_cfg80211_ready_on_channel_expired(wdev, cookie, chan);
11833
	nl80211_send_remain_on_chan_event(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
11834
					  rdev, wdev, cookie, chan, 0, gfp);
11835
}
11836
EXPORT_SYMBOL(cfg80211_remain_on_channel_expired);
11837

11838 11839
void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
		      struct station_info *sinfo, gfp_t gfp)
11840
{
11841
	struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
11842
	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
11843 11844
	struct sk_buff *msg;

11845 11846
	trace_cfg80211_new_sta(dev, mac_addr, sinfo);

11847
	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
11848 11849 11850
	if (!msg)
		return;

11851
	if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION, 0, 0, 0,
11852
				 rdev, dev, mac_addr, sinfo) < 0) {
11853 11854 11855 11856
		nlmsg_free(msg);
		return;
	}

11857
	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
11858
				NL80211_MCGRP_MLME, gfp);
11859
}
11860
EXPORT_SYMBOL(cfg80211_new_sta);
11861

11862 11863
void cfg80211_del_sta_sinfo(struct net_device *dev, const u8 *mac_addr,
			    struct station_info *sinfo, gfp_t gfp)
11864
{
11865
	struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
11866
	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
11867
	struct sk_buff *msg;
11868 11869 11870 11871
	struct station_info empty_sinfo = {};

	if (!sinfo)
		sinfo = &empty_sinfo;
11872

11873 11874
	trace_cfg80211_del_sta(dev, mac_addr);

11875
	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
11876 11877 11878
	if (!msg)
		return;

11879
	if (nl80211_send_station(msg, NL80211_CMD_DEL_STATION, 0, 0, 0,
11880
				 rdev, dev, mac_addr, sinfo) < 0) {
11881 11882 11883 11884
		nlmsg_free(msg);
		return;
	}

11885
	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
11886
				NL80211_MCGRP_MLME, gfp);
11887
}
11888
EXPORT_SYMBOL(cfg80211_del_sta_sinfo);
11889

11890 11891 11892
void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr,
			  enum nl80211_connect_failed_reason reason,
			  gfp_t gfp)
11893
{
11894
	struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
11895
	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
11896 11897 11898 11899 11900 11901 11902 11903 11904 11905 11906 11907 11908 11909 11910 11911 11912 11913 11914 11915
	struct sk_buff *msg;
	void *hdr;

	msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
	if (!msg)
		return;

	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONN_FAILED);
	if (!hdr) {
		nlmsg_free(msg);
		return;
	}

	if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
	    nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr) ||
	    nla_put_u32(msg, NL80211_ATTR_CONN_FAILED_REASON, reason))
		goto nla_put_failure;

	genlmsg_end(msg, hdr);

11916
	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
11917
				NL80211_MCGRP_MLME, gfp);
11918 11919 11920 11921 11922 11923
	return;

 nla_put_failure:
	genlmsg_cancel(msg, hdr);
	nlmsg_free(msg);
}
11924
EXPORT_SYMBOL(cfg80211_conn_failed);
11925

11926 11927
static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd,
				       const u8 *addr, gfp_t gfp)
11928 11929
{
	struct wireless_dev *wdev = dev->ieee80211_ptr;
11930
	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
11931 11932
	struct sk_buff *msg;
	void *hdr;
11933
	u32 nlportid = ACCESS_ONCE(wdev->ap_unexpected_nlportid);
11934

11935
	if (!nlportid)
11936 11937 11938 11939 11940 11941
		return false;

	msg = nlmsg_new(100, gfp);
	if (!msg)
		return true;

11942
	hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
11943 11944 11945 11946 11947
	if (!hdr) {
		nlmsg_free(msg);
		return true;
	}

11948 11949 11950 11951
	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
	    nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
		goto nla_put_failure;
11952

11953
	genlmsg_end(msg, hdr);
11954
	genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
11955 11956 11957 11958 11959 11960 11961 11962
	return true;

 nla_put_failure:
	genlmsg_cancel(msg, hdr);
	nlmsg_free(msg);
	return true;
}

11963 11964
bool cfg80211_rx_spurious_frame(struct net_device *dev,
				const u8 *addr, gfp_t gfp)
11965
{
11966 11967 11968 11969 11970 11971 11972 11973 11974 11975 11976 11977 11978 11979
	struct wireless_dev *wdev = dev->ieee80211_ptr;
	bool ret;

	trace_cfg80211_rx_spurious_frame(dev, addr);

	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
		    wdev->iftype != NL80211_IFTYPE_P2P_GO)) {
		trace_cfg80211_return_bool(false);
		return false;
	}
	ret = __nl80211_unexpected_frame(dev, NL80211_CMD_UNEXPECTED_FRAME,
					 addr, gfp);
	trace_cfg80211_return_bool(ret);
	return ret;
11980
}
11981
EXPORT_SYMBOL(cfg80211_rx_spurious_frame);
11982

11983 11984
bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev,
					const u8 *addr, gfp_t gfp)
11985
{
11986 11987 11988 11989 11990 11991 11992 11993 11994 11995 11996 11997 11998 11999 12000 12001
	struct wireless_dev *wdev = dev->ieee80211_ptr;
	bool ret;

	trace_cfg80211_rx_unexpected_4addr_frame(dev, addr);

	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
		    wdev->iftype != NL80211_IFTYPE_P2P_GO &&
		    wdev->iftype != NL80211_IFTYPE_AP_VLAN)) {
		trace_cfg80211_return_bool(false);
		return false;
	}
	ret = __nl80211_unexpected_frame(dev,
					 NL80211_CMD_UNEXPECTED_4ADDR_FRAME,
					 addr, gfp);
	trace_cfg80211_return_bool(ret);
	return ret;
12002
}
12003
EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame);
12004

12005
int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
12006
		      struct wireless_dev *wdev, u32 nlportid,
12007
		      int freq, int sig_dbm,
12008
		      const u8 *buf, size_t len, u32 flags, gfp_t gfp)
12009
{
12010
	struct net_device *netdev = wdev->netdev;
12011 12012 12013 12014 12015 12016 12017
	struct sk_buff *msg;
	void *hdr;

	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
	if (!msg)
		return -ENOMEM;

12018
	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME);
12019 12020 12021 12022 12023
	if (!hdr) {
		nlmsg_free(msg);
		return -ENOMEM;
	}

12024
	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
12025 12026
	    (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
					netdev->ifindex)) ||
12027
	    nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) ||
12028 12029 12030
	    nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) ||
	    (sig_dbm &&
	     nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) ||
12031 12032 12033
	    nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
	    (flags &&
	     nla_put_u32(msg, NL80211_ATTR_RXMGMT_FLAGS, flags)))
12034
		goto nla_put_failure;
12035

12036
	genlmsg_end(msg, hdr);
12037

12038
	return genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
12039 12040 12041 12042 12043 12044 12045

 nla_put_failure:
	genlmsg_cancel(msg, hdr);
	nlmsg_free(msg);
	return -ENOBUFS;
}

12046 12047
void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
			     const u8 *buf, size_t len, bool ack, gfp_t gfp)
12048
{
12049
	struct wiphy *wiphy = wdev->wiphy;
12050
	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
12051
	struct net_device *netdev = wdev->netdev;
12052 12053 12054
	struct sk_buff *msg;
	void *hdr;

12055 12056
	trace_cfg80211_mgmt_tx_status(wdev, cookie, ack);

12057 12058 12059 12060
	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
	if (!msg)
		return;

12061
	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME_TX_STATUS);
12062 12063 12064 12065 12066
	if (!hdr) {
		nlmsg_free(msg);
		return;
	}

12067
	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
12068 12069
	    (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
				   netdev->ifindex)) ||
12070
	    nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) ||
12071 12072 12073 12074
	    nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
	    nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie) ||
	    (ack && nla_put_flag(msg, NL80211_ATTR_ACK)))
		goto nla_put_failure;
12075

12076
	genlmsg_end(msg, hdr);
12077

12078
	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
12079
				NL80211_MCGRP_MLME, gfp);
12080 12081 12082 12083 12084 12085
	return;

 nla_put_failure:
	genlmsg_cancel(msg, hdr);
	nlmsg_free(msg);
}
12086
EXPORT_SYMBOL(cfg80211_mgmt_tx_status);
12087

12088 12089
static struct sk_buff *cfg80211_prepare_cqm(struct net_device *dev,
					    const char *mac, gfp_t gfp)
12090
{
12091
	struct wireless_dev *wdev = dev->ieee80211_ptr;
12092 12093 12094
	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
	struct sk_buff *msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
	void **cb;
12095

12096
	if (!msg)
12097
		return NULL;
12098

12099 12100 12101 12102
	cb = (void **)msg->cb;

	cb[0] = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NOTIFY_CQM);
	if (!cb[0]) {
12103
		nlmsg_free(msg);
12104
		return NULL;
12105 12106
	}

12107
	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
12108
	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
12109
		goto nla_put_failure;
12110

12111
	if (mac && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac))
12112 12113
		goto nla_put_failure;

12114 12115
	cb[1] = nla_nest_start(msg, NL80211_ATTR_CQM);
	if (!cb[1])
12116
		goto nla_put_failure;
12117

12118
	cb[2] = rdev;
12119

12120 12121 12122 12123 12124 12125 12126 12127 12128 12129 12130 12131 12132 12133 12134
	return msg;
 nla_put_failure:
	nlmsg_free(msg);
	return NULL;
}

static void cfg80211_send_cqm(struct sk_buff *msg, gfp_t gfp)
{
	void **cb = (void **)msg->cb;
	struct cfg80211_registered_device *rdev = cb[2];

	nla_nest_end(msg, cb[1]);
	genlmsg_end(msg, cb[0]);

	memset(msg->cb, 0, sizeof(msg->cb));
12135

12136
	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
12137
				NL80211_MCGRP_MLME, gfp);
12138 12139 12140 12141 12142 12143 12144 12145 12146 12147
}

void cfg80211_cqm_rssi_notify(struct net_device *dev,
			      enum nl80211_cqm_rssi_threshold_event rssi_event,
			      gfp_t gfp)
{
	struct sk_buff *msg;

	trace_cfg80211_cqm_rssi_notify(dev, rssi_event);

12148 12149 12150 12151
	if (WARN_ON(rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW &&
		    rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH))
		return;

12152 12153 12154 12155 12156 12157 12158 12159 12160 12161
	msg = cfg80211_prepare_cqm(dev, NULL, gfp);
	if (!msg)
		return;

	if (nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT,
			rssi_event))
		goto nla_put_failure;

	cfg80211_send_cqm(msg, gfp);

12162 12163 12164 12165 12166
	return;

 nla_put_failure:
	nlmsg_free(msg);
}
12167
EXPORT_SYMBOL(cfg80211_cqm_rssi_notify);
12168

12169 12170 12171 12172 12173 12174 12175 12176 12177 12178 12179 12180 12181 12182 12183 12184 12185 12186 12187 12188 12189 12190 12191 12192 12193 12194 12195 12196 12197 12198 12199 12200 12201 12202 12203 12204 12205 12206 12207 12208 12209 12210 12211 12212 12213 12214 12215 12216 12217
void cfg80211_cqm_txe_notify(struct net_device *dev,
			     const u8 *peer, u32 num_packets,
			     u32 rate, u32 intvl, gfp_t gfp)
{
	struct sk_buff *msg;

	msg = cfg80211_prepare_cqm(dev, peer, gfp);
	if (!msg)
		return;

	if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_PKTS, num_packets))
		goto nla_put_failure;

	if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_RATE, rate))
		goto nla_put_failure;

	if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_INTVL, intvl))
		goto nla_put_failure;

	cfg80211_send_cqm(msg, gfp);
	return;

 nla_put_failure:
	nlmsg_free(msg);
}
EXPORT_SYMBOL(cfg80211_cqm_txe_notify);

void cfg80211_cqm_pktloss_notify(struct net_device *dev,
				 const u8 *peer, u32 num_packets, gfp_t gfp)
{
	struct sk_buff *msg;

	trace_cfg80211_cqm_pktloss_notify(dev, peer, num_packets);

	msg = cfg80211_prepare_cqm(dev, peer, gfp);
	if (!msg)
		return;

	if (nla_put_u32(msg, NL80211_ATTR_CQM_PKT_LOSS_EVENT, num_packets))
		goto nla_put_failure;

	cfg80211_send_cqm(msg, gfp);
	return;

 nla_put_failure:
	nlmsg_free(msg);
}
EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify);

12218 12219 12220 12221 12222 12223 12224 12225 12226 12227 12228 12229 12230 12231 12232 12233 12234 12235 12236
void cfg80211_cqm_beacon_loss_notify(struct net_device *dev, gfp_t gfp)
{
	struct sk_buff *msg;

	msg = cfg80211_prepare_cqm(dev, NULL, gfp);
	if (!msg)
		return;

	if (nla_put_flag(msg, NL80211_ATTR_CQM_BEACON_LOSS_EVENT))
		goto nla_put_failure;

	cfg80211_send_cqm(msg, gfp);
	return;

 nla_put_failure:
	nlmsg_free(msg);
}
EXPORT_SYMBOL(cfg80211_cqm_beacon_loss_notify);

12237 12238 12239
static void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev,
				     struct net_device *netdev, const u8 *bssid,
				     const u8 *replay_ctr, gfp_t gfp)
12240 12241 12242 12243 12244
{
	struct sk_buff *msg;
	struct nlattr *rekey_attr;
	void *hdr;

12245
	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
12246 12247 12248 12249 12250 12251 12252 12253 12254
	if (!msg)
		return;

	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_SET_REKEY_OFFLOAD);
	if (!hdr) {
		nlmsg_free(msg);
		return;
	}

12255 12256 12257 12258
	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
	    nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))
		goto nla_put_failure;
12259 12260 12261 12262 12263

	rekey_attr = nla_nest_start(msg, NL80211_ATTR_REKEY_DATA);
	if (!rekey_attr)
		goto nla_put_failure;

12264 12265 12266
	if (nla_put(msg, NL80211_REKEY_DATA_REPLAY_CTR,
		    NL80211_REPLAY_CTR_LEN, replay_ctr))
		goto nla_put_failure;
12267 12268 12269

	nla_nest_end(msg, rekey_attr);

12270
	genlmsg_end(msg, hdr);
12271

12272
	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
12273
				NL80211_MCGRP_MLME, gfp);
12274 12275 12276 12277 12278 12279 12280
	return;

 nla_put_failure:
	genlmsg_cancel(msg, hdr);
	nlmsg_free(msg);
}

12281 12282 12283 12284 12285
void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid,
			       const u8 *replay_ctr, gfp_t gfp)
{
	struct wireless_dev *wdev = dev->ieee80211_ptr;
	struct wiphy *wiphy = wdev->wiphy;
12286
	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
12287 12288 12289 12290 12291 12292 12293 12294 12295 12296

	trace_cfg80211_gtk_rekey_notify(dev, bssid);
	nl80211_gtk_rekey_notify(rdev, dev, bssid, replay_ctr, gfp);
}
EXPORT_SYMBOL(cfg80211_gtk_rekey_notify);

static void
nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev,
			       struct net_device *netdev, int index,
			       const u8 *bssid, bool preauth, gfp_t gfp)
12297 12298 12299 12300 12301
{
	struct sk_buff *msg;
	struct nlattr *attr;
	void *hdr;

12302
	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
12303 12304 12305 12306 12307 12308 12309 12310 12311
	if (!msg)
		return;

	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PMKSA_CANDIDATE);
	if (!hdr) {
		nlmsg_free(msg);
		return;
	}

12312 12313 12314
	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex))
		goto nla_put_failure;
12315 12316 12317 12318 12319

	attr = nla_nest_start(msg, NL80211_ATTR_PMKSA_CANDIDATE);
	if (!attr)
		goto nla_put_failure;

12320 12321 12322 12323 12324
	if (nla_put_u32(msg, NL80211_PMKSA_CANDIDATE_INDEX, index) ||
	    nla_put(msg, NL80211_PMKSA_CANDIDATE_BSSID, ETH_ALEN, bssid) ||
	    (preauth &&
	     nla_put_flag(msg, NL80211_PMKSA_CANDIDATE_PREAUTH)))
		goto nla_put_failure;
12325 12326 12327

	nla_nest_end(msg, attr);

12328
	genlmsg_end(msg, hdr);
12329

12330
	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
12331
				NL80211_MCGRP_MLME, gfp);
12332 12333 12334 12335 12336 12337 12338
	return;

 nla_put_failure:
	genlmsg_cancel(msg, hdr);
	nlmsg_free(msg);
}

12339 12340 12341 12342 12343
void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index,
				     const u8 *bssid, bool preauth, gfp_t gfp)
{
	struct wireless_dev *wdev = dev->ieee80211_ptr;
	struct wiphy *wiphy = wdev->wiphy;
12344
	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
12345 12346 12347 12348 12349 12350 12351 12352 12353

	trace_cfg80211_pmksa_candidate_notify(dev, index, bssid, preauth);
	nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp);
}
EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify);

static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
				     struct net_device *netdev,
				     struct cfg80211_chan_def *chandef,
12354 12355 12356
				     gfp_t gfp,
				     enum nl80211_commands notif,
				     u8 count)
12357 12358 12359 12360
{
	struct sk_buff *msg;
	void *hdr;

12361
	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
12362 12363 12364
	if (!msg)
		return;

12365
	hdr = nl80211hdr_put(msg, 0, 0, 0, notif);
12366 12367 12368 12369 12370
	if (!hdr) {
		nlmsg_free(msg);
		return;
	}

12371 12372 12373 12374
	if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex))
		goto nla_put_failure;

	if (nl80211_send_chandef(msg, chandef))
12375
		goto nla_put_failure;
12376

12377 12378 12379 12380
	if ((notif == NL80211_CMD_CH_SWITCH_STARTED_NOTIFY) &&
	    (nla_put_u32(msg, NL80211_ATTR_CH_SWITCH_COUNT, count)))
			goto nla_put_failure;

12381 12382
	genlmsg_end(msg, hdr);

12383
	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
12384
				NL80211_MCGRP_MLME, gfp);
12385 12386 12387 12388 12389 12390 12391
	return;

 nla_put_failure:
	genlmsg_cancel(msg, hdr);
	nlmsg_free(msg);
}

12392 12393
void cfg80211_ch_switch_notify(struct net_device *dev,
			       struct cfg80211_chan_def *chandef)
12394
{
12395 12396
	struct wireless_dev *wdev = dev->ieee80211_ptr;
	struct wiphy *wiphy = wdev->wiphy;
12397
	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
12398

12399
	ASSERT_WDEV_LOCK(wdev);
12400

12401
	trace_cfg80211_ch_switch_notify(dev, chandef);
12402

12403
	wdev->chandef = *chandef;
12404
	wdev->preset_chandef = *chandef;
12405 12406
	nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
				 NL80211_CMD_CH_SWITCH_NOTIFY, 0);
12407 12408 12409
}
EXPORT_SYMBOL(cfg80211_ch_switch_notify);

12410 12411 12412 12413 12414 12415 12416 12417 12418 12419 12420 12421 12422 12423 12424
void cfg80211_ch_switch_started_notify(struct net_device *dev,
				       struct cfg80211_chan_def *chandef,
				       u8 count)
{
	struct wireless_dev *wdev = dev->ieee80211_ptr;
	struct wiphy *wiphy = wdev->wiphy;
	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);

	trace_cfg80211_ch_switch_started_notify(dev, chandef);

	nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
				 NL80211_CMD_CH_SWITCH_STARTED_NOTIFY, count);
}
EXPORT_SYMBOL(cfg80211_ch_switch_started_notify);

12425 12426
void
nl80211_radar_notify(struct cfg80211_registered_device *rdev,
12427
		     const struct cfg80211_chan_def *chandef,
12428 12429 12430 12431 12432 12433 12434 12435 12436 12437 12438 12439 12440 12441 12442 12443 12444 12445 12446 12447 12448 12449 12450 12451 12452 12453 12454 12455 12456 12457 12458 12459 12460 12461
		     enum nl80211_radar_event event,
		     struct net_device *netdev, gfp_t gfp)
{
	struct sk_buff *msg;
	void *hdr;

	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
	if (!msg)
		return;

	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_RADAR_DETECT);
	if (!hdr) {
		nlmsg_free(msg);
		return;
	}

	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
		goto nla_put_failure;

	/* NOP and radar events don't need a netdev parameter */
	if (netdev) {
		struct wireless_dev *wdev = netdev->ieee80211_ptr;

		if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
		    nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
			goto nla_put_failure;
	}

	if (nla_put_u32(msg, NL80211_ATTR_RADAR_EVENT, event))
		goto nla_put_failure;

	if (nl80211_send_chandef(msg, chandef))
		goto nla_put_failure;

12462
	genlmsg_end(msg, hdr);
12463

12464
	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
12465
				NL80211_MCGRP_MLME, gfp);
12466 12467 12468 12469 12470 12471 12472
	return;

 nla_put_failure:
	genlmsg_cancel(msg, hdr);
	nlmsg_free(msg);
}

12473 12474 12475 12476
void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
			   u64 cookie, bool acked, gfp_t gfp)
{
	struct wireless_dev *wdev = dev->ieee80211_ptr;
12477
	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
12478 12479 12480
	struct sk_buff *msg;
	void *hdr;

12481 12482
	trace_cfg80211_probe_status(dev, addr, cookie, acked);

12483
	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
12484

12485 12486 12487 12488 12489 12490 12491 12492 12493
	if (!msg)
		return;

	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PROBE_CLIENT);
	if (!hdr) {
		nlmsg_free(msg);
		return;
	}

12494 12495 12496 12497 12498 12499
	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
	    nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
	    nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie) ||
	    (acked && nla_put_flag(msg, NL80211_ATTR_ACK)))
		goto nla_put_failure;
12500

12501
	genlmsg_end(msg, hdr);
12502

12503
	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
12504
				NL80211_MCGRP_MLME, gfp);
12505 12506 12507 12508 12509 12510 12511 12512
	return;

 nla_put_failure:
	genlmsg_cancel(msg, hdr);
	nlmsg_free(msg);
}
EXPORT_SYMBOL(cfg80211_probe_status);

12513 12514
void cfg80211_report_obss_beacon(struct wiphy *wiphy,
				 const u8 *frame, size_t len,
12515
				 int freq, int sig_dbm)
12516
{
12517
	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
12518 12519
	struct sk_buff *msg;
	void *hdr;
12520
	struct cfg80211_beacon_registration *reg;
12521

12522 12523
	trace_cfg80211_report_obss_beacon(wiphy, frame, len, freq, sig_dbm);

12524 12525 12526 12527 12528 12529 12530
	spin_lock_bh(&rdev->beacon_registrations_lock);
	list_for_each_entry(reg, &rdev->beacon_registrations, list) {
		msg = nlmsg_new(len + 100, GFP_ATOMIC);
		if (!msg) {
			spin_unlock_bh(&rdev->beacon_registrations_lock);
			return;
		}
12531

12532 12533 12534
		hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME);
		if (!hdr)
			goto nla_put_failure;
12535

12536 12537 12538 12539 12540 12541 12542
		if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
		    (freq &&
		     nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq)) ||
		    (sig_dbm &&
		     nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) ||
		    nla_put(msg, NL80211_ATTR_FRAME, len, frame))
			goto nla_put_failure;
12543

12544
		genlmsg_end(msg, hdr);
12545

12546 12547 12548
		genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, reg->nlportid);
	}
	spin_unlock_bh(&rdev->beacon_registrations_lock);
12549 12550 12551
	return;

 nla_put_failure:
12552 12553 12554
	spin_unlock_bh(&rdev->beacon_registrations_lock);
	if (hdr)
		genlmsg_cancel(msg, hdr);
12555 12556 12557 12558
	nlmsg_free(msg);
}
EXPORT_SYMBOL(cfg80211_report_obss_beacon);

12559
#ifdef CONFIG_PM
12560 12561 12562 12563 12564 12565 12566 12567 12568 12569 12570 12571 12572 12573 12574 12575 12576 12577 12578 12579 12580 12581 12582 12583 12584 12585 12586 12587 12588 12589 12590 12591 12592 12593 12594 12595 12596 12597 12598 12599 12600
static int cfg80211_net_detect_results(struct sk_buff *msg,
				       struct cfg80211_wowlan_wakeup *wakeup)
{
	struct cfg80211_wowlan_nd_info *nd = wakeup->net_detect;
	struct nlattr *nl_results, *nl_match, *nl_freqs;
	int i, j;

	nl_results = nla_nest_start(
		msg, NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS);
	if (!nl_results)
		return -EMSGSIZE;

	for (i = 0; i < nd->n_matches; i++) {
		struct cfg80211_wowlan_nd_match *match = nd->matches[i];

		nl_match = nla_nest_start(msg, i);
		if (!nl_match)
			break;

		/* The SSID attribute is optional in nl80211, but for
		 * simplicity reasons it's always present in the
		 * cfg80211 structure.  If a driver can't pass the
		 * SSID, that needs to be changed.  A zero length SSID
		 * is still a valid SSID (wildcard), so it cannot be
		 * used for this purpose.
		 */
		if (nla_put(msg, NL80211_ATTR_SSID, match->ssid.ssid_len,
			    match->ssid.ssid)) {
			nla_nest_cancel(msg, nl_match);
			goto out;
		}

		if (match->n_channels) {
			nl_freqs = nla_nest_start(
				msg, NL80211_ATTR_SCAN_FREQUENCIES);
			if (!nl_freqs) {
				nla_nest_cancel(msg, nl_match);
				goto out;
			}

			for (j = 0; j < match->n_channels; j++) {
12601
				if (nla_put_u32(msg, j, match->channels[j])) {
12602 12603 12604 12605 12606 12607 12608 12609 12610 12611 12612 12613 12614 12615 12616 12617 12618
					nla_nest_cancel(msg, nl_freqs);
					nla_nest_cancel(msg, nl_match);
					goto out;
				}
			}

			nla_nest_end(msg, nl_freqs);
		}

		nla_nest_end(msg, nl_match);
	}

out:
	nla_nest_end(msg, nl_results);
	return 0;
}

12619 12620 12621 12622
void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
				   struct cfg80211_wowlan_wakeup *wakeup,
				   gfp_t gfp)
{
12623
	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
12624 12625
	struct sk_buff *msg;
	void *hdr;
12626
	int size = 200;
12627 12628 12629 12630 12631 12632 12633 12634 12635 12636 12637 12638 12639 12640 12641 12642 12643 12644 12645 12646 12647 12648 12649 12650 12651 12652

	trace_cfg80211_report_wowlan_wakeup(wdev->wiphy, wdev, wakeup);

	if (wakeup)
		size += wakeup->packet_present_len;

	msg = nlmsg_new(size, gfp);
	if (!msg)
		return;

	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_SET_WOWLAN);
	if (!hdr)
		goto free_msg;

	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
	    nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
		goto free_msg;

	if (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
					wdev->netdev->ifindex))
		goto free_msg;

	if (wakeup) {
		struct nlattr *reasons;

		reasons = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS);
12653 12654
		if (!reasons)
			goto free_msg;
12655 12656 12657 12658 12659 12660 12661 12662 12663 12664 12665 12666 12667 12668 12669 12670 12671 12672 12673 12674 12675 12676 12677 12678 12679

		if (wakeup->disconnect &&
		    nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT))
			goto free_msg;
		if (wakeup->magic_pkt &&
		    nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT))
			goto free_msg;
		if (wakeup->gtk_rekey_failure &&
		    nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE))
			goto free_msg;
		if (wakeup->eap_identity_req &&
		    nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST))
			goto free_msg;
		if (wakeup->four_way_handshake &&
		    nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE))
			goto free_msg;
		if (wakeup->rfkill_release &&
		    nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))
			goto free_msg;

		if (wakeup->pattern_idx >= 0 &&
		    nla_put_u32(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN,
				wakeup->pattern_idx))
			goto free_msg;

12680 12681 12682
		if (wakeup->tcp_match &&
		    nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH))
			goto free_msg;
12683

12684 12685 12686
		if (wakeup->tcp_connlost &&
		    nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST))
			goto free_msg;
12687

12688 12689 12690 12691
		if (wakeup->tcp_nomoretokens &&
		    nla_put_flag(msg,
				 NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS))
			goto free_msg;
12692

12693 12694 12695 12696 12697 12698 12699 12700 12701 12702 12703 12704 12705 12706 12707 12708 12709 12710 12711 12712
		if (wakeup->packet) {
			u32 pkt_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211;
			u32 len_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN;

			if (!wakeup->packet_80211) {
				pkt_attr =
					NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023;
				len_attr =
					NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN;
			}

			if (wakeup->packet_len &&
			    nla_put_u32(msg, len_attr, wakeup->packet_len))
				goto free_msg;

			if (nla_put(msg, pkt_attr, wakeup->packet_present_len,
				    wakeup->packet))
				goto free_msg;
		}

12713 12714 12715 12716
		if (wakeup->net_detect &&
		    cfg80211_net_detect_results(msg, wakeup))
				goto free_msg;

12717 12718 12719
		nla_nest_end(msg, reasons);
	}

12720
	genlmsg_end(msg, hdr);
12721

12722
	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
12723
				NL80211_MCGRP_MLME, gfp);
12724 12725 12726 12727 12728 12729 12730 12731
	return;

 free_msg:
	nlmsg_free(msg);
}
EXPORT_SYMBOL(cfg80211_report_wowlan_wakeup);
#endif

12732 12733 12734 12735 12736
void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer,
				enum nl80211_tdls_operation oper,
				u16 reason_code, gfp_t gfp)
{
	struct wireless_dev *wdev = dev->ieee80211_ptr;
12737
	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
12738 12739 12740 12741 12742 12743 12744 12745 12746 12747 12748 12749 12750 12751 12752 12753 12754 12755 12756 12757 12758 12759 12760 12761
	struct sk_buff *msg;
	void *hdr;

	trace_cfg80211_tdls_oper_request(wdev->wiphy, dev, peer, oper,
					 reason_code);

	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
	if (!msg)
		return;

	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_TDLS_OPER);
	if (!hdr) {
		nlmsg_free(msg);
		return;
	}

	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
	    nla_put_u8(msg, NL80211_ATTR_TDLS_OPERATION, oper) ||
	    nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer) ||
	    (reason_code > 0 &&
	     nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code)))
		goto nla_put_failure;

12762
	genlmsg_end(msg, hdr);
12763

12764
	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
12765
				NL80211_MCGRP_MLME, gfp);
12766 12767 12768 12769 12770 12771 12772 12773
	return;

 nla_put_failure:
	genlmsg_cancel(msg, hdr);
	nlmsg_free(msg);
}
EXPORT_SYMBOL(cfg80211_tdls_oper_request);

12774 12775 12776 12777 12778 12779 12780
static int nl80211_netlink_notify(struct notifier_block * nb,
				  unsigned long state,
				  void *_notify)
{
	struct netlink_notify *notify = _notify;
	struct cfg80211_registered_device *rdev;
	struct wireless_dev *wdev;
12781
	struct cfg80211_beacon_registration *reg, *tmp;
12782 12783 12784 12785 12786 12787

	if (state != NETLINK_URELEASE)
		return NOTIFY_DONE;

	rcu_read_lock();

12788
	list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) {
12789
		bool schedule_destroy_work = false;
12790 12791 12792 12793 12794 12795 12796
		bool schedule_scan_stop = false;
		struct cfg80211_sched_scan_request *sched_scan_req =
			rcu_dereference(rdev->sched_scan_req);

		if (sched_scan_req && notify->portid &&
		    sched_scan_req->owner_nlportid == notify->portid)
			schedule_scan_stop = true;
12797 12798

		list_for_each_entry_rcu(wdev, &rdev->wdev_list, list) {
12799
			cfg80211_mlme_unregister_socket(wdev, notify->portid);
12800

12801 12802 12803 12804
			if (wdev->owner_nlportid == notify->portid)
				schedule_destroy_work = true;
		}

12805 12806 12807 12808 12809 12810 12811 12812 12813 12814
		spin_lock_bh(&rdev->beacon_registrations_lock);
		list_for_each_entry_safe(reg, tmp, &rdev->beacon_registrations,
					 list) {
			if (reg->nlportid == notify->portid) {
				list_del(&reg->list);
				kfree(reg);
				break;
			}
		}
		spin_unlock_bh(&rdev->beacon_registrations_lock);
12815 12816 12817 12818 12819 12820 12821 12822 12823 12824 12825 12826

		if (schedule_destroy_work) {
			struct cfg80211_iface_destroy *destroy;

			destroy = kzalloc(sizeof(*destroy), GFP_ATOMIC);
			if (destroy) {
				destroy->nlportid = notify->portid;
				spin_lock(&rdev->destroy_list_lock);
				list_add(&destroy->list, &rdev->destroy_list);
				spin_unlock(&rdev->destroy_list_lock);
				schedule_work(&rdev->destroy_work);
			}
12827 12828 12829 12830 12831 12832
		} else if (schedule_scan_stop) {
			sched_scan_req->owner_nlportid = 0;

			if (rdev->ops->sched_scan_stop &&
			    rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN)
				schedule_work(&rdev->sched_scan_stop_wk);
12833
		}
12834
	}
12835 12836 12837

	rcu_read_unlock();

12838 12839 12840 12841 12842
	/*
	 * It is possible that the user space process that is controlling the
	 * indoor setting disappeared, so notify the regulatory core.
	 */
	regulatory_netlink_notify(notify->portid);
12843
	return NOTIFY_OK;
12844 12845 12846 12847 12848 12849
}

static struct notifier_block nl80211_netlink_notifier = {
	.notifier_call = nl80211_netlink_notify,
};

12850 12851 12852 12853
void cfg80211_ft_event(struct net_device *netdev,
		       struct cfg80211_ft_event_params *ft_event)
{
	struct wiphy *wiphy = netdev->ieee80211_ptr->wiphy;
12854
	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
12855 12856 12857 12858 12859 12860 12861 12862 12863 12864 12865 12866 12867
	struct sk_buff *msg;
	void *hdr;

	trace_cfg80211_ft_event(wiphy, netdev, ft_event);

	if (!ft_event->target_ap)
		return;

	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
	if (!msg)
		return;

	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FT_EVENT);
12868 12869
	if (!hdr)
		goto out;
12870

12871 12872 12873 12874
	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
	    nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ft_event->target_ap))
		goto out;
12875

12876 12877 12878 12879 12880 12881 12882
	if (ft_event->ies &&
	    nla_put(msg, NL80211_ATTR_IE, ft_event->ies_len, ft_event->ies))
		goto out;
	if (ft_event->ric_ies &&
	    nla_put(msg, NL80211_ATTR_IE_RIC, ft_event->ric_ies_len,
		    ft_event->ric_ies))
		goto out;
12883

12884
	genlmsg_end(msg, hdr);
12885

12886
	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
12887
				NL80211_MCGRP_MLME, GFP_KERNEL);
12888 12889 12890
	return;
 out:
	nlmsg_free(msg);
12891 12892 12893
}
EXPORT_SYMBOL(cfg80211_ft_event);

12894 12895 12896 12897 12898 12899 12900
void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp)
{
	struct cfg80211_registered_device *rdev;
	struct sk_buff *msg;
	void *hdr;
	u32 nlportid;

12901
	rdev = wiphy_to_rdev(wdev->wiphy);
12902 12903 12904 12905 12906 12907 12908 12909 12910 12911 12912 12913 12914 12915 12916 12917 12918 12919 12920 12921 12922 12923 12924 12925 12926 12927 12928 12929 12930 12931 12932
	if (!rdev->crit_proto_nlportid)
		return;

	nlportid = rdev->crit_proto_nlportid;
	rdev->crit_proto_nlportid = 0;

	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
	if (!msg)
		return;

	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CRIT_PROTOCOL_STOP);
	if (!hdr)
		goto nla_put_failure;

	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
	    nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
		goto nla_put_failure;

	genlmsg_end(msg, hdr);

	genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
	return;

 nla_put_failure:
	if (hdr)
		genlmsg_cancel(msg, hdr);
	nlmsg_free(msg);

}
EXPORT_SYMBOL(cfg80211_crit_proto_stopped);

12933 12934 12935
void nl80211_send_ap_stopped(struct wireless_dev *wdev)
{
	struct wiphy *wiphy = wdev->wiphy;
12936
	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
12937 12938 12939 12940 12941 12942 12943 12944 12945 12946 12947 12948 12949 12950 12951 12952 12953 12954 12955 12956 12957 12958 12959 12960 12961
	struct sk_buff *msg;
	void *hdr;

	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
	if (!msg)
		return;

	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STOP_AP);
	if (!hdr)
		goto out;

	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex) ||
	    nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
		goto out;

	genlmsg_end(msg, hdr);

	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(wiphy), msg, 0,
				NL80211_MCGRP_MLME, GFP_KERNEL);
	return;
 out:
	nlmsg_free(msg);
}

12962 12963 12964 12965
/* initialisation/exit functions */

int nl80211_init(void)
{
12966
	int err;
12967

12968 12969
	err = genl_register_family_with_ops_groups(&nl80211_fam, nl80211_ops,
						   nl80211_mcgrps);
12970 12971 12972
	if (err)
		return err;

12973 12974 12975 12976
	err = netlink_register_notifier(&nl80211_netlink_notifier);
	if (err)
		goto err_out;

12977 12978 12979 12980 12981 12982 12983 12984
	return 0;
 err_out:
	genl_unregister_family(&nl80211_fam);
	return err;
}

void nl80211_exit(void)
{
12985
	netlink_unregister_notifier(&nl80211_netlink_notifier);
12986 12987
	genl_unregister_family(&nl80211_fam);
}