diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /net/wireless/nl80211.c | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r-- | net/wireless/nl80211.c | 4280 |
1 files changed, 1116 insertions, 3164 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index f45706adaf3..fb18bb4dea7 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -22,12 +22,6 @@ | |||
22 | #include "core.h" | 22 | #include "core.h" |
23 | #include "nl80211.h" | 23 | #include "nl80211.h" |
24 | #include "reg.h" | 24 | #include "reg.h" |
25 | #include "rdev-ops.h" | ||
26 | |||
27 | static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, | ||
28 | struct genl_info *info, | ||
29 | struct cfg80211_crypto_settings *settings, | ||
30 | int cipher_limit); | ||
31 | 25 | ||
32 | static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, | 26 | static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, |
33 | struct genl_info *info); | 27 | struct genl_info *info); |
@@ -46,175 +40,29 @@ static struct genl_family nl80211_fam = { | |||
46 | .post_doit = nl80211_post_doit, | 40 | .post_doit = nl80211_post_doit, |
47 | }; | 41 | }; |
48 | 42 | ||
49 | /* returns ERR_PTR values */ | 43 | /* internal helper: get rdev and dev */ |
50 | static struct wireless_dev * | 44 | static int get_rdev_dev_by_info_ifindex(struct genl_info *info, |
51 | __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs) | 45 | struct cfg80211_registered_device **rdev, |
52 | { | 46 | struct net_device **dev) |
53 | struct cfg80211_registered_device *rdev; | ||
54 | struct wireless_dev *result = NULL; | ||
55 | bool have_ifidx = attrs[NL80211_ATTR_IFINDEX]; | ||
56 | bool have_wdev_id = attrs[NL80211_ATTR_WDEV]; | ||
57 | u64 wdev_id; | ||
58 | int wiphy_idx = -1; | ||
59 | int ifidx = -1; | ||
60 | |||
61 | assert_cfg80211_lock(); | ||
62 | |||
63 | if (!have_ifidx && !have_wdev_id) | ||
64 | return ERR_PTR(-EINVAL); | ||
65 | |||
66 | if (have_ifidx) | ||
67 | ifidx = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]); | ||
68 | if (have_wdev_id) { | ||
69 | wdev_id = nla_get_u64(attrs[NL80211_ATTR_WDEV]); | ||
70 | wiphy_idx = wdev_id >> 32; | ||
71 | } | ||
72 | |||
73 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { | ||
74 | struct wireless_dev *wdev; | ||
75 | |||
76 | if (wiphy_net(&rdev->wiphy) != netns) | ||
77 | continue; | ||
78 | |||
79 | if (have_wdev_id && rdev->wiphy_idx != wiphy_idx) | ||
80 | continue; | ||
81 | |||
82 | mutex_lock(&rdev->devlist_mtx); | ||
83 | list_for_each_entry(wdev, &rdev->wdev_list, list) { | ||
84 | if (have_ifidx && wdev->netdev && | ||
85 | wdev->netdev->ifindex == ifidx) { | ||
86 | result = wdev; | ||
87 | break; | ||
88 | } | ||
89 | if (have_wdev_id && wdev->identifier == (u32)wdev_id) { | ||
90 | result = wdev; | ||
91 | break; | ||
92 | } | ||
93 | } | ||
94 | mutex_unlock(&rdev->devlist_mtx); | ||
95 | |||
96 | if (result) | ||
97 | break; | ||
98 | } | ||
99 | |||
100 | if (result) | ||
101 | return result; | ||
102 | return ERR_PTR(-ENODEV); | ||
103 | } | ||
104 | |||
105 | static struct cfg80211_registered_device * | ||
106 | __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs) | ||
107 | { | 47 | { |
108 | struct cfg80211_registered_device *rdev = NULL, *tmp; | 48 | struct nlattr **attrs = info->attrs; |
109 | struct net_device *netdev; | 49 | int ifindex; |
110 | |||
111 | assert_cfg80211_lock(); | ||
112 | |||
113 | if (!attrs[NL80211_ATTR_WIPHY] && | ||
114 | !attrs[NL80211_ATTR_IFINDEX] && | ||
115 | !attrs[NL80211_ATTR_WDEV]) | ||
116 | return ERR_PTR(-EINVAL); | ||
117 | |||
118 | if (attrs[NL80211_ATTR_WIPHY]) | ||
119 | rdev = cfg80211_rdev_by_wiphy_idx( | ||
120 | nla_get_u32(attrs[NL80211_ATTR_WIPHY])); | ||
121 | |||
122 | if (attrs[NL80211_ATTR_WDEV]) { | ||
123 | u64 wdev_id = nla_get_u64(attrs[NL80211_ATTR_WDEV]); | ||
124 | struct wireless_dev *wdev; | ||
125 | bool found = false; | ||
126 | |||
127 | tmp = cfg80211_rdev_by_wiphy_idx(wdev_id >> 32); | ||
128 | if (tmp) { | ||
129 | /* make sure wdev exists */ | ||
130 | mutex_lock(&tmp->devlist_mtx); | ||
131 | list_for_each_entry(wdev, &tmp->wdev_list, list) { | ||
132 | if (wdev->identifier != (u32)wdev_id) | ||
133 | continue; | ||
134 | found = true; | ||
135 | break; | ||
136 | } | ||
137 | mutex_unlock(&tmp->devlist_mtx); | ||
138 | |||
139 | if (!found) | ||
140 | tmp = NULL; | ||
141 | |||
142 | if (rdev && tmp != rdev) | ||
143 | return ERR_PTR(-EINVAL); | ||
144 | rdev = tmp; | ||
145 | } | ||
146 | } | ||
147 | 50 | ||
148 | if (attrs[NL80211_ATTR_IFINDEX]) { | 51 | if (!attrs[NL80211_ATTR_IFINDEX]) |
149 | int ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]); | 52 | return -EINVAL; |
150 | netdev = dev_get_by_index(netns, ifindex); | ||
151 | if (netdev) { | ||
152 | if (netdev->ieee80211_ptr) | ||
153 | tmp = wiphy_to_dev( | ||
154 | netdev->ieee80211_ptr->wiphy); | ||
155 | else | ||
156 | tmp = NULL; | ||
157 | |||
158 | dev_put(netdev); | ||
159 | |||
160 | /* not wireless device -- return error */ | ||
161 | if (!tmp) | ||
162 | return ERR_PTR(-EINVAL); | ||
163 | 53 | ||
164 | /* mismatch -- return error */ | 54 | ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]); |
165 | if (rdev && tmp != rdev) | 55 | *dev = dev_get_by_index(genl_info_net(info), ifindex); |
166 | return ERR_PTR(-EINVAL); | 56 | if (!*dev) |
57 | return -ENODEV; | ||
167 | 58 | ||
168 | rdev = tmp; | 59 | *rdev = cfg80211_get_dev_from_ifindex(genl_info_net(info), ifindex); |
169 | } | 60 | if (IS_ERR(*rdev)) { |
61 | dev_put(*dev); | ||
62 | return PTR_ERR(*rdev); | ||
170 | } | 63 | } |
171 | 64 | ||
172 | if (!rdev) | 65 | return 0; |
173 | return ERR_PTR(-ENODEV); | ||
174 | |||
175 | if (netns != wiphy_net(&rdev->wiphy)) | ||
176 | return ERR_PTR(-ENODEV); | ||
177 | |||
178 | return rdev; | ||
179 | } | ||
180 | |||
181 | /* | ||
182 | * This function returns a pointer to the driver | ||
183 | * that the genl_info item that is passed refers to. | ||
184 | * If successful, it returns non-NULL and also locks | ||
185 | * the driver's mutex! | ||
186 | * | ||
187 | * This means that you need to call cfg80211_unlock_rdev() | ||
188 | * before being allowed to acquire &cfg80211_mutex! | ||
189 | * | ||
190 | * This is necessary because we need to lock the global | ||
191 | * mutex to get an item off the list safely, and then | ||
192 | * we lock the rdev mutex so it doesn't go away under us. | ||
193 | * | ||
194 | * We don't want to keep cfg80211_mutex locked | ||
195 | * for all the time in order to allow requests on | ||
196 | * other interfaces to go through at the same time. | ||
197 | * | ||
198 | * The result of this can be a PTR_ERR and hence must | ||
199 | * be checked with IS_ERR() for errors. | ||
200 | */ | ||
201 | static struct cfg80211_registered_device * | ||
202 | cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info) | ||
203 | { | ||
204 | struct cfg80211_registered_device *rdev; | ||
205 | |||
206 | mutex_lock(&cfg80211_mutex); | ||
207 | rdev = __cfg80211_rdev_from_attrs(netns, info->attrs); | ||
208 | |||
209 | /* if it is not an error we grab the lock on | ||
210 | * it to assure it won't be going away while | ||
211 | * we operate on it */ | ||
212 | if (!IS_ERR(rdev)) | ||
213 | mutex_lock(&rdev->mtx); | ||
214 | |||
215 | mutex_unlock(&cfg80211_mutex); | ||
216 | |||
217 | return rdev; | ||
218 | } | 66 | } |
219 | 67 | ||
220 | /* policy for the attributes */ | 68 | /* policy for the attributes */ |
@@ -223,13 +71,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
223 | [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING, | 71 | [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING, |
224 | .len = 20-1 }, | 72 | .len = 20-1 }, |
225 | [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED }, | 73 | [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED }, |
226 | |||
227 | [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 }, | 74 | [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 }, |
228 | [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 }, | 75 | [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 }, |
229 | [NL80211_ATTR_CHANNEL_WIDTH] = { .type = NLA_U32 }, | ||
230 | [NL80211_ATTR_CENTER_FREQ1] = { .type = NLA_U32 }, | ||
231 | [NL80211_ATTR_CENTER_FREQ2] = { .type = NLA_U32 }, | ||
232 | |||
233 | [NL80211_ATTR_WIPHY_RETRY_SHORT] = { .type = NLA_U8 }, | 76 | [NL80211_ATTR_WIPHY_RETRY_SHORT] = { .type = NLA_U8 }, |
234 | [NL80211_ATTR_WIPHY_RETRY_LONG] = { .type = NLA_U8 }, | 77 | [NL80211_ATTR_WIPHY_RETRY_LONG] = { .type = NLA_U8 }, |
235 | [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 }, | 78 | [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 }, |
@@ -249,7 +92,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
249 | [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 }, | 92 | [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 }, |
250 | [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 }, | 93 | [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 }, |
251 | [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG }, | 94 | [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG }, |
252 | [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 }, | 95 | [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 }, |
253 | [NL80211_ATTR_KEY_TYPE] = { .type = NLA_U32 }, | 96 | [NL80211_ATTR_KEY_TYPE] = { .type = NLA_U32 }, |
254 | 97 | ||
255 | [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 }, | 98 | [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 }, |
@@ -267,7 +110,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
267 | [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 }, | 110 | [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 }, |
268 | [NL80211_ATTR_MNTR_FLAGS] = { /* NLA_NESTED can't be empty */ }, | 111 | [NL80211_ATTR_MNTR_FLAGS] = { /* NLA_NESTED can't be empty */ }, |
269 | [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY, | 112 | [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY, |
270 | .len = IEEE80211_MAX_MESH_ID_LEN }, | 113 | .len = IEEE80211_MAX_MESH_ID_LEN }, |
271 | [NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_U32 }, | 114 | [NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_U32 }, |
272 | 115 | ||
273 | [NL80211_ATTR_REG_ALPHA2] = { .type = NLA_STRING, .len = 2 }, | 116 | [NL80211_ATTR_REG_ALPHA2] = { .type = NLA_STRING, .len = 2 }, |
@@ -334,37 +177,6 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
334 | [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 }, | 177 | [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 }, |
335 | [NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED }, | 178 | [NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED }, |
336 | [NL80211_ATTR_SCAN_SUPP_RATES] = { .type = NLA_NESTED }, | 179 | [NL80211_ATTR_SCAN_SUPP_RATES] = { .type = NLA_NESTED }, |
337 | [NL80211_ATTR_HIDDEN_SSID] = { .type = NLA_U32 }, | ||
338 | [NL80211_ATTR_IE_PROBE_RESP] = { .type = NLA_BINARY, | ||
339 | .len = IEEE80211_MAX_DATA_LEN }, | ||
340 | [NL80211_ATTR_IE_ASSOC_RESP] = { .type = NLA_BINARY, | ||
341 | .len = IEEE80211_MAX_DATA_LEN }, | ||
342 | [NL80211_ATTR_ROAM_SUPPORT] = { .type = NLA_FLAG }, | ||
343 | [NL80211_ATTR_SCHED_SCAN_MATCH] = { .type = NLA_NESTED }, | ||
344 | [NL80211_ATTR_TX_NO_CCK_RATE] = { .type = NLA_FLAG }, | ||
345 | [NL80211_ATTR_TDLS_ACTION] = { .type = NLA_U8 }, | ||
346 | [NL80211_ATTR_TDLS_DIALOG_TOKEN] = { .type = NLA_U8 }, | ||
347 | [NL80211_ATTR_TDLS_OPERATION] = { .type = NLA_U8 }, | ||
348 | [NL80211_ATTR_TDLS_SUPPORT] = { .type = NLA_FLAG }, | ||
349 | [NL80211_ATTR_TDLS_EXTERNAL_SETUP] = { .type = NLA_FLAG }, | ||
350 | [NL80211_ATTR_DONT_WAIT_FOR_ACK] = { .type = NLA_FLAG }, | ||
351 | [NL80211_ATTR_PROBE_RESP] = { .type = NLA_BINARY, | ||
352 | .len = IEEE80211_MAX_DATA_LEN }, | ||
353 | [NL80211_ATTR_DFS_REGION] = { .type = NLA_U8 }, | ||
354 | [NL80211_ATTR_DISABLE_HT] = { .type = NLA_FLAG }, | ||
355 | [NL80211_ATTR_HT_CAPABILITY_MASK] = { | ||
356 | .len = NL80211_HT_CAPABILITY_LEN | ||
357 | }, | ||
358 | [NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 }, | ||
359 | [NL80211_ATTR_INACTIVITY_TIMEOUT] = { .type = NLA_U16 }, | ||
360 | [NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 }, | ||
361 | [NL80211_ATTR_WDEV] = { .type = NLA_U64 }, | ||
362 | [NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 }, | ||
363 | [NL80211_ATTR_SAE_DATA] = { .type = NLA_BINARY, }, | ||
364 | [NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN }, | ||
365 | [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 }, | ||
366 | [NL80211_ATTR_P2P_CTWINDOW] = { .type = NLA_U8 }, | ||
367 | [NL80211_ATTR_P2P_OPPPS] = { .type = NLA_U8 }, | ||
368 | }; | 180 | }; |
369 | 181 | ||
370 | /* policy for the key attributes */ | 182 | /* policy for the key attributes */ |
@@ -372,7 +184,7 @@ static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = { | |||
372 | [NL80211_KEY_DATA] = { .type = NLA_BINARY, .len = WLAN_MAX_KEY_LEN }, | 184 | [NL80211_KEY_DATA] = { .type = NLA_BINARY, .len = WLAN_MAX_KEY_LEN }, |
373 | [NL80211_KEY_IDX] = { .type = NLA_U8 }, | 185 | [NL80211_KEY_IDX] = { .type = NLA_U8 }, |
374 | [NL80211_KEY_CIPHER] = { .type = NLA_U32 }, | 186 | [NL80211_KEY_CIPHER] = { .type = NLA_U32 }, |
375 | [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 }, | 187 | [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 }, |
376 | [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG }, | 188 | [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG }, |
377 | [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG }, | 189 | [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG }, |
378 | [NL80211_KEY_TYPE] = { .type = NLA_U32 }, | 190 | [NL80211_KEY_TYPE] = { .type = NLA_U32 }, |
@@ -407,13 +219,6 @@ nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = { | |||
407 | [NL80211_REKEY_DATA_REPLAY_CTR] = { .len = NL80211_REPLAY_CTR_LEN }, | 219 | [NL80211_REKEY_DATA_REPLAY_CTR] = { .len = NL80211_REPLAY_CTR_LEN }, |
408 | }; | 220 | }; |
409 | 221 | ||
410 | static const struct nla_policy | ||
411 | nl80211_match_policy[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1] = { | ||
412 | [NL80211_SCHED_SCAN_MATCH_ATTR_SSID] = { .type = NLA_BINARY, | ||
413 | .len = IEEE80211_MAX_SSID_LEN }, | ||
414 | [NL80211_SCHED_SCAN_MATCH_ATTR_RSSI] = { .type = NLA_U32 }, | ||
415 | }; | ||
416 | |||
417 | /* ifidx get helper */ | 222 | /* ifidx get helper */ |
418 | static int nl80211_get_ifidx(struct netlink_callback *cb) | 223 | static int nl80211_get_ifidx(struct netlink_callback *cb) |
419 | { | 224 | { |
@@ -506,36 +311,30 @@ static bool is_valid_ie_attr(const struct nlattr *attr) | |||
506 | } | 311 | } |
507 | 312 | ||
508 | /* message building helper */ | 313 | /* message building helper */ |
509 | static inline void *nl80211hdr_put(struct sk_buff *skb, u32 portid, u32 seq, | 314 | static inline void *nl80211hdr_put(struct sk_buff *skb, u32 pid, u32 seq, |
510 | int flags, u8 cmd) | 315 | int flags, u8 cmd) |
511 | { | 316 | { |
512 | /* since there is no private header just add the generic one */ | 317 | /* since there is no private header just add the generic one */ |
513 | return genlmsg_put(skb, portid, seq, &nl80211_fam, flags, cmd); | 318 | return genlmsg_put(skb, pid, seq, &nl80211_fam, flags, cmd); |
514 | } | 319 | } |
515 | 320 | ||
516 | static int nl80211_msg_put_channel(struct sk_buff *msg, | 321 | static int nl80211_msg_put_channel(struct sk_buff *msg, |
517 | struct ieee80211_channel *chan) | 322 | struct ieee80211_channel *chan) |
518 | { | 323 | { |
519 | if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_FREQ, | 324 | NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_FREQ, |
520 | chan->center_freq)) | 325 | chan->center_freq); |
521 | goto nla_put_failure; | ||
522 | 326 | ||
523 | if ((chan->flags & IEEE80211_CHAN_DISABLED) && | 327 | if (chan->flags & IEEE80211_CHAN_DISABLED) |
524 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_DISABLED)) | 328 | NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_DISABLED); |
525 | goto nla_put_failure; | 329 | if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) |
526 | if ((chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) && | 330 | NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN); |
527 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN)) | 331 | if (chan->flags & IEEE80211_CHAN_NO_IBSS) |
528 | goto nla_put_failure; | 332 | NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_NO_IBSS); |
529 | if ((chan->flags & IEEE80211_CHAN_NO_IBSS) && | 333 | if (chan->flags & IEEE80211_CHAN_RADAR) |
530 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IBSS)) | 334 | NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR); |
531 | goto nla_put_failure; | ||
532 | if ((chan->flags & IEEE80211_CHAN_RADAR) && | ||
533 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR)) | ||
534 | goto nla_put_failure; | ||
535 | 335 | ||
536 | if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER, | 336 | NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER, |
537 | DBM_TO_MBM(chan->max_power))) | 337 | DBM_TO_MBM(chan->max_power)); |
538 | goto nla_put_failure; | ||
539 | 338 | ||
540 | return 0; | 339 | return 0; |
541 | 340 | ||
@@ -595,9 +394,10 @@ static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k) | |||
595 | 394 | ||
596 | if (tb[NL80211_KEY_DEFAULT_TYPES]) { | 395 | if (tb[NL80211_KEY_DEFAULT_TYPES]) { |
597 | struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES]; | 396 | struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES]; |
598 | err = nla_parse_nested(kdt, NUM_NL80211_KEY_DEFAULT_TYPES - 1, | 397 | int err = nla_parse_nested(kdt, |
599 | tb[NL80211_KEY_DEFAULT_TYPES], | 398 | NUM_NL80211_KEY_DEFAULT_TYPES - 1, |
600 | nl80211_key_default_policy); | 399 | tb[NL80211_KEY_DEFAULT_TYPES], |
400 | nl80211_key_default_policy); | ||
601 | if (err) | 401 | if (err) |
602 | return err; | 402 | return err; |
603 | 403 | ||
@@ -700,7 +500,7 @@ static int nl80211_parse_key(struct genl_info *info, struct key_parse *k) | |||
700 | 500 | ||
701 | static struct cfg80211_cached_keys * | 501 | static struct cfg80211_cached_keys * |
702 | nl80211_parse_connkeys(struct cfg80211_registered_device *rdev, | 502 | nl80211_parse_connkeys(struct cfg80211_registered_device *rdev, |
703 | struct nlattr *keys, bool *no_ht) | 503 | struct nlattr *keys) |
704 | { | 504 | { |
705 | struct key_parse parse; | 505 | struct key_parse parse; |
706 | struct nlattr *key; | 506 | struct nlattr *key; |
@@ -743,12 +543,6 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev, | |||
743 | result->params[parse.idx].key_len = parse.p.key_len; | 543 | result->params[parse.idx].key_len = parse.p.key_len; |
744 | result->params[parse.idx].key = result->data[parse.idx]; | 544 | result->params[parse.idx].key = result->data[parse.idx]; |
745 | memcpy(result->data[parse.idx], parse.p.key, parse.p.key_len); | 545 | memcpy(result->data[parse.idx], parse.p.key, parse.p.key_len); |
746 | |||
747 | if (parse.p.cipher == WLAN_CIPHER_SUITE_WEP40 || | ||
748 | parse.p.cipher == WLAN_CIPHER_SUITE_WEP104) { | ||
749 | if (no_ht) | ||
750 | *no_ht = true; | ||
751 | } | ||
752 | } | 546 | } |
753 | 547 | ||
754 | return result; | 548 | return result; |
@@ -793,8 +587,8 @@ static int nl80211_put_iftypes(struct sk_buff *msg, u32 attr, u16 ifmodes) | |||
793 | 587 | ||
794 | i = 0; | 588 | i = 0; |
795 | while (ifmodes) { | 589 | while (ifmodes) { |
796 | if ((ifmodes & 1) && nla_put_flag(msg, i)) | 590 | if (ifmodes & 1) |
797 | goto nla_put_failure; | 591 | NLA_PUT_FLAG(msg, i); |
798 | ifmodes >>= 1; | 592 | ifmodes >>= 1; |
799 | i++; | 593 | i++; |
800 | } | 594 | } |
@@ -837,9 +631,8 @@ static int nl80211_put_iface_combinations(struct wiphy *wiphy, | |||
837 | nl_limit = nla_nest_start(msg, j + 1); | 631 | nl_limit = nla_nest_start(msg, j + 1); |
838 | if (!nl_limit) | 632 | if (!nl_limit) |
839 | goto nla_put_failure; | 633 | goto nla_put_failure; |
840 | if (nla_put_u32(msg, NL80211_IFACE_LIMIT_MAX, | 634 | NLA_PUT_U32(msg, NL80211_IFACE_LIMIT_MAX, |
841 | c->limits[j].max)) | 635 | c->limits[j].max); |
842 | goto nla_put_failure; | ||
843 | if (nl80211_put_iftypes(msg, NL80211_IFACE_LIMIT_TYPES, | 636 | if (nl80211_put_iftypes(msg, NL80211_IFACE_LIMIT_TYPES, |
844 | c->limits[j].types)) | 637 | c->limits[j].types)) |
845 | goto nla_put_failure; | 638 | goto nla_put_failure; |
@@ -848,14 +641,13 @@ static int nl80211_put_iface_combinations(struct wiphy *wiphy, | |||
848 | 641 | ||
849 | nla_nest_end(msg, nl_limits); | 642 | nla_nest_end(msg, nl_limits); |
850 | 643 | ||
851 | if (c->beacon_int_infra_match && | 644 | if (c->beacon_int_infra_match) |
852 | nla_put_flag(msg, NL80211_IFACE_COMB_STA_AP_BI_MATCH)) | 645 | NLA_PUT_FLAG(msg, |
853 | goto nla_put_failure; | 646 | NL80211_IFACE_COMB_STA_AP_BI_MATCH); |
854 | if (nla_put_u32(msg, NL80211_IFACE_COMB_NUM_CHANNELS, | 647 | NLA_PUT_U32(msg, NL80211_IFACE_COMB_NUM_CHANNELS, |
855 | c->num_different_channels) || | 648 | c->num_different_channels); |
856 | nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM, | 649 | NLA_PUT_U32(msg, NL80211_IFACE_COMB_MAXNUM, |
857 | c->max_interfaces)) | 650 | c->max_interfaces); |
858 | goto nla_put_failure; | ||
859 | 651 | ||
860 | nla_nest_end(msg, nl_combi); | 652 | nla_nest_end(msg, nl_combi); |
861 | } | 653 | } |
@@ -867,7 +659,7 @@ nla_put_failure: | |||
867 | return -ENOBUFS; | 659 | return -ENOBUFS; |
868 | } | 660 | } |
869 | 661 | ||
870 | static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flags, | 662 | static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, |
871 | struct cfg80211_registered_device *dev) | 663 | struct cfg80211_registered_device *dev) |
872 | { | 664 | { |
873 | void *hdr; | 665 | void *hdr; |
@@ -882,90 +674,63 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag | |||
882 | const struct ieee80211_txrx_stypes *mgmt_stypes = | 674 | const struct ieee80211_txrx_stypes *mgmt_stypes = |
883 | dev->wiphy.mgmt_stypes; | 675 | dev->wiphy.mgmt_stypes; |
884 | 676 | ||
885 | hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_WIPHY); | 677 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY); |
886 | if (!hdr) | 678 | if (!hdr) |
887 | return -1; | 679 | return -1; |
888 | 680 | ||
889 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx) || | 681 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx); |
890 | nla_put_string(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)) || | 682 | NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)); |
891 | nla_put_u32(msg, NL80211_ATTR_GENERATION, | 683 | |
892 | cfg80211_rdev_list_generation) || | 684 | NLA_PUT_U32(msg, NL80211_ATTR_GENERATION, |
893 | nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT, | 685 | cfg80211_rdev_list_generation); |
894 | dev->wiphy.retry_short) || | 686 | |
895 | nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_LONG, | 687 | NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT, |
896 | dev->wiphy.retry_long) || | 688 | dev->wiphy.retry_short); |
897 | nla_put_u32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, | 689 | NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_LONG, |
898 | dev->wiphy.frag_threshold) || | 690 | dev->wiphy.retry_long); |
899 | nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, | 691 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, |
900 | dev->wiphy.rts_threshold) || | 692 | dev->wiphy.frag_threshold); |
901 | nla_put_u8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS, | 693 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, |
902 | dev->wiphy.coverage_class) || | 694 | dev->wiphy.rts_threshold); |
903 | nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS, | 695 | NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS, |
904 | dev->wiphy.max_scan_ssids) || | 696 | dev->wiphy.coverage_class); |
905 | nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS, | 697 | NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS, |
906 | dev->wiphy.max_sched_scan_ssids) || | 698 | dev->wiphy.max_scan_ssids); |
907 | nla_put_u16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN, | 699 | NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS, |
908 | dev->wiphy.max_scan_ie_len) || | 700 | dev->wiphy.max_sched_scan_ssids); |
909 | nla_put_u16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN, | 701 | NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN, |
910 | dev->wiphy.max_sched_scan_ie_len) || | 702 | dev->wiphy.max_scan_ie_len); |
911 | nla_put_u8(msg, NL80211_ATTR_MAX_MATCH_SETS, | 703 | NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN, |
912 | dev->wiphy.max_match_sets)) | 704 | dev->wiphy.max_sched_scan_ie_len); |
913 | goto nla_put_failure; | 705 | |
914 | 706 | if (dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) | |
915 | if ((dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) && | 707 | NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_IBSS_RSN); |
916 | nla_put_flag(msg, NL80211_ATTR_SUPPORT_IBSS_RSN)) | 708 | if (dev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) |
917 | goto nla_put_failure; | 709 | NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_MESH_AUTH); |
918 | if ((dev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) && | 710 | |
919 | nla_put_flag(msg, NL80211_ATTR_SUPPORT_MESH_AUTH)) | 711 | NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES, |
920 | goto nla_put_failure; | 712 | sizeof(u32) * dev->wiphy.n_cipher_suites, |
921 | if ((dev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) && | 713 | dev->wiphy.cipher_suites); |
922 | nla_put_flag(msg, NL80211_ATTR_SUPPORT_AP_UAPSD)) | 714 | |
923 | goto nla_put_failure; | 715 | NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_PMKIDS, |
924 | if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM) && | 716 | dev->wiphy.max_num_pmkids); |
925 | nla_put_flag(msg, NL80211_ATTR_ROAM_SUPPORT)) | 717 | |
926 | goto nla_put_failure; | 718 | if (dev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) |
927 | if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) && | 719 | NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE); |
928 | nla_put_flag(msg, NL80211_ATTR_TDLS_SUPPORT)) | 720 | |
929 | goto nla_put_failure; | 721 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX, |
930 | if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) && | 722 | dev->wiphy.available_antennas_tx); |
931 | nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP)) | 723 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX, |
932 | goto nla_put_failure; | 724 | dev->wiphy.available_antennas_rx); |
933 | |||
934 | if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES, | ||
935 | sizeof(u32) * dev->wiphy.n_cipher_suites, | ||
936 | dev->wiphy.cipher_suites)) | ||
937 | goto nla_put_failure; | ||
938 | |||
939 | if (nla_put_u8(msg, NL80211_ATTR_MAX_NUM_PMKIDS, | ||
940 | dev->wiphy.max_num_pmkids)) | ||
941 | goto nla_put_failure; | ||
942 | |||
943 | if ((dev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) && | ||
944 | nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE)) | ||
945 | goto nla_put_failure; | ||
946 | |||
947 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX, | ||
948 | dev->wiphy.available_antennas_tx) || | ||
949 | nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX, | ||
950 | dev->wiphy.available_antennas_rx)) | ||
951 | goto nla_put_failure; | ||
952 | |||
953 | if ((dev->wiphy.flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) && | ||
954 | nla_put_u32(msg, NL80211_ATTR_PROBE_RESP_OFFLOAD, | ||
955 | dev->wiphy.probe_resp_offload)) | ||
956 | goto nla_put_failure; | ||
957 | 725 | ||
958 | if ((dev->wiphy.available_antennas_tx || | 726 | if ((dev->wiphy.available_antennas_tx || |
959 | dev->wiphy.available_antennas_rx) && dev->ops->get_antenna) { | 727 | dev->wiphy.available_antennas_rx) && dev->ops->get_antenna) { |
960 | u32 tx_ant = 0, rx_ant = 0; | 728 | u32 tx_ant = 0, rx_ant = 0; |
961 | int res; | 729 | int res; |
962 | res = rdev_get_antenna(dev, &tx_ant, &rx_ant); | 730 | res = dev->ops->get_antenna(&dev->wiphy, &tx_ant, &rx_ant); |
963 | if (!res) { | 731 | if (!res) { |
964 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_TX, | 732 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_ANTENNA_TX, tx_ant); |
965 | tx_ant) || | 733 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_ANTENNA_RX, rx_ant); |
966 | nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_RX, | ||
967 | rx_ant)) | ||
968 | goto nla_put_failure; | ||
969 | } | 734 | } |
970 | } | 735 | } |
971 | 736 | ||
@@ -986,26 +751,17 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag | |||
986 | goto nla_put_failure; | 751 | goto nla_put_failure; |
987 | 752 | ||
988 | /* add HT info */ | 753 | /* add HT info */ |
989 | if (dev->wiphy.bands[band]->ht_cap.ht_supported && | 754 | if (dev->wiphy.bands[band]->ht_cap.ht_supported) { |
990 | (nla_put(msg, NL80211_BAND_ATTR_HT_MCS_SET, | 755 | NLA_PUT(msg, NL80211_BAND_ATTR_HT_MCS_SET, |
991 | sizeof(dev->wiphy.bands[band]->ht_cap.mcs), | 756 | sizeof(dev->wiphy.bands[band]->ht_cap.mcs), |
992 | &dev->wiphy.bands[band]->ht_cap.mcs) || | 757 | &dev->wiphy.bands[band]->ht_cap.mcs); |
993 | nla_put_u16(msg, NL80211_BAND_ATTR_HT_CAPA, | 758 | NLA_PUT_U16(msg, NL80211_BAND_ATTR_HT_CAPA, |
994 | dev->wiphy.bands[band]->ht_cap.cap) || | 759 | dev->wiphy.bands[band]->ht_cap.cap); |
995 | nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR, | 760 | NLA_PUT_U8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR, |
996 | dev->wiphy.bands[band]->ht_cap.ampdu_factor) || | 761 | dev->wiphy.bands[band]->ht_cap.ampdu_factor); |
997 | nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY, | 762 | NLA_PUT_U8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY, |
998 | dev->wiphy.bands[band]->ht_cap.ampdu_density))) | 763 | dev->wiphy.bands[band]->ht_cap.ampdu_density); |
999 | goto nla_put_failure; | 764 | } |
1000 | |||
1001 | /* add VHT info */ | ||
1002 | if (dev->wiphy.bands[band]->vht_cap.vht_supported && | ||
1003 | (nla_put(msg, NL80211_BAND_ATTR_VHT_MCS_SET, | ||
1004 | sizeof(dev->wiphy.bands[band]->vht_cap.vht_mcs), | ||
1005 | &dev->wiphy.bands[band]->vht_cap.vht_mcs) || | ||
1006 | nla_put_u32(msg, NL80211_BAND_ATTR_VHT_CAPA, | ||
1007 | dev->wiphy.bands[band]->vht_cap.cap))) | ||
1008 | goto nla_put_failure; | ||
1009 | 765 | ||
1010 | /* add frequencies */ | 766 | /* add frequencies */ |
1011 | nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS); | 767 | nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS); |
@@ -1038,13 +794,11 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag | |||
1038 | goto nla_put_failure; | 794 | goto nla_put_failure; |
1039 | 795 | ||
1040 | rate = &dev->wiphy.bands[band]->bitrates[i]; | 796 | rate = &dev->wiphy.bands[band]->bitrates[i]; |
1041 | if (nla_put_u32(msg, NL80211_BITRATE_ATTR_RATE, | 797 | NLA_PUT_U32(msg, NL80211_BITRATE_ATTR_RATE, |
1042 | rate->bitrate)) | 798 | rate->bitrate); |
1043 | goto nla_put_failure; | 799 | if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) |
1044 | if ((rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) && | 800 | NLA_PUT_FLAG(msg, |
1045 | nla_put_flag(msg, | 801 | NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE); |
1046 | NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE)) | ||
1047 | goto nla_put_failure; | ||
1048 | 802 | ||
1049 | nla_nest_end(msg, nl_rate); | 803 | nla_nest_end(msg, nl_rate); |
1050 | } | 804 | } |
@@ -1064,15 +818,14 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag | |||
1064 | do { \ | 818 | do { \ |
1065 | if (dev->ops->op) { \ | 819 | if (dev->ops->op) { \ |
1066 | i++; \ | 820 | i++; \ |
1067 | if (nla_put_u32(msg, i, NL80211_CMD_ ## n)) \ | 821 | NLA_PUT_U32(msg, i, NL80211_CMD_ ## n); \ |
1068 | goto nla_put_failure; \ | ||
1069 | } \ | 822 | } \ |
1070 | } while (0) | 823 | } while (0) |
1071 | 824 | ||
1072 | CMD(add_virtual_intf, NEW_INTERFACE); | 825 | CMD(add_virtual_intf, NEW_INTERFACE); |
1073 | CMD(change_virtual_intf, SET_INTERFACE); | 826 | CMD(change_virtual_intf, SET_INTERFACE); |
1074 | CMD(add_key, NEW_KEY); | 827 | CMD(add_key, NEW_KEY); |
1075 | CMD(start_ap, START_AP); | 828 | CMD(add_beacon, NEW_BEACON); |
1076 | CMD(add_station, NEW_STATION); | 829 | CMD(add_station, NEW_STATION); |
1077 | CMD(add_mpath, NEW_MPATH); | 830 | CMD(add_mpath, NEW_MPATH); |
1078 | CMD(update_mesh_config, SET_MESH_CONFIG); | 831 | CMD(update_mesh_config, SET_MESH_CONFIG); |
@@ -1086,68 +839,40 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag | |||
1086 | CMD(set_pmksa, SET_PMKSA); | 839 | CMD(set_pmksa, SET_PMKSA); |
1087 | CMD(del_pmksa, DEL_PMKSA); | 840 | CMD(del_pmksa, DEL_PMKSA); |
1088 | CMD(flush_pmksa, FLUSH_PMKSA); | 841 | CMD(flush_pmksa, FLUSH_PMKSA); |
1089 | if (dev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) | 842 | CMD(remain_on_channel, REMAIN_ON_CHANNEL); |
1090 | CMD(remain_on_channel, REMAIN_ON_CHANNEL); | ||
1091 | CMD(set_bitrate_mask, SET_TX_BITRATE_MASK); | 843 | CMD(set_bitrate_mask, SET_TX_BITRATE_MASK); |
1092 | CMD(mgmt_tx, FRAME); | 844 | CMD(mgmt_tx, FRAME); |
1093 | CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL); | 845 | CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL); |
1094 | if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { | 846 | if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { |
1095 | i++; | 847 | i++; |
1096 | if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS)) | 848 | NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); |
1097 | goto nla_put_failure; | ||
1098 | } | ||
1099 | if (dev->ops->set_monitor_channel || dev->ops->start_ap || | ||
1100 | dev->ops->join_mesh) { | ||
1101 | i++; | ||
1102 | if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL)) | ||
1103 | goto nla_put_failure; | ||
1104 | } | 849 | } |
850 | CMD(set_channel, SET_CHANNEL); | ||
1105 | CMD(set_wds_peer, SET_WDS_PEER); | 851 | CMD(set_wds_peer, SET_WDS_PEER); |
1106 | if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) { | ||
1107 | CMD(tdls_mgmt, TDLS_MGMT); | ||
1108 | CMD(tdls_oper, TDLS_OPER); | ||
1109 | } | ||
1110 | if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) | 852 | if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) |
1111 | CMD(sched_scan_start, START_SCHED_SCAN); | 853 | CMD(sched_scan_start, START_SCHED_SCAN); |
1112 | CMD(probe_client, PROBE_CLIENT); | ||
1113 | CMD(set_noack_map, SET_NOACK_MAP); | ||
1114 | if (dev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) { | ||
1115 | i++; | ||
1116 | if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS)) | ||
1117 | goto nla_put_failure; | ||
1118 | } | ||
1119 | CMD(start_p2p_device, START_P2P_DEVICE); | ||
1120 | CMD(set_mcast_rate, SET_MCAST_RATE); | ||
1121 | |||
1122 | #ifdef CONFIG_NL80211_TESTMODE | ||
1123 | CMD(testmode_cmd, TESTMODE); | ||
1124 | #endif | ||
1125 | 854 | ||
1126 | #undef CMD | 855 | #undef CMD |
1127 | 856 | ||
1128 | if (dev->ops->connect || dev->ops->auth) { | 857 | if (dev->ops->connect || dev->ops->auth) { |
1129 | i++; | 858 | i++; |
1130 | if (nla_put_u32(msg, i, NL80211_CMD_CONNECT)) | 859 | NLA_PUT_U32(msg, i, NL80211_CMD_CONNECT); |
1131 | goto nla_put_failure; | ||
1132 | } | 860 | } |
1133 | 861 | ||
1134 | if (dev->ops->disconnect || dev->ops->deauth) { | 862 | if (dev->ops->disconnect || dev->ops->deauth) { |
1135 | i++; | 863 | i++; |
1136 | if (nla_put_u32(msg, i, NL80211_CMD_DISCONNECT)) | 864 | NLA_PUT_U32(msg, i, NL80211_CMD_DISCONNECT); |
1137 | goto nla_put_failure; | ||
1138 | } | 865 | } |
1139 | 866 | ||
1140 | nla_nest_end(msg, nl_cmds); | 867 | nla_nest_end(msg, nl_cmds); |
1141 | 868 | ||
1142 | if (dev->ops->remain_on_channel && | 869 | if (dev->ops->remain_on_channel) |
1143 | (dev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) && | 870 | NLA_PUT_U32(msg, NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION, |
1144 | nla_put_u32(msg, NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION, | 871 | dev->wiphy.max_remain_on_channel_duration); |
1145 | dev->wiphy.max_remain_on_channel_duration)) | ||
1146 | goto nla_put_failure; | ||
1147 | 872 | ||
1148 | if ((dev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX) && | 873 | /* for now at least assume all drivers have it */ |
1149 | nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK)) | 874 | if (dev->ops->mgmt_tx) |
1150 | goto nla_put_failure; | 875 | NLA_PUT_FLAG(msg, NL80211_ATTR_OFFCHANNEL_TX_OK); |
1151 | 876 | ||
1152 | if (mgmt_stypes) { | 877 | if (mgmt_stypes) { |
1153 | u16 stypes; | 878 | u16 stypes; |
@@ -1165,10 +890,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag | |||
1165 | i = 0; | 890 | i = 0; |
1166 | stypes = mgmt_stypes[ift].tx; | 891 | stypes = mgmt_stypes[ift].tx; |
1167 | while (stypes) { | 892 | while (stypes) { |
1168 | if ((stypes & 1) && | 893 | if (stypes & 1) |
1169 | nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE, | 894 | NLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, |
1170 | (i << 4) | IEEE80211_FTYPE_MGMT)) | 895 | (i << 4) | IEEE80211_FTYPE_MGMT); |
1171 | goto nla_put_failure; | ||
1172 | stypes >>= 1; | 896 | stypes >>= 1; |
1173 | i++; | 897 | i++; |
1174 | } | 898 | } |
@@ -1188,10 +912,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag | |||
1188 | i = 0; | 912 | i = 0; |
1189 | stypes = mgmt_stypes[ift].rx; | 913 | stypes = mgmt_stypes[ift].rx; |
1190 | while (stypes) { | 914 | while (stypes) { |
1191 | if ((stypes & 1) && | 915 | if (stypes & 1) |
1192 | nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE, | 916 | NLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, |
1193 | (i << 4) | IEEE80211_FTYPE_MGMT)) | 917 | (i << 4) | IEEE80211_FTYPE_MGMT); |
1194 | goto nla_put_failure; | ||
1195 | stypes >>= 1; | 918 | stypes >>= 1; |
1196 | i++; | 919 | i++; |
1197 | } | 920 | } |
@@ -1200,7 +923,6 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag | |||
1200 | nla_nest_end(msg, nl_ifs); | 923 | nla_nest_end(msg, nl_ifs); |
1201 | } | 924 | } |
1202 | 925 | ||
1203 | #ifdef CONFIG_PM | ||
1204 | if (dev->wiphy.wowlan.flags || dev->wiphy.wowlan.n_patterns) { | 926 | if (dev->wiphy.wowlan.flags || dev->wiphy.wowlan.n_patterns) { |
1205 | struct nlattr *nl_wowlan; | 927 | struct nlattr *nl_wowlan; |
1206 | 928 | ||
@@ -1209,23 +931,22 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag | |||
1209 | if (!nl_wowlan) | 931 | if (!nl_wowlan) |
1210 | goto nla_put_failure; | 932 | goto nla_put_failure; |
1211 | 933 | ||
1212 | if (((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_ANY) && | 934 | if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_ANY) |
1213 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) || | 935 | NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_ANY); |
1214 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_DISCONNECT) && | 936 | if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_DISCONNECT) |
1215 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) || | 937 | NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_DISCONNECT); |
1216 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_MAGIC_PKT) && | 938 | if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_MAGIC_PKT) |
1217 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) || | 939 | NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT); |
1218 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY) && | 940 | if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY) |
1219 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED)) || | 941 | NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED); |
1220 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) && | 942 | if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) |
1221 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) || | 943 | NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE); |
1222 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ) && | 944 | if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ) |
1223 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) || | 945 | NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST); |
1224 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_4WAY_HANDSHAKE) && | 946 | if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_4WAY_HANDSHAKE) |
1225 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) || | 947 | NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE); |
1226 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_RFKILL_RELEASE) && | 948 | if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_RFKILL_RELEASE) |
1227 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))) | 949 | NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE); |
1228 | goto nla_put_failure; | ||
1229 | if (dev->wiphy.wowlan.n_patterns) { | 950 | if (dev->wiphy.wowlan.n_patterns) { |
1230 | struct nl80211_wowlan_pattern_support pat = { | 951 | struct nl80211_wowlan_pattern_support pat = { |
1231 | .max_patterns = dev->wiphy.wowlan.n_patterns, | 952 | .max_patterns = dev->wiphy.wowlan.n_patterns, |
@@ -1234,14 +955,12 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag | |||
1234 | .max_pattern_len = | 955 | .max_pattern_len = |
1235 | dev->wiphy.wowlan.pattern_max_len, | 956 | dev->wiphy.wowlan.pattern_max_len, |
1236 | }; | 957 | }; |
1237 | if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN, | 958 | NLA_PUT(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN, |
1238 | sizeof(pat), &pat)) | 959 | sizeof(pat), &pat); |
1239 | goto nla_put_failure; | ||
1240 | } | 960 | } |
1241 | 961 | ||
1242 | nla_nest_end(msg, nl_wowlan); | 962 | nla_nest_end(msg, nl_wowlan); |
1243 | } | 963 | } |
1244 | #endif | ||
1245 | 964 | ||
1246 | if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES, | 965 | if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES, |
1247 | dev->wiphy.software_iftypes)) | 966 | dev->wiphy.software_iftypes)) |
@@ -1250,21 +969,6 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag | |||
1250 | if (nl80211_put_iface_combinations(&dev->wiphy, msg)) | 969 | if (nl80211_put_iface_combinations(&dev->wiphy, msg)) |
1251 | goto nla_put_failure; | 970 | goto nla_put_failure; |
1252 | 971 | ||
1253 | if ((dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) && | ||
1254 | nla_put_u32(msg, NL80211_ATTR_DEVICE_AP_SME, | ||
1255 | dev->wiphy.ap_sme_capa)) | ||
1256 | goto nla_put_failure; | ||
1257 | |||
1258 | if (nla_put_u32(msg, NL80211_ATTR_FEATURE_FLAGS, | ||
1259 | dev->wiphy.features)) | ||
1260 | goto nla_put_failure; | ||
1261 | |||
1262 | if (dev->wiphy.ht_capa_mod_mask && | ||
1263 | nla_put(msg, NL80211_ATTR_HT_CAPABILITY_MASK, | ||
1264 | sizeof(*dev->wiphy.ht_capa_mod_mask), | ||
1265 | dev->wiphy.ht_capa_mod_mask)) | ||
1266 | goto nla_put_failure; | ||
1267 | |||
1268 | return genlmsg_end(msg, hdr); | 972 | return genlmsg_end(msg, hdr); |
1269 | 973 | ||
1270 | nla_put_failure: | 974 | nla_put_failure: |
@@ -1284,7 +988,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) | |||
1284 | continue; | 988 | continue; |
1285 | if (++idx <= start) | 989 | if (++idx <= start) |
1286 | continue; | 990 | continue; |
1287 | if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).portid, | 991 | if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).pid, |
1288 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 992 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
1289 | dev) < 0) { | 993 | dev) < 0) { |
1290 | idx--; | 994 | idx--; |
@@ -1307,7 +1011,7 @@ static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1307 | if (!msg) | 1011 | if (!msg) |
1308 | return -ENOMEM; | 1012 | return -ENOMEM; |
1309 | 1013 | ||
1310 | if (nl80211_send_wiphy(msg, info->snd_portid, info->snd_seq, 0, dev) < 0) { | 1014 | if (nl80211_send_wiphy(msg, info->snd_pid, info->snd_seq, 0, dev) < 0) { |
1311 | nlmsg_free(msg); | 1015 | nlmsg_free(msg); |
1312 | return -ENOBUFS; | 1016 | return -ENOBUFS; |
1313 | } | 1017 | } |
@@ -1326,148 +1030,73 @@ static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = { | |||
1326 | static int parse_txq_params(struct nlattr *tb[], | 1030 | static int parse_txq_params(struct nlattr *tb[], |
1327 | struct ieee80211_txq_params *txq_params) | 1031 | struct ieee80211_txq_params *txq_params) |
1328 | { | 1032 | { |
1329 | if (!tb[NL80211_TXQ_ATTR_AC] || !tb[NL80211_TXQ_ATTR_TXOP] || | 1033 | if (!tb[NL80211_TXQ_ATTR_QUEUE] || !tb[NL80211_TXQ_ATTR_TXOP] || |
1330 | !tb[NL80211_TXQ_ATTR_CWMIN] || !tb[NL80211_TXQ_ATTR_CWMAX] || | 1034 | !tb[NL80211_TXQ_ATTR_CWMIN] || !tb[NL80211_TXQ_ATTR_CWMAX] || |
1331 | !tb[NL80211_TXQ_ATTR_AIFS]) | 1035 | !tb[NL80211_TXQ_ATTR_AIFS]) |
1332 | return -EINVAL; | 1036 | return -EINVAL; |
1333 | 1037 | ||
1334 | txq_params->ac = nla_get_u8(tb[NL80211_TXQ_ATTR_AC]); | 1038 | txq_params->queue = nla_get_u8(tb[NL80211_TXQ_ATTR_QUEUE]); |
1335 | txq_params->txop = nla_get_u16(tb[NL80211_TXQ_ATTR_TXOP]); | 1039 | txq_params->txop = nla_get_u16(tb[NL80211_TXQ_ATTR_TXOP]); |
1336 | txq_params->cwmin = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMIN]); | 1040 | txq_params->cwmin = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMIN]); |
1337 | txq_params->cwmax = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMAX]); | 1041 | txq_params->cwmax = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMAX]); |
1338 | txq_params->aifs = nla_get_u8(tb[NL80211_TXQ_ATTR_AIFS]); | 1042 | txq_params->aifs = nla_get_u8(tb[NL80211_TXQ_ATTR_AIFS]); |
1339 | 1043 | ||
1340 | if (txq_params->ac >= NL80211_NUM_ACS) | ||
1341 | return -EINVAL; | ||
1342 | |||
1343 | return 0; | 1044 | return 0; |
1344 | } | 1045 | } |
1345 | 1046 | ||
1346 | static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev) | 1047 | static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev) |
1347 | { | 1048 | { |
1348 | /* | 1049 | /* |
1349 | * You can only set the channel explicitly for WDS interfaces, | 1050 | * You can only set the channel explicitly for AP, mesh |
1350 | * all others have their channel managed via their respective | 1051 | * and WDS type interfaces; all others have their channel |
1351 | * "establish a connection" command (connect, join, ...) | 1052 | * managed via their respective "establish a connection" |
1352 | * | 1053 | * command (connect, join, ...) |
1353 | * For AP/GO and mesh mode, the channel can be set with the | ||
1354 | * channel userspace API, but is only stored and passed to the | ||
1355 | * low-level driver when the AP starts or the mesh is joined. | ||
1356 | * This is for backward compatibility, userspace can also give | ||
1357 | * the channel in the start-ap or join-mesh commands instead. | ||
1358 | * | 1054 | * |
1359 | * Monitors are special as they are normally slaved to | 1055 | * Monitors are special as they are normally slaved to |
1360 | * whatever else is going on, so they have their own special | 1056 | * whatever else is going on, so they behave as though |
1361 | * operation to set the monitor channel if possible. | 1057 | * you tried setting the wiphy channel itself. |
1362 | */ | 1058 | */ |
1363 | return !wdev || | 1059 | return !wdev || |
1364 | wdev->iftype == NL80211_IFTYPE_AP || | 1060 | wdev->iftype == NL80211_IFTYPE_AP || |
1061 | wdev->iftype == NL80211_IFTYPE_WDS || | ||
1365 | wdev->iftype == NL80211_IFTYPE_MESH_POINT || | 1062 | wdev->iftype == NL80211_IFTYPE_MESH_POINT || |
1366 | wdev->iftype == NL80211_IFTYPE_MONITOR || | 1063 | wdev->iftype == NL80211_IFTYPE_MONITOR || |
1367 | wdev->iftype == NL80211_IFTYPE_P2P_GO; | 1064 | wdev->iftype == NL80211_IFTYPE_P2P_GO; |
1368 | } | 1065 | } |
1369 | 1066 | ||
1370 | static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev, | ||
1371 | struct genl_info *info, | ||
1372 | struct cfg80211_chan_def *chandef) | ||
1373 | { | ||
1374 | u32 control_freq; | ||
1375 | |||
1376 | if (!info->attrs[NL80211_ATTR_WIPHY_FREQ]) | ||
1377 | return -EINVAL; | ||
1378 | |||
1379 | control_freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); | ||
1380 | |||
1381 | chandef->chan = ieee80211_get_channel(&rdev->wiphy, control_freq); | ||
1382 | chandef->width = NL80211_CHAN_WIDTH_20_NOHT; | ||
1383 | chandef->center_freq1 = control_freq; | ||
1384 | chandef->center_freq2 = 0; | ||
1385 | |||
1386 | /* Primary channel not allowed */ | ||
1387 | if (!chandef->chan || chandef->chan->flags & IEEE80211_CHAN_DISABLED) | ||
1388 | return -EINVAL; | ||
1389 | |||
1390 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { | ||
1391 | enum nl80211_channel_type chantype; | ||
1392 | |||
1393 | chantype = nla_get_u32( | ||
1394 | info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]); | ||
1395 | |||
1396 | switch (chantype) { | ||
1397 | case NL80211_CHAN_NO_HT: | ||
1398 | case NL80211_CHAN_HT20: | ||
1399 | case NL80211_CHAN_HT40PLUS: | ||
1400 | case NL80211_CHAN_HT40MINUS: | ||
1401 | cfg80211_chandef_create(chandef, chandef->chan, | ||
1402 | chantype); | ||
1403 | break; | ||
1404 | default: | ||
1405 | return -EINVAL; | ||
1406 | } | ||
1407 | } else if (info->attrs[NL80211_ATTR_CHANNEL_WIDTH]) { | ||
1408 | chandef->width = | ||
1409 | nla_get_u32(info->attrs[NL80211_ATTR_CHANNEL_WIDTH]); | ||
1410 | if (info->attrs[NL80211_ATTR_CENTER_FREQ1]) | ||
1411 | chandef->center_freq1 = | ||
1412 | nla_get_u32( | ||
1413 | info->attrs[NL80211_ATTR_CENTER_FREQ1]); | ||
1414 | if (info->attrs[NL80211_ATTR_CENTER_FREQ2]) | ||
1415 | chandef->center_freq2 = | ||
1416 | nla_get_u32( | ||
1417 | info->attrs[NL80211_ATTR_CENTER_FREQ2]); | ||
1418 | } | ||
1419 | |||
1420 | if (!cfg80211_chandef_valid(chandef)) | ||
1421 | return -EINVAL; | ||
1422 | |||
1423 | if (!cfg80211_chandef_usable(&rdev->wiphy, chandef, | ||
1424 | IEEE80211_CHAN_DISABLED)) | ||
1425 | return -EINVAL; | ||
1426 | |||
1427 | return 0; | ||
1428 | } | ||
1429 | |||
1430 | static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, | 1067 | static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, |
1431 | struct wireless_dev *wdev, | 1068 | struct wireless_dev *wdev, |
1432 | struct genl_info *info) | 1069 | struct genl_info *info) |
1433 | { | 1070 | { |
1434 | struct cfg80211_chan_def chandef; | 1071 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; |
1072 | u32 freq; | ||
1435 | int result; | 1073 | int result; |
1436 | enum nl80211_iftype iftype = NL80211_IFTYPE_MONITOR; | ||
1437 | 1074 | ||
1438 | if (wdev) | 1075 | if (!info->attrs[NL80211_ATTR_WIPHY_FREQ]) |
1439 | iftype = wdev->iftype; | 1076 | return -EINVAL; |
1440 | 1077 | ||
1441 | if (!nl80211_can_set_dev_channel(wdev)) | 1078 | if (!nl80211_can_set_dev_channel(wdev)) |
1442 | return -EOPNOTSUPP; | 1079 | return -EOPNOTSUPP; |
1443 | 1080 | ||
1444 | result = nl80211_parse_chandef(rdev, info, &chandef); | 1081 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { |
1445 | if (result) | 1082 | channel_type = nla_get_u32(info->attrs[ |
1446 | return result; | 1083 | NL80211_ATTR_WIPHY_CHANNEL_TYPE]); |
1084 | if (channel_type != NL80211_CHAN_NO_HT && | ||
1085 | channel_type != NL80211_CHAN_HT20 && | ||
1086 | channel_type != NL80211_CHAN_HT40PLUS && | ||
1087 | channel_type != NL80211_CHAN_HT40MINUS) | ||
1088 | return -EINVAL; | ||
1089 | } | ||
1090 | |||
1091 | freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); | ||
1447 | 1092 | ||
1448 | mutex_lock(&rdev->devlist_mtx); | 1093 | mutex_lock(&rdev->devlist_mtx); |
1449 | switch (iftype) { | 1094 | if (wdev) { |
1450 | case NL80211_IFTYPE_AP: | 1095 | wdev_lock(wdev); |
1451 | case NL80211_IFTYPE_P2P_GO: | 1096 | result = cfg80211_set_freq(rdev, wdev, freq, channel_type); |
1452 | if (wdev->beacon_interval) { | 1097 | wdev_unlock(wdev); |
1453 | result = -EBUSY; | 1098 | } else { |
1454 | break; | 1099 | result = cfg80211_set_freq(rdev, NULL, freq, channel_type); |
1455 | } | ||
1456 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, &chandef)) { | ||
1457 | result = -EINVAL; | ||
1458 | break; | ||
1459 | } | ||
1460 | wdev->preset_chandef = chandef; | ||
1461 | result = 0; | ||
1462 | break; | ||
1463 | case NL80211_IFTYPE_MESH_POINT: | ||
1464 | result = cfg80211_set_mesh_channel(rdev, wdev, &chandef); | ||
1465 | break; | ||
1466 | case NL80211_IFTYPE_MONITOR: | ||
1467 | result = cfg80211_set_monitor_channel(rdev, &chandef); | ||
1468 | break; | ||
1469 | default: | ||
1470 | result = -EINVAL; | ||
1471 | } | 1100 | } |
1472 | mutex_unlock(&rdev->devlist_mtx); | 1101 | mutex_unlock(&rdev->devlist_mtx); |
1473 | 1102 | ||
@@ -1502,7 +1131,7 @@ static int nl80211_set_wds_peer(struct sk_buff *skb, struct genl_info *info) | |||
1502 | return -EOPNOTSUPP; | 1131 | return -EOPNOTSUPP; |
1503 | 1132 | ||
1504 | bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); | 1133 | bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); |
1505 | return rdev_set_wds_peer(rdev, dev, bssid); | 1134 | return rdev->ops->set_wds_peer(wdev->wiphy, dev, bssid); |
1506 | } | 1135 | } |
1507 | 1136 | ||
1508 | 1137 | ||
@@ -1541,8 +1170,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1541 | } | 1170 | } |
1542 | 1171 | ||
1543 | if (!netdev) { | 1172 | if (!netdev) { |
1544 | rdev = __cfg80211_rdev_from_attrs(genl_info_net(info), | 1173 | rdev = __cfg80211_rdev_from_info(info); |
1545 | info->attrs); | ||
1546 | if (IS_ERR(rdev)) { | 1174 | if (IS_ERR(rdev)) { |
1547 | mutex_unlock(&cfg80211_mutex); | 1175 | mutex_unlock(&cfg80211_mutex); |
1548 | return PTR_ERR(rdev); | 1176 | return PTR_ERR(rdev); |
@@ -1552,8 +1180,11 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1552 | result = 0; | 1180 | result = 0; |
1553 | 1181 | ||
1554 | mutex_lock(&rdev->mtx); | 1182 | mutex_lock(&rdev->mtx); |
1555 | } else | 1183 | } else if (netif_running(netdev) && |
1184 | nl80211_can_set_dev_channel(netdev->ieee80211_ptr)) | ||
1556 | wdev = netdev->ieee80211_ptr; | 1185 | wdev = netdev->ieee80211_ptr; |
1186 | else | ||
1187 | wdev = NULL; | ||
1557 | 1188 | ||
1558 | /* | 1189 | /* |
1559 | * end workaround code, by now the rdev is available | 1190 | * end workaround code, by now the rdev is available |
@@ -1578,22 +1209,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1578 | goto bad_res; | 1209 | goto bad_res; |
1579 | } | 1210 | } |
1580 | 1211 | ||
1581 | if (!netdev) { | ||
1582 | result = -EINVAL; | ||
1583 | goto bad_res; | ||
1584 | } | ||
1585 | |||
1586 | if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | ||
1587 | netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { | ||
1588 | result = -EINVAL; | ||
1589 | goto bad_res; | ||
1590 | } | ||
1591 | |||
1592 | if (!netif_running(netdev)) { | ||
1593 | result = -ENETDOWN; | ||
1594 | goto bad_res; | ||
1595 | } | ||
1596 | |||
1597 | nla_for_each_nested(nl_txq_params, | 1212 | nla_for_each_nested(nl_txq_params, |
1598 | info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS], | 1213 | info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS], |
1599 | rem_txq_params) { | 1214 | rem_txq_params) { |
@@ -1605,29 +1220,23 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1605 | if (result) | 1220 | if (result) |
1606 | goto bad_res; | 1221 | goto bad_res; |
1607 | 1222 | ||
1608 | result = rdev_set_txq_params(rdev, netdev, | 1223 | result = rdev->ops->set_txq_params(&rdev->wiphy, |
1609 | &txq_params); | 1224 | &txq_params); |
1610 | if (result) | 1225 | if (result) |
1611 | goto bad_res; | 1226 | goto bad_res; |
1612 | } | 1227 | } |
1613 | } | 1228 | } |
1614 | 1229 | ||
1615 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { | 1230 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { |
1616 | result = __nl80211_set_channel(rdev, | 1231 | result = __nl80211_set_channel(rdev, wdev, info); |
1617 | nl80211_can_set_dev_channel(wdev) ? wdev : NULL, | ||
1618 | info); | ||
1619 | if (result) | 1232 | if (result) |
1620 | goto bad_res; | 1233 | goto bad_res; |
1621 | } | 1234 | } |
1622 | 1235 | ||
1623 | if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) { | 1236 | if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) { |
1624 | struct wireless_dev *txp_wdev = wdev; | ||
1625 | enum nl80211_tx_power_setting type; | 1237 | enum nl80211_tx_power_setting type; |
1626 | int idx, mbm = 0; | 1238 | int idx, mbm = 0; |
1627 | 1239 | ||
1628 | if (!(rdev->wiphy.features & NL80211_FEATURE_VIF_TXPOWER)) | ||
1629 | txp_wdev = NULL; | ||
1630 | |||
1631 | if (!rdev->ops->set_tx_power) { | 1240 | if (!rdev->ops->set_tx_power) { |
1632 | result = -EOPNOTSUPP; | 1241 | result = -EOPNOTSUPP; |
1633 | goto bad_res; | 1242 | goto bad_res; |
@@ -1647,7 +1256,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1647 | mbm = nla_get_u32(info->attrs[idx]); | 1256 | mbm = nla_get_u32(info->attrs[idx]); |
1648 | } | 1257 | } |
1649 | 1258 | ||
1650 | result = rdev_set_tx_power(rdev, txp_wdev, type, mbm); | 1259 | result = rdev->ops->set_tx_power(&rdev->wiphy, type, mbm); |
1651 | if (result) | 1260 | if (result) |
1652 | goto bad_res; | 1261 | goto bad_res; |
1653 | } | 1262 | } |
@@ -1676,7 +1285,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1676 | tx_ant = tx_ant & rdev->wiphy.available_antennas_tx; | 1285 | tx_ant = tx_ant & rdev->wiphy.available_antennas_tx; |
1677 | rx_ant = rx_ant & rdev->wiphy.available_antennas_rx; | 1286 | rx_ant = rx_ant & rdev->wiphy.available_antennas_rx; |
1678 | 1287 | ||
1679 | result = rdev_set_antenna(rdev, tx_ant, rx_ant); | 1288 | result = rdev->ops->set_antenna(&rdev->wiphy, tx_ant, rx_ant); |
1680 | if (result) | 1289 | if (result) |
1681 | goto bad_res; | 1290 | goto bad_res; |
1682 | } | 1291 | } |
@@ -1761,7 +1370,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1761 | if (changed & WIPHY_PARAM_COVERAGE_CLASS) | 1370 | if (changed & WIPHY_PARAM_COVERAGE_CLASS) |
1762 | rdev->wiphy.coverage_class = coverage_class; | 1371 | rdev->wiphy.coverage_class = coverage_class; |
1763 | 1372 | ||
1764 | result = rdev_set_wiphy_params(rdev, changed); | 1373 | result = rdev->ops->set_wiphy_params(&rdev->wiphy, changed); |
1765 | if (result) { | 1374 | if (result) { |
1766 | rdev->wiphy.retry_short = old_retry_short; | 1375 | rdev->wiphy.retry_short = old_retry_short; |
1767 | rdev->wiphy.retry_long = old_retry_long; | 1376 | rdev->wiphy.retry_long = old_retry_long; |
@@ -1778,81 +1387,25 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1778 | return result; | 1387 | return result; |
1779 | } | 1388 | } |
1780 | 1389 | ||
1781 | static inline u64 wdev_id(struct wireless_dev *wdev) | ||
1782 | { | ||
1783 | return (u64)wdev->identifier | | ||
1784 | ((u64)wiphy_to_dev(wdev->wiphy)->wiphy_idx << 32); | ||
1785 | } | ||
1786 | |||
1787 | static int nl80211_send_chandef(struct sk_buff *msg, | ||
1788 | struct cfg80211_chan_def *chandef) | ||
1789 | { | ||
1790 | WARN_ON(!cfg80211_chandef_valid(chandef)); | ||
1791 | |||
1792 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, | ||
1793 | chandef->chan->center_freq)) | ||
1794 | return -ENOBUFS; | ||
1795 | switch (chandef->width) { | ||
1796 | case NL80211_CHAN_WIDTH_20_NOHT: | ||
1797 | case NL80211_CHAN_WIDTH_20: | ||
1798 | case NL80211_CHAN_WIDTH_40: | ||
1799 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, | ||
1800 | cfg80211_get_chandef_type(chandef))) | ||
1801 | return -ENOBUFS; | ||
1802 | break; | ||
1803 | default: | ||
1804 | break; | ||
1805 | } | ||
1806 | if (nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, chandef->width)) | ||
1807 | return -ENOBUFS; | ||
1808 | if (nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ1, chandef->center_freq1)) | ||
1809 | return -ENOBUFS; | ||
1810 | if (chandef->center_freq2 && | ||
1811 | nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ2, chandef->center_freq2)) | ||
1812 | return -ENOBUFS; | ||
1813 | return 0; | ||
1814 | } | ||
1815 | 1390 | ||
1816 | static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags, | 1391 | static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags, |
1817 | struct cfg80211_registered_device *rdev, | 1392 | struct cfg80211_registered_device *rdev, |
1818 | struct wireless_dev *wdev) | 1393 | struct net_device *dev) |
1819 | { | 1394 | { |
1820 | struct net_device *dev = wdev->netdev; | ||
1821 | void *hdr; | 1395 | void *hdr; |
1822 | 1396 | ||
1823 | hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_INTERFACE); | 1397 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_INTERFACE); |
1824 | if (!hdr) | 1398 | if (!hdr) |
1825 | return -1; | 1399 | return -1; |
1826 | 1400 | ||
1827 | if (dev && | 1401 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); |
1828 | (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || | 1402 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); |
1829 | nla_put_string(msg, NL80211_ATTR_IFNAME, dev->name))) | 1403 | NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name); |
1830 | goto nla_put_failure; | 1404 | NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, dev->ieee80211_ptr->iftype); |
1831 | |||
1832 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | ||
1833 | nla_put_u32(msg, NL80211_ATTR_IFTYPE, wdev->iftype) || | ||
1834 | nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) || | ||
1835 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, wdev_address(wdev)) || | ||
1836 | nla_put_u32(msg, NL80211_ATTR_GENERATION, | ||
1837 | rdev->devlist_generation ^ | ||
1838 | (cfg80211_rdev_list_generation << 2))) | ||
1839 | goto nla_put_failure; | ||
1840 | |||
1841 | if (rdev->ops->get_channel) { | ||
1842 | int ret; | ||
1843 | struct cfg80211_chan_def chandef; | ||
1844 | |||
1845 | ret = rdev_get_channel(rdev, wdev, &chandef); | ||
1846 | if (ret == 0) { | ||
1847 | if (nl80211_send_chandef(msg, &chandef)) | ||
1848 | goto nla_put_failure; | ||
1849 | } | ||
1850 | } | ||
1851 | 1405 | ||
1852 | if (wdev->ssid_len) { | 1406 | NLA_PUT_U32(msg, NL80211_ATTR_GENERATION, |
1853 | if (nla_put(msg, NL80211_ATTR_SSID, wdev->ssid_len, wdev->ssid)) | 1407 | rdev->devlist_generation ^ |
1854 | goto nla_put_failure; | 1408 | (cfg80211_rdev_list_generation << 2)); |
1855 | } | ||
1856 | 1409 | ||
1857 | return genlmsg_end(msg, hdr); | 1410 | return genlmsg_end(msg, hdr); |
1858 | 1411 | ||
@@ -1881,14 +1434,14 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback * | |||
1881 | if_idx = 0; | 1434 | if_idx = 0; |
1882 | 1435 | ||
1883 | mutex_lock(&rdev->devlist_mtx); | 1436 | mutex_lock(&rdev->devlist_mtx); |
1884 | list_for_each_entry(wdev, &rdev->wdev_list, list) { | 1437 | list_for_each_entry(wdev, &rdev->netdev_list, list) { |
1885 | if (if_idx < if_start) { | 1438 | if (if_idx < if_start) { |
1886 | if_idx++; | 1439 | if_idx++; |
1887 | continue; | 1440 | continue; |
1888 | } | 1441 | } |
1889 | if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid, | 1442 | if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid, |
1890 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 1443 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
1891 | rdev, wdev) < 0) { | 1444 | rdev, wdev->netdev) < 0) { |
1892 | mutex_unlock(&rdev->devlist_mtx); | 1445 | mutex_unlock(&rdev->devlist_mtx); |
1893 | goto out; | 1446 | goto out; |
1894 | } | 1447 | } |
@@ -1911,14 +1464,14 @@ static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info) | |||
1911 | { | 1464 | { |
1912 | struct sk_buff *msg; | 1465 | struct sk_buff *msg; |
1913 | struct cfg80211_registered_device *dev = info->user_ptr[0]; | 1466 | struct cfg80211_registered_device *dev = info->user_ptr[0]; |
1914 | struct wireless_dev *wdev = info->user_ptr[1]; | 1467 | struct net_device *netdev = info->user_ptr[1]; |
1915 | 1468 | ||
1916 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 1469 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
1917 | if (!msg) | 1470 | if (!msg) |
1918 | return -ENOMEM; | 1471 | return -ENOMEM; |
1919 | 1472 | ||
1920 | if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0, | 1473 | if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0, |
1921 | dev, wdev) < 0) { | 1474 | dev, netdev) < 0) { |
1922 | nlmsg_free(msg); | 1475 | nlmsg_free(msg); |
1923 | return -ENOBUFS; | 1476 | return -ENOBUFS; |
1924 | } | 1477 | } |
@@ -2058,8 +1611,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
2058 | { | 1611 | { |
2059 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 1612 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
2060 | struct vif_params params; | 1613 | struct vif_params params; |
2061 | struct wireless_dev *wdev; | 1614 | struct net_device *dev; |
2062 | struct sk_buff *msg; | ||
2063 | int err; | 1615 | int err; |
2064 | enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED; | 1616 | enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED; |
2065 | u32 flags; | 1617 | u32 flags; |
@@ -2086,25 +1638,19 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
2086 | return err; | 1638 | return err; |
2087 | } | 1639 | } |
2088 | 1640 | ||
2089 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
2090 | if (!msg) | ||
2091 | return -ENOMEM; | ||
2092 | |||
2093 | err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? | 1641 | err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? |
2094 | info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, | 1642 | info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, |
2095 | &flags); | 1643 | &flags); |
2096 | wdev = rdev_add_virtual_intf(rdev, | 1644 | dev = rdev->ops->add_virtual_intf(&rdev->wiphy, |
2097 | nla_data(info->attrs[NL80211_ATTR_IFNAME]), | 1645 | nla_data(info->attrs[NL80211_ATTR_IFNAME]), |
2098 | type, err ? NULL : &flags, ¶ms); | 1646 | type, err ? NULL : &flags, ¶ms); |
2099 | if (IS_ERR(wdev)) { | 1647 | if (IS_ERR(dev)) |
2100 | nlmsg_free(msg); | 1648 | return PTR_ERR(dev); |
2101 | return PTR_ERR(wdev); | 1649 | |
2102 | } | 1650 | if (type == NL80211_IFTYPE_MESH_POINT && |
1651 | info->attrs[NL80211_ATTR_MESH_ID]) { | ||
1652 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
2103 | 1653 | ||
2104 | switch (type) { | ||
2105 | case NL80211_IFTYPE_MESH_POINT: | ||
2106 | if (!info->attrs[NL80211_ATTR_MESH_ID]) | ||
2107 | break; | ||
2108 | wdev_lock(wdev); | 1654 | wdev_lock(wdev); |
2109 | BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN != | 1655 | BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN != |
2110 | IEEE80211_MAX_MESH_ID_LEN); | 1656 | IEEE80211_MAX_MESH_ID_LEN); |
@@ -2113,73 +1659,20 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
2113 | memcpy(wdev->ssid, nla_data(info->attrs[NL80211_ATTR_MESH_ID]), | 1659 | memcpy(wdev->ssid, nla_data(info->attrs[NL80211_ATTR_MESH_ID]), |
2114 | wdev->mesh_id_up_len); | 1660 | wdev->mesh_id_up_len); |
2115 | wdev_unlock(wdev); | 1661 | wdev_unlock(wdev); |
2116 | break; | ||
2117 | case NL80211_IFTYPE_P2P_DEVICE: | ||
2118 | /* | ||
2119 | * P2P Device doesn't have a netdev, so doesn't go | ||
2120 | * through the netdev notifier and must be added here | ||
2121 | */ | ||
2122 | mutex_init(&wdev->mtx); | ||
2123 | INIT_LIST_HEAD(&wdev->event_list); | ||
2124 | spin_lock_init(&wdev->event_lock); | ||
2125 | INIT_LIST_HEAD(&wdev->mgmt_registrations); | ||
2126 | spin_lock_init(&wdev->mgmt_registrations_lock); | ||
2127 | |||
2128 | mutex_lock(&rdev->devlist_mtx); | ||
2129 | wdev->identifier = ++rdev->wdev_id; | ||
2130 | list_add_rcu(&wdev->list, &rdev->wdev_list); | ||
2131 | rdev->devlist_generation++; | ||
2132 | mutex_unlock(&rdev->devlist_mtx); | ||
2133 | break; | ||
2134 | default: | ||
2135 | break; | ||
2136 | } | ||
2137 | |||
2138 | if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0, | ||
2139 | rdev, wdev) < 0) { | ||
2140 | nlmsg_free(msg); | ||
2141 | return -ENOBUFS; | ||
2142 | } | 1662 | } |
2143 | 1663 | ||
2144 | return genlmsg_reply(msg, info); | 1664 | return 0; |
2145 | } | 1665 | } |
2146 | 1666 | ||
2147 | static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info) | 1667 | static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info) |
2148 | { | 1668 | { |
2149 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 1669 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
2150 | struct wireless_dev *wdev = info->user_ptr[1]; | ||
2151 | |||
2152 | if (!rdev->ops->del_virtual_intf) | ||
2153 | return -EOPNOTSUPP; | ||
2154 | |||
2155 | /* | ||
2156 | * If we remove a wireless device without a netdev then clear | ||
2157 | * user_ptr[1] so that nl80211_post_doit won't dereference it | ||
2158 | * to check if it needs to do dev_put(). Otherwise it crashes | ||
2159 | * since the wdev has been freed, unlike with a netdev where | ||
2160 | * we need the dev_put() for the netdev to really be freed. | ||
2161 | */ | ||
2162 | if (!wdev->netdev) | ||
2163 | info->user_ptr[1] = NULL; | ||
2164 | |||
2165 | return rdev_del_virtual_intf(rdev, wdev); | ||
2166 | } | ||
2167 | |||
2168 | static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info) | ||
2169 | { | ||
2170 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
2171 | struct net_device *dev = info->user_ptr[1]; | 1670 | struct net_device *dev = info->user_ptr[1]; |
2172 | u16 noack_map; | ||
2173 | |||
2174 | if (!info->attrs[NL80211_ATTR_NOACK_MAP]) | ||
2175 | return -EINVAL; | ||
2176 | 1671 | ||
2177 | if (!rdev->ops->set_noack_map) | 1672 | if (!rdev->ops->del_virtual_intf) |
2178 | return -EOPNOTSUPP; | 1673 | return -EOPNOTSUPP; |
2179 | 1674 | ||
2180 | noack_map = nla_get_u16(info->attrs[NL80211_ATTR_NOACK_MAP]); | 1675 | return rdev->ops->del_virtual_intf(&rdev->wiphy, dev); |
2181 | |||
2182 | return rdev_set_noack_map(rdev, dev, noack_map); | ||
2183 | } | 1676 | } |
2184 | 1677 | ||
2185 | struct get_key_cookie { | 1678 | struct get_key_cookie { |
@@ -2193,34 +1686,35 @@ static void get_key_callback(void *c, struct key_params *params) | |||
2193 | struct nlattr *key; | 1686 | struct nlattr *key; |
2194 | struct get_key_cookie *cookie = c; | 1687 | struct get_key_cookie *cookie = c; |
2195 | 1688 | ||
2196 | if ((params->key && | 1689 | if (params->key) |
2197 | nla_put(cookie->msg, NL80211_ATTR_KEY_DATA, | 1690 | NLA_PUT(cookie->msg, NL80211_ATTR_KEY_DATA, |
2198 | params->key_len, params->key)) || | 1691 | params->key_len, params->key); |
2199 | (params->seq && | 1692 | |
2200 | nla_put(cookie->msg, NL80211_ATTR_KEY_SEQ, | 1693 | if (params->seq) |
2201 | params->seq_len, params->seq)) || | 1694 | NLA_PUT(cookie->msg, NL80211_ATTR_KEY_SEQ, |
2202 | (params->cipher && | 1695 | params->seq_len, params->seq); |
2203 | nla_put_u32(cookie->msg, NL80211_ATTR_KEY_CIPHER, | 1696 | |
2204 | params->cipher))) | 1697 | if (params->cipher) |
2205 | goto nla_put_failure; | 1698 | NLA_PUT_U32(cookie->msg, NL80211_ATTR_KEY_CIPHER, |
1699 | params->cipher); | ||
2206 | 1700 | ||
2207 | key = nla_nest_start(cookie->msg, NL80211_ATTR_KEY); | 1701 | key = nla_nest_start(cookie->msg, NL80211_ATTR_KEY); |
2208 | if (!key) | 1702 | if (!key) |
2209 | goto nla_put_failure; | 1703 | goto nla_put_failure; |
2210 | 1704 | ||
2211 | if ((params->key && | 1705 | if (params->key) |
2212 | nla_put(cookie->msg, NL80211_KEY_DATA, | 1706 | NLA_PUT(cookie->msg, NL80211_KEY_DATA, |
2213 | params->key_len, params->key)) || | 1707 | params->key_len, params->key); |
2214 | (params->seq && | ||
2215 | nla_put(cookie->msg, NL80211_KEY_SEQ, | ||
2216 | params->seq_len, params->seq)) || | ||
2217 | (params->cipher && | ||
2218 | nla_put_u32(cookie->msg, NL80211_KEY_CIPHER, | ||
2219 | params->cipher))) | ||
2220 | goto nla_put_failure; | ||
2221 | 1708 | ||
2222 | if (nla_put_u8(cookie->msg, NL80211_ATTR_KEY_IDX, cookie->idx)) | 1709 | if (params->seq) |
2223 | goto nla_put_failure; | 1710 | NLA_PUT(cookie->msg, NL80211_KEY_SEQ, |
1711 | params->seq_len, params->seq); | ||
1712 | |||
1713 | if (params->cipher) | ||
1714 | NLA_PUT_U32(cookie->msg, NL80211_KEY_CIPHER, | ||
1715 | params->cipher); | ||
1716 | |||
1717 | NLA_PUT_U8(cookie->msg, NL80211_ATTR_KEY_IDX, cookie->idx); | ||
2224 | 1718 | ||
2225 | nla_nest_end(cookie->msg, key); | 1719 | nla_nest_end(cookie->msg, key); |
2226 | 1720 | ||
@@ -2270,7 +1764,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) | |||
2270 | if (!msg) | 1764 | if (!msg) |
2271 | return -ENOMEM; | 1765 | return -ENOMEM; |
2272 | 1766 | ||
2273 | hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0, | 1767 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, |
2274 | NL80211_CMD_NEW_KEY); | 1768 | NL80211_CMD_NEW_KEY); |
2275 | if (IS_ERR(hdr)) | 1769 | if (IS_ERR(hdr)) |
2276 | return PTR_ERR(hdr); | 1770 | return PTR_ERR(hdr); |
@@ -2278,19 +1772,17 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) | |||
2278 | cookie.msg = msg; | 1772 | cookie.msg = msg; |
2279 | cookie.idx = key_idx; | 1773 | cookie.idx = key_idx; |
2280 | 1774 | ||
2281 | if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || | 1775 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); |
2282 | nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx)) | 1776 | NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx); |
2283 | goto nla_put_failure; | 1777 | if (mac_addr) |
2284 | if (mac_addr && | 1778 | NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); |
2285 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr)) | ||
2286 | goto nla_put_failure; | ||
2287 | 1779 | ||
2288 | if (pairwise && mac_addr && | 1780 | if (pairwise && mac_addr && |
2289 | !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) | 1781 | !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) |
2290 | return -ENOENT; | 1782 | return -ENOENT; |
2291 | 1783 | ||
2292 | err = rdev_get_key(rdev, dev, key_idx, pairwise, mac_addr, &cookie, | 1784 | err = rdev->ops->get_key(&rdev->wiphy, dev, key_idx, pairwise, |
2293 | get_key_callback); | 1785 | mac_addr, &cookie, get_key_callback); |
2294 | 1786 | ||
2295 | if (err) | 1787 | if (err) |
2296 | goto free_msg; | 1788 | goto free_msg; |
@@ -2338,7 +1830,7 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) | |||
2338 | if (err) | 1830 | if (err) |
2339 | goto out; | 1831 | goto out; |
2340 | 1832 | ||
2341 | err = rdev_set_default_key(rdev, dev, key.idx, | 1833 | err = rdev->ops->set_default_key(&rdev->wiphy, dev, key.idx, |
2342 | key.def_uni, key.def_multi); | 1834 | key.def_uni, key.def_multi); |
2343 | 1835 | ||
2344 | if (err) | 1836 | if (err) |
@@ -2362,7 +1854,8 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) | |||
2362 | if (err) | 1854 | if (err) |
2363 | goto out; | 1855 | goto out; |
2364 | 1856 | ||
2365 | err = rdev_set_default_mgmt_key(rdev, dev, key.idx); | 1857 | err = rdev->ops->set_default_mgmt_key(&rdev->wiphy, |
1858 | dev, key.idx); | ||
2366 | if (err) | 1859 | if (err) |
2367 | goto out; | 1860 | goto out; |
2368 | 1861 | ||
@@ -2418,9 +1911,9 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) | |||
2418 | wdev_lock(dev->ieee80211_ptr); | 1911 | wdev_lock(dev->ieee80211_ptr); |
2419 | err = nl80211_key_allowed(dev->ieee80211_ptr); | 1912 | err = nl80211_key_allowed(dev->ieee80211_ptr); |
2420 | if (!err) | 1913 | if (!err) |
2421 | err = rdev_add_key(rdev, dev, key.idx, | 1914 | err = rdev->ops->add_key(&rdev->wiphy, dev, key.idx, |
2422 | key.type == NL80211_KEYTYPE_PAIRWISE, | 1915 | key.type == NL80211_KEYTYPE_PAIRWISE, |
2423 | mac_addr, &key.p); | 1916 | mac_addr, &key.p); |
2424 | wdev_unlock(dev->ieee80211_ptr); | 1917 | wdev_unlock(dev->ieee80211_ptr); |
2425 | 1918 | ||
2426 | return err; | 1919 | return err; |
@@ -2464,9 +1957,9 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) | |||
2464 | err = -ENOENT; | 1957 | err = -ENOENT; |
2465 | 1958 | ||
2466 | if (!err) | 1959 | if (!err) |
2467 | err = rdev_del_key(rdev, dev, key.idx, | 1960 | err = rdev->ops->del_key(&rdev->wiphy, dev, key.idx, |
2468 | key.type == NL80211_KEYTYPE_PAIRWISE, | 1961 | key.type == NL80211_KEYTYPE_PAIRWISE, |
2469 | mac_addr); | 1962 | mac_addr); |
2470 | 1963 | ||
2471 | #ifdef CONFIG_CFG80211_WEXT | 1964 | #ifdef CONFIG_CFG80211_WEXT |
2472 | if (!err) { | 1965 | if (!err) { |
@@ -2481,291 +1974,96 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) | |||
2481 | return err; | 1974 | return err; |
2482 | } | 1975 | } |
2483 | 1976 | ||
2484 | static int nl80211_parse_beacon(struct genl_info *info, | 1977 | static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) |
2485 | struct cfg80211_beacon_data *bcn) | ||
2486 | { | ||
2487 | bool haveinfo = false; | ||
2488 | |||
2489 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL]) || | ||
2490 | !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]) || | ||
2491 | !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE_PROBE_RESP]) || | ||
2492 | !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE_ASSOC_RESP])) | ||
2493 | return -EINVAL; | ||
2494 | |||
2495 | memset(bcn, 0, sizeof(*bcn)); | ||
2496 | |||
2497 | if (info->attrs[NL80211_ATTR_BEACON_HEAD]) { | ||
2498 | bcn->head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]); | ||
2499 | bcn->head_len = nla_len(info->attrs[NL80211_ATTR_BEACON_HEAD]); | ||
2500 | if (!bcn->head_len) | ||
2501 | return -EINVAL; | ||
2502 | haveinfo = true; | ||
2503 | } | ||
2504 | |||
2505 | if (info->attrs[NL80211_ATTR_BEACON_TAIL]) { | ||
2506 | bcn->tail = nla_data(info->attrs[NL80211_ATTR_BEACON_TAIL]); | ||
2507 | bcn->tail_len = | ||
2508 | nla_len(info->attrs[NL80211_ATTR_BEACON_TAIL]); | ||
2509 | haveinfo = true; | ||
2510 | } | ||
2511 | |||
2512 | if (!haveinfo) | ||
2513 | return -EINVAL; | ||
2514 | |||
2515 | if (info->attrs[NL80211_ATTR_IE]) { | ||
2516 | bcn->beacon_ies = nla_data(info->attrs[NL80211_ATTR_IE]); | ||
2517 | bcn->beacon_ies_len = nla_len(info->attrs[NL80211_ATTR_IE]); | ||
2518 | } | ||
2519 | |||
2520 | if (info->attrs[NL80211_ATTR_IE_PROBE_RESP]) { | ||
2521 | bcn->proberesp_ies = | ||
2522 | nla_data(info->attrs[NL80211_ATTR_IE_PROBE_RESP]); | ||
2523 | bcn->proberesp_ies_len = | ||
2524 | nla_len(info->attrs[NL80211_ATTR_IE_PROBE_RESP]); | ||
2525 | } | ||
2526 | |||
2527 | if (info->attrs[NL80211_ATTR_IE_ASSOC_RESP]) { | ||
2528 | bcn->assocresp_ies = | ||
2529 | nla_data(info->attrs[NL80211_ATTR_IE_ASSOC_RESP]); | ||
2530 | bcn->assocresp_ies_len = | ||
2531 | nla_len(info->attrs[NL80211_ATTR_IE_ASSOC_RESP]); | ||
2532 | } | ||
2533 | |||
2534 | if (info->attrs[NL80211_ATTR_PROBE_RESP]) { | ||
2535 | bcn->probe_resp = | ||
2536 | nla_data(info->attrs[NL80211_ATTR_PROBE_RESP]); | ||
2537 | bcn->probe_resp_len = | ||
2538 | nla_len(info->attrs[NL80211_ATTR_PROBE_RESP]); | ||
2539 | } | ||
2540 | |||
2541 | return 0; | ||
2542 | } | ||
2543 | |||
2544 | static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev, | ||
2545 | struct cfg80211_ap_settings *params) | ||
2546 | { | ||
2547 | struct wireless_dev *wdev; | ||
2548 | bool ret = false; | ||
2549 | |||
2550 | mutex_lock(&rdev->devlist_mtx); | ||
2551 | |||
2552 | list_for_each_entry(wdev, &rdev->wdev_list, list) { | ||
2553 | if (wdev->iftype != NL80211_IFTYPE_AP && | ||
2554 | wdev->iftype != NL80211_IFTYPE_P2P_GO) | ||
2555 | continue; | ||
2556 | |||
2557 | if (!wdev->preset_chandef.chan) | ||
2558 | continue; | ||
2559 | |||
2560 | params->chandef = wdev->preset_chandef; | ||
2561 | ret = true; | ||
2562 | break; | ||
2563 | } | ||
2564 | |||
2565 | mutex_unlock(&rdev->devlist_mtx); | ||
2566 | |||
2567 | return ret; | ||
2568 | } | ||
2569 | |||
2570 | static bool nl80211_valid_auth_type(struct cfg80211_registered_device *rdev, | ||
2571 | enum nl80211_auth_type auth_type, | ||
2572 | enum nl80211_commands cmd) | ||
2573 | { | ||
2574 | if (auth_type > NL80211_AUTHTYPE_MAX) | ||
2575 | return false; | ||
2576 | |||
2577 | switch (cmd) { | ||
2578 | case NL80211_CMD_AUTHENTICATE: | ||
2579 | if (!(rdev->wiphy.features & NL80211_FEATURE_SAE) && | ||
2580 | auth_type == NL80211_AUTHTYPE_SAE) | ||
2581 | return false; | ||
2582 | return true; | ||
2583 | case NL80211_CMD_CONNECT: | ||
2584 | case NL80211_CMD_START_AP: | ||
2585 | /* SAE not supported yet */ | ||
2586 | if (auth_type == NL80211_AUTHTYPE_SAE) | ||
2587 | return false; | ||
2588 | return true; | ||
2589 | default: | ||
2590 | return false; | ||
2591 | } | ||
2592 | } | ||
2593 | |||
2594 | static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) | ||
2595 | { | 1978 | { |
1979 | int (*call)(struct wiphy *wiphy, struct net_device *dev, | ||
1980 | struct beacon_parameters *info); | ||
2596 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 1981 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
2597 | struct net_device *dev = info->user_ptr[1]; | 1982 | struct net_device *dev = info->user_ptr[1]; |
2598 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 1983 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
2599 | struct cfg80211_ap_settings params; | 1984 | struct beacon_parameters params; |
2600 | int err; | 1985 | int haveinfo = 0, err; |
1986 | |||
1987 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL])) | ||
1988 | return -EINVAL; | ||
2601 | 1989 | ||
2602 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | 1990 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
2603 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) | 1991 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) |
2604 | return -EOPNOTSUPP; | 1992 | return -EOPNOTSUPP; |
2605 | 1993 | ||
2606 | if (!rdev->ops->start_ap) | ||
2607 | return -EOPNOTSUPP; | ||
2608 | |||
2609 | if (wdev->beacon_interval) | ||
2610 | return -EALREADY; | ||
2611 | |||
2612 | memset(¶ms, 0, sizeof(params)); | 1994 | memset(¶ms, 0, sizeof(params)); |
2613 | 1995 | ||
2614 | /* these are required for START_AP */ | 1996 | switch (info->genlhdr->cmd) { |
2615 | if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] || | 1997 | case NL80211_CMD_NEW_BEACON: |
2616 | !info->attrs[NL80211_ATTR_DTIM_PERIOD] || | 1998 | /* these are required for NEW_BEACON */ |
2617 | !info->attrs[NL80211_ATTR_BEACON_HEAD]) | 1999 | if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] || |
2618 | return -EINVAL; | 2000 | !info->attrs[NL80211_ATTR_DTIM_PERIOD] || |
2619 | 2001 | !info->attrs[NL80211_ATTR_BEACON_HEAD]) | |
2620 | err = nl80211_parse_beacon(info, ¶ms.beacon); | ||
2621 | if (err) | ||
2622 | return err; | ||
2623 | |||
2624 | params.beacon_interval = | ||
2625 | nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]); | ||
2626 | params.dtim_period = | ||
2627 | nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]); | ||
2628 | |||
2629 | err = cfg80211_validate_beacon_int(rdev, params.beacon_interval); | ||
2630 | if (err) | ||
2631 | return err; | ||
2632 | |||
2633 | /* | ||
2634 | * In theory, some of these attributes should be required here | ||
2635 | * but since they were not used when the command was originally | ||
2636 | * added, keep them optional for old user space programs to let | ||
2637 | * them continue to work with drivers that do not need the | ||
2638 | * additional information -- drivers must check! | ||
2639 | */ | ||
2640 | if (info->attrs[NL80211_ATTR_SSID]) { | ||
2641 | params.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); | ||
2642 | params.ssid_len = | ||
2643 | nla_len(info->attrs[NL80211_ATTR_SSID]); | ||
2644 | if (params.ssid_len == 0 || | ||
2645 | params.ssid_len > IEEE80211_MAX_SSID_LEN) | ||
2646 | return -EINVAL; | ||
2647 | } | ||
2648 | |||
2649 | if (info->attrs[NL80211_ATTR_HIDDEN_SSID]) { | ||
2650 | params.hidden_ssid = nla_get_u32( | ||
2651 | info->attrs[NL80211_ATTR_HIDDEN_SSID]); | ||
2652 | if (params.hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE && | ||
2653 | params.hidden_ssid != NL80211_HIDDEN_SSID_ZERO_LEN && | ||
2654 | params.hidden_ssid != NL80211_HIDDEN_SSID_ZERO_CONTENTS) | ||
2655 | return -EINVAL; | ||
2656 | } | ||
2657 | |||
2658 | params.privacy = !!info->attrs[NL80211_ATTR_PRIVACY]; | ||
2659 | |||
2660 | if (info->attrs[NL80211_ATTR_AUTH_TYPE]) { | ||
2661 | params.auth_type = nla_get_u32( | ||
2662 | info->attrs[NL80211_ATTR_AUTH_TYPE]); | ||
2663 | if (!nl80211_valid_auth_type(rdev, params.auth_type, | ||
2664 | NL80211_CMD_START_AP)) | ||
2665 | return -EINVAL; | 2002 | return -EINVAL; |
2666 | } else | ||
2667 | params.auth_type = NL80211_AUTHTYPE_AUTOMATIC; | ||
2668 | 2003 | ||
2669 | err = nl80211_crypto_settings(rdev, info, ¶ms.crypto, | 2004 | params.interval = |
2670 | NL80211_MAX_NR_CIPHER_SUITES); | 2005 | nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]); |
2671 | if (err) | 2006 | params.dtim_period = |
2672 | return err; | 2007 | nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]); |
2673 | 2008 | ||
2674 | if (info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]) { | 2009 | err = cfg80211_validate_beacon_int(rdev, params.interval); |
2675 | if (!(rdev->wiphy.features & NL80211_FEATURE_INACTIVITY_TIMER)) | 2010 | if (err) |
2676 | return -EOPNOTSUPP; | 2011 | return err; |
2677 | params.inactivity_timeout = nla_get_u16( | ||
2678 | info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]); | ||
2679 | } | ||
2680 | 2012 | ||
2681 | if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) { | 2013 | call = rdev->ops->add_beacon; |
2682 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) | 2014 | break; |
2683 | return -EINVAL; | 2015 | case NL80211_CMD_SET_BEACON: |
2684 | params.p2p_ctwindow = | 2016 | call = rdev->ops->set_beacon; |
2685 | nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]); | 2017 | break; |
2686 | if (params.p2p_ctwindow > 127) | 2018 | default: |
2687 | return -EINVAL; | 2019 | WARN_ON(1); |
2688 | if (params.p2p_ctwindow != 0 && | 2020 | return -EOPNOTSUPP; |
2689 | !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN)) | ||
2690 | return -EINVAL; | ||
2691 | } | 2021 | } |
2692 | 2022 | ||
2693 | if (info->attrs[NL80211_ATTR_P2P_OPPPS]) { | 2023 | if (!call) |
2694 | u8 tmp; | 2024 | return -EOPNOTSUPP; |
2695 | 2025 | ||
2696 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) | 2026 | if (info->attrs[NL80211_ATTR_BEACON_HEAD]) { |
2697 | return -EINVAL; | 2027 | params.head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]); |
2698 | tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]); | 2028 | params.head_len = |
2699 | if (tmp > 1) | 2029 | nla_len(info->attrs[NL80211_ATTR_BEACON_HEAD]); |
2700 | return -EINVAL; | 2030 | haveinfo = 1; |
2701 | params.p2p_opp_ps = tmp; | ||
2702 | if (params.p2p_opp_ps != 0 && | ||
2703 | !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS)) | ||
2704 | return -EINVAL; | ||
2705 | } | 2031 | } |
2706 | 2032 | ||
2707 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { | 2033 | if (info->attrs[NL80211_ATTR_BEACON_TAIL]) { |
2708 | err = nl80211_parse_chandef(rdev, info, ¶ms.chandef); | 2034 | params.tail = nla_data(info->attrs[NL80211_ATTR_BEACON_TAIL]); |
2709 | if (err) | 2035 | params.tail_len = |
2710 | return err; | 2036 | nla_len(info->attrs[NL80211_ATTR_BEACON_TAIL]); |
2711 | } else if (wdev->preset_chandef.chan) { | 2037 | haveinfo = 1; |
2712 | params.chandef = wdev->preset_chandef; | 2038 | } |
2713 | } else if (!nl80211_get_ap_channel(rdev, ¶ms)) | ||
2714 | return -EINVAL; | ||
2715 | 2039 | ||
2716 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef)) | 2040 | if (!haveinfo) |
2717 | return -EINVAL; | 2041 | return -EINVAL; |
2718 | 2042 | ||
2719 | mutex_lock(&rdev->devlist_mtx); | 2043 | err = call(&rdev->wiphy, dev, ¶ms); |
2720 | err = cfg80211_can_use_chan(rdev, wdev, params.chandef.chan, | 2044 | if (!err && params.interval) |
2721 | CHAN_MODE_SHARED); | 2045 | wdev->beacon_interval = params.interval; |
2722 | mutex_unlock(&rdev->devlist_mtx); | ||
2723 | |||
2724 | if (err) | ||
2725 | return err; | ||
2726 | |||
2727 | err = rdev_start_ap(rdev, dev, ¶ms); | ||
2728 | if (!err) { | ||
2729 | wdev->preset_chandef = params.chandef; | ||
2730 | wdev->beacon_interval = params.beacon_interval; | ||
2731 | wdev->channel = params.chandef.chan; | ||
2732 | wdev->ssid_len = params.ssid_len; | ||
2733 | memcpy(wdev->ssid, params.ssid, wdev->ssid_len); | ||
2734 | } | ||
2735 | return err; | 2046 | return err; |
2736 | } | 2047 | } |
2737 | 2048 | ||
2738 | static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info) | 2049 | static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info) |
2739 | { | 2050 | { |
2740 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 2051 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
2741 | struct net_device *dev = info->user_ptr[1]; | 2052 | struct net_device *dev = info->user_ptr[1]; |
2742 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 2053 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
2743 | struct cfg80211_beacon_data params; | ||
2744 | int err; | 2054 | int err; |
2745 | 2055 | ||
2746 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | 2056 | if (!rdev->ops->del_beacon) |
2747 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) | ||
2748 | return -EOPNOTSUPP; | 2057 | return -EOPNOTSUPP; |
2749 | 2058 | ||
2750 | if (!rdev->ops->change_beacon) | 2059 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
2060 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) | ||
2751 | return -EOPNOTSUPP; | 2061 | return -EOPNOTSUPP; |
2752 | 2062 | ||
2753 | if (!wdev->beacon_interval) | 2063 | err = rdev->ops->del_beacon(&rdev->wiphy, dev); |
2754 | return -EINVAL; | 2064 | if (!err) |
2755 | 2065 | wdev->beacon_interval = 0; | |
2756 | err = nl80211_parse_beacon(info, ¶ms); | 2066 | return err; |
2757 | if (err) | ||
2758 | return err; | ||
2759 | |||
2760 | return rdev_change_beacon(rdev, dev, ¶ms); | ||
2761 | } | ||
2762 | |||
2763 | static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info) | ||
2764 | { | ||
2765 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
2766 | struct net_device *dev = info->user_ptr[1]; | ||
2767 | |||
2768 | return cfg80211_stop_ap(rdev, dev); | ||
2769 | } | 2067 | } |
2770 | 2068 | ||
2771 | static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { | 2069 | static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { |
@@ -2774,11 +2072,9 @@ static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { | |||
2774 | [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG }, | 2072 | [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG }, |
2775 | [NL80211_STA_FLAG_MFP] = { .type = NLA_FLAG }, | 2073 | [NL80211_STA_FLAG_MFP] = { .type = NLA_FLAG }, |
2776 | [NL80211_STA_FLAG_AUTHENTICATED] = { .type = NLA_FLAG }, | 2074 | [NL80211_STA_FLAG_AUTHENTICATED] = { .type = NLA_FLAG }, |
2777 | [NL80211_STA_FLAG_TDLS_PEER] = { .type = NLA_FLAG }, | ||
2778 | }; | 2075 | }; |
2779 | 2076 | ||
2780 | static int parse_station_flags(struct genl_info *info, | 2077 | static int parse_station_flags(struct genl_info *info, |
2781 | enum nl80211_iftype iftype, | ||
2782 | struct station_parameters *params) | 2078 | struct station_parameters *params) |
2783 | { | 2079 | { |
2784 | struct nlattr *flags[NL80211_STA_FLAG_MAX + 1]; | 2080 | struct nlattr *flags[NL80211_STA_FLAG_MAX + 1]; |
@@ -2812,44 +2108,13 @@ static int parse_station_flags(struct genl_info *info, | |||
2812 | nla, sta_flags_policy)) | 2108 | nla, sta_flags_policy)) |
2813 | return -EINVAL; | 2109 | return -EINVAL; |
2814 | 2110 | ||
2815 | /* | 2111 | params->sta_flags_mask = (1 << __NL80211_STA_FLAG_AFTER_LAST) - 1; |
2816 | * Only allow certain flags for interface types so that | 2112 | params->sta_flags_mask &= ~1; |
2817 | * other attributes are silently ignored. Remember that | ||
2818 | * this is backward compatibility code with old userspace | ||
2819 | * and shouldn't be hit in other cases anyway. | ||
2820 | */ | ||
2821 | switch (iftype) { | ||
2822 | case NL80211_IFTYPE_AP: | ||
2823 | case NL80211_IFTYPE_AP_VLAN: | ||
2824 | case NL80211_IFTYPE_P2P_GO: | ||
2825 | params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHORIZED) | | ||
2826 | BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) | | ||
2827 | BIT(NL80211_STA_FLAG_WME) | | ||
2828 | BIT(NL80211_STA_FLAG_MFP); | ||
2829 | break; | ||
2830 | case NL80211_IFTYPE_P2P_CLIENT: | ||
2831 | case NL80211_IFTYPE_STATION: | ||
2832 | params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHORIZED) | | ||
2833 | BIT(NL80211_STA_FLAG_TDLS_PEER); | ||
2834 | break; | ||
2835 | case NL80211_IFTYPE_MESH_POINT: | ||
2836 | params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
2837 | BIT(NL80211_STA_FLAG_MFP) | | ||
2838 | BIT(NL80211_STA_FLAG_AUTHORIZED); | ||
2839 | default: | ||
2840 | return -EINVAL; | ||
2841 | } | ||
2842 | 2113 | ||
2843 | for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++) { | 2114 | for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++) |
2844 | if (flags[flag]) { | 2115 | if (flags[flag]) |
2845 | params->sta_flags_set |= (1<<flag); | 2116 | params->sta_flags_set |= (1<<flag); |
2846 | 2117 | ||
2847 | /* no longer support new API additions in old API */ | ||
2848 | if (flag > NL80211_STA_FLAG_MAX_OLD_API) | ||
2849 | return -EINVAL; | ||
2850 | } | ||
2851 | } | ||
2852 | |||
2853 | return 0; | 2118 | return 0; |
2854 | } | 2119 | } |
2855 | 2120 | ||
@@ -2857,120 +2122,77 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, | |||
2857 | int attr) | 2122 | int attr) |
2858 | { | 2123 | { |
2859 | struct nlattr *rate; | 2124 | struct nlattr *rate; |
2860 | u32 bitrate; | 2125 | u16 bitrate; |
2861 | u16 bitrate_compat; | ||
2862 | 2126 | ||
2863 | rate = nla_nest_start(msg, attr); | 2127 | rate = nla_nest_start(msg, attr); |
2864 | if (!rate) | 2128 | if (!rate) |
2865 | return false; | 2129 | goto nla_put_failure; |
2866 | 2130 | ||
2867 | /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */ | 2131 | /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */ |
2868 | bitrate = cfg80211_calculate_bitrate(info); | 2132 | bitrate = cfg80211_calculate_bitrate(info); |
2869 | /* report 16-bit bitrate only if we can */ | 2133 | if (bitrate > 0) |
2870 | bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0; | 2134 | NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate); |
2871 | if (bitrate > 0 && | 2135 | |
2872 | nla_put_u32(msg, NL80211_RATE_INFO_BITRATE32, bitrate)) | 2136 | if (info->flags & RATE_INFO_FLAGS_MCS) |
2873 | return false; | 2137 | NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS, info->mcs); |
2874 | if (bitrate_compat > 0 && | 2138 | if (info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) |
2875 | nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate_compat)) | 2139 | NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH); |
2876 | return false; | 2140 | if (info->flags & RATE_INFO_FLAGS_SHORT_GI) |
2877 | 2141 | NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI); | |
2878 | if (info->flags & RATE_INFO_FLAGS_MCS) { | ||
2879 | if (nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs)) | ||
2880 | return false; | ||
2881 | if (info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH && | ||
2882 | nla_put_flag(msg, NL80211_RATE_INFO_40_MHZ_WIDTH)) | ||
2883 | return false; | ||
2884 | if (info->flags & RATE_INFO_FLAGS_SHORT_GI && | ||
2885 | nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI)) | ||
2886 | return false; | ||
2887 | } else if (info->flags & RATE_INFO_FLAGS_VHT_MCS) { | ||
2888 | if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_MCS, info->mcs)) | ||
2889 | return false; | ||
2890 | if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_NSS, info->nss)) | ||
2891 | return false; | ||
2892 | if (info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH && | ||
2893 | nla_put_flag(msg, NL80211_RATE_INFO_40_MHZ_WIDTH)) | ||
2894 | return false; | ||
2895 | if (info->flags & RATE_INFO_FLAGS_80_MHZ_WIDTH && | ||
2896 | nla_put_flag(msg, NL80211_RATE_INFO_80_MHZ_WIDTH)) | ||
2897 | return false; | ||
2898 | if (info->flags & RATE_INFO_FLAGS_80P80_MHZ_WIDTH && | ||
2899 | nla_put_flag(msg, NL80211_RATE_INFO_80P80_MHZ_WIDTH)) | ||
2900 | return false; | ||
2901 | if (info->flags & RATE_INFO_FLAGS_160_MHZ_WIDTH && | ||
2902 | nla_put_flag(msg, NL80211_RATE_INFO_160_MHZ_WIDTH)) | ||
2903 | return false; | ||
2904 | if (info->flags & RATE_INFO_FLAGS_SHORT_GI && | ||
2905 | nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI)) | ||
2906 | return false; | ||
2907 | } | ||
2908 | 2142 | ||
2909 | nla_nest_end(msg, rate); | 2143 | nla_nest_end(msg, rate); |
2910 | return true; | 2144 | return true; |
2145 | |||
2146 | nla_put_failure: | ||
2147 | return false; | ||
2911 | } | 2148 | } |
2912 | 2149 | ||
2913 | static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq, | 2150 | static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, |
2914 | int flags, | 2151 | int flags, struct net_device *dev, |
2915 | struct cfg80211_registered_device *rdev, | ||
2916 | struct net_device *dev, | ||
2917 | const u8 *mac_addr, struct station_info *sinfo) | 2152 | const u8 *mac_addr, struct station_info *sinfo) |
2918 | { | 2153 | { |
2919 | void *hdr; | 2154 | void *hdr; |
2920 | struct nlattr *sinfoattr, *bss_param; | 2155 | struct nlattr *sinfoattr, *bss_param; |
2921 | 2156 | ||
2922 | hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_STATION); | 2157 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION); |
2923 | if (!hdr) | 2158 | if (!hdr) |
2924 | return -1; | 2159 | return -1; |
2925 | 2160 | ||
2926 | if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || | 2161 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); |
2927 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr) || | 2162 | NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); |
2928 | nla_put_u32(msg, NL80211_ATTR_GENERATION, sinfo->generation)) | 2163 | |
2929 | goto nla_put_failure; | 2164 | NLA_PUT_U32(msg, NL80211_ATTR_GENERATION, sinfo->generation); |
2930 | 2165 | ||
2931 | sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO); | 2166 | sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO); |
2932 | if (!sinfoattr) | 2167 | if (!sinfoattr) |
2933 | goto nla_put_failure; | 2168 | goto nla_put_failure; |
2934 | if ((sinfo->filled & STATION_INFO_CONNECTED_TIME) && | 2169 | if (sinfo->filled & STATION_INFO_CONNECTED_TIME) |
2935 | nla_put_u32(msg, NL80211_STA_INFO_CONNECTED_TIME, | 2170 | NLA_PUT_U32(msg, NL80211_STA_INFO_CONNECTED_TIME, |
2936 | sinfo->connected_time)) | 2171 | sinfo->connected_time); |
2937 | goto nla_put_failure; | 2172 | if (sinfo->filled & STATION_INFO_INACTIVE_TIME) |
2938 | if ((sinfo->filled & STATION_INFO_INACTIVE_TIME) && | 2173 | NLA_PUT_U32(msg, NL80211_STA_INFO_INACTIVE_TIME, |
2939 | nla_put_u32(msg, NL80211_STA_INFO_INACTIVE_TIME, | 2174 | sinfo->inactive_time); |
2940 | sinfo->inactive_time)) | 2175 | if (sinfo->filled & STATION_INFO_RX_BYTES) |
2941 | goto nla_put_failure; | 2176 | NLA_PUT_U32(msg, NL80211_STA_INFO_RX_BYTES, |
2942 | if ((sinfo->filled & STATION_INFO_RX_BYTES) && | 2177 | sinfo->rx_bytes); |
2943 | nla_put_u32(msg, NL80211_STA_INFO_RX_BYTES, | 2178 | if (sinfo->filled & STATION_INFO_TX_BYTES) |
2944 | sinfo->rx_bytes)) | 2179 | NLA_PUT_U32(msg, NL80211_STA_INFO_TX_BYTES, |
2945 | goto nla_put_failure; | 2180 | sinfo->tx_bytes); |
2946 | if ((sinfo->filled & STATION_INFO_TX_BYTES) && | 2181 | if (sinfo->filled & STATION_INFO_LLID) |
2947 | nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES, | 2182 | NLA_PUT_U16(msg, NL80211_STA_INFO_LLID, |
2948 | sinfo->tx_bytes)) | 2183 | sinfo->llid); |
2949 | goto nla_put_failure; | 2184 | if (sinfo->filled & STATION_INFO_PLID) |
2950 | if ((sinfo->filled & STATION_INFO_LLID) && | 2185 | NLA_PUT_U16(msg, NL80211_STA_INFO_PLID, |
2951 | nla_put_u16(msg, NL80211_STA_INFO_LLID, sinfo->llid)) | 2186 | sinfo->plid); |
2952 | goto nla_put_failure; | 2187 | if (sinfo->filled & STATION_INFO_PLINK_STATE) |
2953 | if ((sinfo->filled & STATION_INFO_PLID) && | 2188 | NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE, |
2954 | nla_put_u16(msg, NL80211_STA_INFO_PLID, sinfo->plid)) | 2189 | sinfo->plink_state); |
2955 | goto nla_put_failure; | 2190 | if (sinfo->filled & STATION_INFO_SIGNAL) |
2956 | if ((sinfo->filled & STATION_INFO_PLINK_STATE) && | 2191 | NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL, |
2957 | nla_put_u8(msg, NL80211_STA_INFO_PLINK_STATE, | 2192 | sinfo->signal); |
2958 | sinfo->plink_state)) | 2193 | if (sinfo->filled & STATION_INFO_SIGNAL_AVG) |
2959 | goto nla_put_failure; | 2194 | NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL_AVG, |
2960 | switch (rdev->wiphy.signal_type) { | 2195 | sinfo->signal_avg); |
2961 | case CFG80211_SIGNAL_TYPE_MBM: | ||
2962 | if ((sinfo->filled & STATION_INFO_SIGNAL) && | ||
2963 | nla_put_u8(msg, NL80211_STA_INFO_SIGNAL, | ||
2964 | sinfo->signal)) | ||
2965 | goto nla_put_failure; | ||
2966 | if ((sinfo->filled & STATION_INFO_SIGNAL_AVG) && | ||
2967 | nla_put_u8(msg, NL80211_STA_INFO_SIGNAL_AVG, | ||
2968 | sinfo->signal_avg)) | ||
2969 | goto nla_put_failure; | ||
2970 | break; | ||
2971 | default: | ||
2972 | break; | ||
2973 | } | ||
2974 | if (sinfo->filled & STATION_INFO_TX_BITRATE) { | 2196 | if (sinfo->filled & STATION_INFO_TX_BITRATE) { |
2975 | if (!nl80211_put_sta_rate(msg, &sinfo->txrate, | 2197 | if (!nl80211_put_sta_rate(msg, &sinfo->txrate, |
2976 | NL80211_STA_INFO_TX_BITRATE)) | 2198 | NL80211_STA_INFO_TX_BITRATE)) |
@@ -2981,60 +2203,42 @@ static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq, | |||
2981 | NL80211_STA_INFO_RX_BITRATE)) | 2203 | NL80211_STA_INFO_RX_BITRATE)) |
2982 | goto nla_put_failure; | 2204 | goto nla_put_failure; |
2983 | } | 2205 | } |
2984 | if ((sinfo->filled & STATION_INFO_RX_PACKETS) && | 2206 | if (sinfo->filled & STATION_INFO_RX_PACKETS) |
2985 | nla_put_u32(msg, NL80211_STA_INFO_RX_PACKETS, | 2207 | NLA_PUT_U32(msg, NL80211_STA_INFO_RX_PACKETS, |
2986 | sinfo->rx_packets)) | 2208 | sinfo->rx_packets); |
2987 | goto nla_put_failure; | 2209 | if (sinfo->filled & STATION_INFO_TX_PACKETS) |
2988 | if ((sinfo->filled & STATION_INFO_TX_PACKETS) && | 2210 | NLA_PUT_U32(msg, NL80211_STA_INFO_TX_PACKETS, |
2989 | nla_put_u32(msg, NL80211_STA_INFO_TX_PACKETS, | 2211 | sinfo->tx_packets); |
2990 | sinfo->tx_packets)) | 2212 | if (sinfo->filled & STATION_INFO_TX_RETRIES) |
2991 | goto nla_put_failure; | 2213 | NLA_PUT_U32(msg, NL80211_STA_INFO_TX_RETRIES, |
2992 | if ((sinfo->filled & STATION_INFO_TX_RETRIES) && | 2214 | sinfo->tx_retries); |
2993 | nla_put_u32(msg, NL80211_STA_INFO_TX_RETRIES, | 2215 | if (sinfo->filled & STATION_INFO_TX_FAILED) |
2994 | sinfo->tx_retries)) | 2216 | NLA_PUT_U32(msg, NL80211_STA_INFO_TX_FAILED, |
2995 | goto nla_put_failure; | 2217 | sinfo->tx_failed); |
2996 | if ((sinfo->filled & STATION_INFO_TX_FAILED) && | ||
2997 | nla_put_u32(msg, NL80211_STA_INFO_TX_FAILED, | ||
2998 | sinfo->tx_failed)) | ||
2999 | goto nla_put_failure; | ||
3000 | if ((sinfo->filled & STATION_INFO_BEACON_LOSS_COUNT) && | ||
3001 | nla_put_u32(msg, NL80211_STA_INFO_BEACON_LOSS, | ||
3002 | sinfo->beacon_loss_count)) | ||
3003 | goto nla_put_failure; | ||
3004 | if (sinfo->filled & STATION_INFO_BSS_PARAM) { | 2218 | if (sinfo->filled & STATION_INFO_BSS_PARAM) { |
3005 | bss_param = nla_nest_start(msg, NL80211_STA_INFO_BSS_PARAM); | 2219 | bss_param = nla_nest_start(msg, NL80211_STA_INFO_BSS_PARAM); |
3006 | if (!bss_param) | 2220 | if (!bss_param) |
3007 | goto nla_put_failure; | 2221 | goto nla_put_failure; |
3008 | 2222 | ||
3009 | if (((sinfo->bss_param.flags & BSS_PARAM_FLAGS_CTS_PROT) && | 2223 | if (sinfo->bss_param.flags & BSS_PARAM_FLAGS_CTS_PROT) |
3010 | nla_put_flag(msg, NL80211_STA_BSS_PARAM_CTS_PROT)) || | 2224 | NLA_PUT_FLAG(msg, NL80211_STA_BSS_PARAM_CTS_PROT); |
3011 | ((sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_PREAMBLE) && | 2225 | if (sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_PREAMBLE) |
3012 | nla_put_flag(msg, NL80211_STA_BSS_PARAM_SHORT_PREAMBLE)) || | 2226 | NLA_PUT_FLAG(msg, NL80211_STA_BSS_PARAM_SHORT_PREAMBLE); |
3013 | ((sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_SLOT_TIME) && | 2227 | if (sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_SLOT_TIME) |
3014 | nla_put_flag(msg, NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME)) || | 2228 | NLA_PUT_FLAG(msg, |
3015 | nla_put_u8(msg, NL80211_STA_BSS_PARAM_DTIM_PERIOD, | 2229 | NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME); |
3016 | sinfo->bss_param.dtim_period) || | 2230 | NLA_PUT_U8(msg, NL80211_STA_BSS_PARAM_DTIM_PERIOD, |
3017 | nla_put_u16(msg, NL80211_STA_BSS_PARAM_BEACON_INTERVAL, | 2231 | sinfo->bss_param.dtim_period); |
3018 | sinfo->bss_param.beacon_interval)) | 2232 | NLA_PUT_U16(msg, NL80211_STA_BSS_PARAM_BEACON_INTERVAL, |
3019 | goto nla_put_failure; | 2233 | sinfo->bss_param.beacon_interval); |
3020 | 2234 | ||
3021 | nla_nest_end(msg, bss_param); | 2235 | nla_nest_end(msg, bss_param); |
3022 | } | 2236 | } |
3023 | if ((sinfo->filled & STATION_INFO_STA_FLAGS) && | ||
3024 | nla_put(msg, NL80211_STA_INFO_STA_FLAGS, | ||
3025 | sizeof(struct nl80211_sta_flag_update), | ||
3026 | &sinfo->sta_flags)) | ||
3027 | goto nla_put_failure; | ||
3028 | if ((sinfo->filled & STATION_INFO_T_OFFSET) && | ||
3029 | nla_put_u64(msg, NL80211_STA_INFO_T_OFFSET, | ||
3030 | sinfo->t_offset)) | ||
3031 | goto nla_put_failure; | ||
3032 | nla_nest_end(msg, sinfoattr); | 2237 | nla_nest_end(msg, sinfoattr); |
3033 | 2238 | ||
3034 | if ((sinfo->filled & STATION_INFO_ASSOC_REQ_IES) && | 2239 | if (sinfo->assoc_req_ies) |
3035 | nla_put(msg, NL80211_ATTR_IE, sinfo->assoc_req_ies_len, | 2240 | NLA_PUT(msg, NL80211_ATTR_IE, sinfo->assoc_req_ies_len, |
3036 | sinfo->assoc_req_ies)) | 2241 | sinfo->assoc_req_ies); |
3037 | goto nla_put_failure; | ||
3038 | 2242 | ||
3039 | return genlmsg_end(msg, hdr); | 2243 | return genlmsg_end(msg, hdr); |
3040 | 2244 | ||
@@ -3064,17 +2268,17 @@ static int nl80211_dump_station(struct sk_buff *skb, | |||
3064 | 2268 | ||
3065 | while (1) { | 2269 | while (1) { |
3066 | memset(&sinfo, 0, sizeof(sinfo)); | 2270 | memset(&sinfo, 0, sizeof(sinfo)); |
3067 | err = rdev_dump_station(dev, netdev, sta_idx, | 2271 | err = dev->ops->dump_station(&dev->wiphy, netdev, sta_idx, |
3068 | mac_addr, &sinfo); | 2272 | mac_addr, &sinfo); |
3069 | if (err == -ENOENT) | 2273 | if (err == -ENOENT) |
3070 | break; | 2274 | break; |
3071 | if (err) | 2275 | if (err) |
3072 | goto out_err; | 2276 | goto out_err; |
3073 | 2277 | ||
3074 | if (nl80211_send_station(skb, | 2278 | if (nl80211_send_station(skb, |
3075 | NETLINK_CB(cb->skb).portid, | 2279 | NETLINK_CB(cb->skb).pid, |
3076 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 2280 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
3077 | dev, netdev, mac_addr, | 2281 | netdev, mac_addr, |
3078 | &sinfo) < 0) | 2282 | &sinfo) < 0) |
3079 | goto out; | 2283 | goto out; |
3080 | 2284 | ||
@@ -3110,7 +2314,7 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info) | |||
3110 | if (!rdev->ops->get_station) | 2314 | if (!rdev->ops->get_station) |
3111 | return -EOPNOTSUPP; | 2315 | return -EOPNOTSUPP; |
3112 | 2316 | ||
3113 | err = rdev_get_station(rdev, dev, mac_addr, &sinfo); | 2317 | err = rdev->ops->get_station(&rdev->wiphy, dev, mac_addr, &sinfo); |
3114 | if (err) | 2318 | if (err) |
3115 | return err; | 2319 | return err; |
3116 | 2320 | ||
@@ -3118,8 +2322,8 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info) | |||
3118 | if (!msg) | 2322 | if (!msg) |
3119 | return -ENOMEM; | 2323 | return -ENOMEM; |
3120 | 2324 | ||
3121 | if (nl80211_send_station(msg, info->snd_portid, info->snd_seq, 0, | 2325 | if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0, |
3122 | rdev, dev, mac_addr, &sinfo) < 0) { | 2326 | dev, mac_addr, &sinfo) < 0) { |
3123 | nlmsg_free(msg); | 2327 | nlmsg_free(msg); |
3124 | return -ENOBUFS; | 2328 | return -ENOBUFS; |
3125 | } | 2329 | } |
@@ -3130,34 +2334,26 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info) | |||
3130 | /* | 2334 | /* |
3131 | * Get vlan interface making sure it is running and on the right wiphy. | 2335 | * Get vlan interface making sure it is running and on the right wiphy. |
3132 | */ | 2336 | */ |
3133 | static struct net_device *get_vlan(struct genl_info *info, | 2337 | static int get_vlan(struct genl_info *info, |
3134 | struct cfg80211_registered_device *rdev) | 2338 | struct cfg80211_registered_device *rdev, |
2339 | struct net_device **vlan) | ||
3135 | { | 2340 | { |
3136 | struct nlattr *vlanattr = info->attrs[NL80211_ATTR_STA_VLAN]; | 2341 | struct nlattr *vlanattr = info->attrs[NL80211_ATTR_STA_VLAN]; |
3137 | struct net_device *v; | 2342 | *vlan = NULL; |
3138 | int ret; | 2343 | |
3139 | 2344 | if (vlanattr) { | |
3140 | if (!vlanattr) | 2345 | *vlan = dev_get_by_index(genl_info_net(info), |
3141 | return NULL; | 2346 | nla_get_u32(vlanattr)); |
3142 | 2347 | if (!*vlan) | |
3143 | v = dev_get_by_index(genl_info_net(info), nla_get_u32(vlanattr)); | 2348 | return -ENODEV; |
3144 | if (!v) | 2349 | if (!(*vlan)->ieee80211_ptr) |
3145 | return ERR_PTR(-ENODEV); | 2350 | return -EINVAL; |
3146 | 2351 | if ((*vlan)->ieee80211_ptr->wiphy != &rdev->wiphy) | |
3147 | if (!v->ieee80211_ptr || v->ieee80211_ptr->wiphy != &rdev->wiphy) { | 2352 | return -EINVAL; |
3148 | ret = -EINVAL; | 2353 | if (!netif_running(*vlan)) |
3149 | goto error; | 2354 | return -ENETDOWN; |
3150 | } | ||
3151 | |||
3152 | if (!netif_running(v)) { | ||
3153 | ret = -ENETDOWN; | ||
3154 | goto error; | ||
3155 | } | 2355 | } |
3156 | 2356 | return 0; | |
3157 | return v; | ||
3158 | error: | ||
3159 | dev_put(v); | ||
3160 | return ERR_PTR(ret); | ||
3161 | } | 2357 | } |
3162 | 2358 | ||
3163 | static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | 2359 | static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) |
@@ -3196,10 +2392,7 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
3196 | params.ht_capa = | 2392 | params.ht_capa = |
3197 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); | 2393 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); |
3198 | 2394 | ||
3199 | if (!rdev->ops->change_station) | 2395 | if (parse_station_flags(info, ¶ms)) |
3200 | return -EOPNOTSUPP; | ||
3201 | |||
3202 | if (parse_station_flags(info, dev->ieee80211_ptr->iftype, ¶ms)) | ||
3203 | return -EINVAL; | 2396 | return -EINVAL; |
3204 | 2397 | ||
3205 | if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) | 2398 | if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) |
@@ -3210,97 +2403,72 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
3210 | params.plink_state = | 2403 | params.plink_state = |
3211 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]); | 2404 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]); |
3212 | 2405 | ||
2406 | err = get_vlan(info, rdev, ¶ms.vlan); | ||
2407 | if (err) | ||
2408 | goto out; | ||
2409 | |||
2410 | /* validate settings */ | ||
2411 | err = 0; | ||
2412 | |||
3213 | switch (dev->ieee80211_ptr->iftype) { | 2413 | switch (dev->ieee80211_ptr->iftype) { |
3214 | case NL80211_IFTYPE_AP: | 2414 | case NL80211_IFTYPE_AP: |
3215 | case NL80211_IFTYPE_AP_VLAN: | 2415 | case NL80211_IFTYPE_AP_VLAN: |
3216 | case NL80211_IFTYPE_P2P_GO: | 2416 | case NL80211_IFTYPE_P2P_GO: |
3217 | /* disallow mesh-specific things */ | 2417 | /* disallow mesh-specific things */ |
3218 | if (params.plink_action) | 2418 | if (params.plink_action) |
3219 | return -EINVAL; | 2419 | err = -EINVAL; |
3220 | |||
3221 | /* TDLS can't be set, ... */ | ||
3222 | if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) | ||
3223 | return -EINVAL; | ||
3224 | /* | ||
3225 | * ... but don't bother the driver with it. This works around | ||
3226 | * a hostapd/wpa_supplicant issue -- it always includes the | ||
3227 | * TLDS_PEER flag in the mask even for AP mode. | ||
3228 | */ | ||
3229 | params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); | ||
3230 | |||
3231 | /* accept only the listed bits */ | ||
3232 | if (params.sta_flags_mask & | ||
3233 | ~(BIT(NL80211_STA_FLAG_AUTHORIZED) | | ||
3234 | BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) | | ||
3235 | BIT(NL80211_STA_FLAG_WME) | | ||
3236 | BIT(NL80211_STA_FLAG_MFP))) | ||
3237 | return -EINVAL; | ||
3238 | |||
3239 | /* must be last in here for error handling */ | ||
3240 | params.vlan = get_vlan(info, rdev); | ||
3241 | if (IS_ERR(params.vlan)) | ||
3242 | return PTR_ERR(params.vlan); | ||
3243 | break; | 2420 | break; |
3244 | case NL80211_IFTYPE_P2P_CLIENT: | 2421 | case NL80211_IFTYPE_P2P_CLIENT: |
3245 | case NL80211_IFTYPE_STATION: | 2422 | case NL80211_IFTYPE_STATION: |
3246 | /* | 2423 | /* disallow everything but AUTHORIZED flag */ |
3247 | * Don't allow userspace to change the TDLS_PEER flag, | ||
3248 | * but silently ignore attempts to change it since we | ||
3249 | * don't have state here to verify that it doesn't try | ||
3250 | * to change the flag. | ||
3251 | */ | ||
3252 | params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); | ||
3253 | /* fall through */ | ||
3254 | case NL80211_IFTYPE_ADHOC: | ||
3255 | /* disallow things sta doesn't support */ | ||
3256 | if (params.plink_action) | 2424 | if (params.plink_action) |
3257 | return -EINVAL; | 2425 | err = -EINVAL; |
2426 | if (params.vlan) | ||
2427 | err = -EINVAL; | ||
2428 | if (params.supported_rates) | ||
2429 | err = -EINVAL; | ||
3258 | if (params.ht_capa) | 2430 | if (params.ht_capa) |
3259 | return -EINVAL; | 2431 | err = -EINVAL; |
3260 | if (params.listen_interval >= 0) | 2432 | if (params.listen_interval >= 0) |
3261 | return -EINVAL; | 2433 | err = -EINVAL; |
3262 | /* reject any changes other than AUTHORIZED */ | ||
3263 | if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED)) | 2434 | if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED)) |
3264 | return -EINVAL; | 2435 | err = -EINVAL; |
3265 | break; | 2436 | break; |
3266 | case NL80211_IFTYPE_MESH_POINT: | 2437 | case NL80211_IFTYPE_MESH_POINT: |
3267 | /* disallow things mesh doesn't support */ | 2438 | /* disallow things mesh doesn't support */ |
3268 | if (params.vlan) | 2439 | if (params.vlan) |
3269 | return -EINVAL; | 2440 | err = -EINVAL; |
3270 | if (params.ht_capa) | 2441 | if (params.ht_capa) |
3271 | return -EINVAL; | 2442 | err = -EINVAL; |
3272 | if (params.listen_interval >= 0) | 2443 | if (params.listen_interval >= 0) |
3273 | return -EINVAL; | 2444 | err = -EINVAL; |
3274 | /* | ||
3275 | * No special handling for TDLS here -- the userspace | ||
3276 | * mesh code doesn't have this bug. | ||
3277 | */ | ||
3278 | if (params.sta_flags_mask & | 2445 | if (params.sta_flags_mask & |
3279 | ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) | | 2446 | ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) | |
3280 | BIT(NL80211_STA_FLAG_MFP) | | 2447 | BIT(NL80211_STA_FLAG_MFP) | |
3281 | BIT(NL80211_STA_FLAG_AUTHORIZED))) | 2448 | BIT(NL80211_STA_FLAG_AUTHORIZED))) |
3282 | return -EINVAL; | 2449 | err = -EINVAL; |
3283 | break; | 2450 | break; |
3284 | default: | 2451 | default: |
3285 | return -EOPNOTSUPP; | 2452 | err = -EINVAL; |
3286 | } | 2453 | } |
3287 | 2454 | ||
3288 | /* be aware of params.vlan when changing code here */ | 2455 | if (err) |
2456 | goto out; | ||
2457 | |||
2458 | if (!rdev->ops->change_station) { | ||
2459 | err = -EOPNOTSUPP; | ||
2460 | goto out; | ||
2461 | } | ||
3289 | 2462 | ||
3290 | err = rdev_change_station(rdev, dev, mac_addr, ¶ms); | 2463 | err = rdev->ops->change_station(&rdev->wiphy, dev, mac_addr, ¶ms); |
3291 | 2464 | ||
2465 | out: | ||
3292 | if (params.vlan) | 2466 | if (params.vlan) |
3293 | dev_put(params.vlan); | 2467 | dev_put(params.vlan); |
3294 | 2468 | ||
3295 | return err; | 2469 | return err; |
3296 | } | 2470 | } |
3297 | 2471 | ||
3298 | static struct nla_policy | ||
3299 | nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] __read_mostly = { | ||
3300 | [NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 }, | ||
3301 | [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 }, | ||
3302 | }; | ||
3303 | |||
3304 | static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | 2472 | static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) |
3305 | { | 2473 | { |
3306 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 2474 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
@@ -3339,89 +2507,34 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
3339 | params.ht_capa = | 2507 | params.ht_capa = |
3340 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); | 2508 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); |
3341 | 2509 | ||
3342 | if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) | ||
3343 | params.vht_capa = | ||
3344 | nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]); | ||
3345 | |||
3346 | if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) | 2510 | if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) |
3347 | params.plink_action = | 2511 | params.plink_action = |
3348 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); | 2512 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); |
3349 | 2513 | ||
3350 | if (!rdev->ops->add_station) | 2514 | if (parse_station_flags(info, ¶ms)) |
3351 | return -EOPNOTSUPP; | ||
3352 | |||
3353 | if (parse_station_flags(info, dev->ieee80211_ptr->iftype, ¶ms)) | ||
3354 | return -EINVAL; | 2515 | return -EINVAL; |
3355 | 2516 | ||
3356 | switch (dev->ieee80211_ptr->iftype) { | 2517 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
3357 | case NL80211_IFTYPE_AP: | 2518 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && |
3358 | case NL80211_IFTYPE_AP_VLAN: | 2519 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT && |
3359 | case NL80211_IFTYPE_P2P_GO: | 2520 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) |
3360 | /* parse WME attributes if sta is WME capable */ | 2521 | return -EINVAL; |
3361 | if ((rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) && | ||
3362 | (params.sta_flags_set & BIT(NL80211_STA_FLAG_WME)) && | ||
3363 | info->attrs[NL80211_ATTR_STA_WME]) { | ||
3364 | struct nlattr *tb[NL80211_STA_WME_MAX + 1]; | ||
3365 | struct nlattr *nla; | ||
3366 | |||
3367 | nla = info->attrs[NL80211_ATTR_STA_WME]; | ||
3368 | err = nla_parse_nested(tb, NL80211_STA_WME_MAX, nla, | ||
3369 | nl80211_sta_wme_policy); | ||
3370 | if (err) | ||
3371 | return err; | ||
3372 | |||
3373 | if (tb[NL80211_STA_WME_UAPSD_QUEUES]) | ||
3374 | params.uapsd_queues = | ||
3375 | nla_get_u8(tb[NL80211_STA_WME_UAPSD_QUEUES]); | ||
3376 | if (params.uapsd_queues & | ||
3377 | ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) | ||
3378 | return -EINVAL; | ||
3379 | |||
3380 | if (tb[NL80211_STA_WME_MAX_SP]) | ||
3381 | params.max_sp = | ||
3382 | nla_get_u8(tb[NL80211_STA_WME_MAX_SP]); | ||
3383 | 2522 | ||
3384 | if (params.max_sp & | 2523 | err = get_vlan(info, rdev, ¶ms.vlan); |
3385 | ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK) | 2524 | if (err) |
3386 | return -EINVAL; | 2525 | goto out; |
3387 | 2526 | ||
3388 | params.sta_modify_mask |= STATION_PARAM_APPLY_UAPSD; | 2527 | /* validate settings */ |
3389 | } | 2528 | err = 0; |
3390 | /* TDLS peers cannot be added */ | ||
3391 | if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) | ||
3392 | return -EINVAL; | ||
3393 | /* but don't bother the driver with it */ | ||
3394 | params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); | ||
3395 | 2529 | ||
3396 | /* must be last in here for error handling */ | 2530 | if (!rdev->ops->add_station) { |
3397 | params.vlan = get_vlan(info, rdev); | 2531 | err = -EOPNOTSUPP; |
3398 | if (IS_ERR(params.vlan)) | 2532 | goto out; |
3399 | return PTR_ERR(params.vlan); | ||
3400 | break; | ||
3401 | case NL80211_IFTYPE_MESH_POINT: | ||
3402 | /* TDLS peers cannot be added */ | ||
3403 | if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) | ||
3404 | return -EINVAL; | ||
3405 | break; | ||
3406 | case NL80211_IFTYPE_STATION: | ||
3407 | /* Only TDLS peers can be added */ | ||
3408 | if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) | ||
3409 | return -EINVAL; | ||
3410 | /* Can only add if TDLS ... */ | ||
3411 | if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS)) | ||
3412 | return -EOPNOTSUPP; | ||
3413 | /* ... with external setup is supported */ | ||
3414 | if (!(rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP)) | ||
3415 | return -EOPNOTSUPP; | ||
3416 | break; | ||
3417 | default: | ||
3418 | return -EOPNOTSUPP; | ||
3419 | } | 2533 | } |
3420 | 2534 | ||
3421 | /* be aware of params.vlan when changing code here */ | 2535 | err = rdev->ops->add_station(&rdev->wiphy, dev, mac_addr, ¶ms); |
3422 | |||
3423 | err = rdev_add_station(rdev, dev, mac_addr, ¶ms); | ||
3424 | 2536 | ||
2537 | out: | ||
3425 | if (params.vlan) | 2538 | if (params.vlan) |
3426 | dev_put(params.vlan); | 2539 | dev_put(params.vlan); |
3427 | return err; | 2540 | return err; |
@@ -3445,10 +2558,10 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info) | |||
3445 | if (!rdev->ops->del_station) | 2558 | if (!rdev->ops->del_station) |
3446 | return -EOPNOTSUPP; | 2559 | return -EOPNOTSUPP; |
3447 | 2560 | ||
3448 | return rdev_del_station(rdev, dev, mac_addr); | 2561 | return rdev->ops->del_station(&rdev->wiphy, dev, mac_addr); |
3449 | } | 2562 | } |
3450 | 2563 | ||
3451 | static int nl80211_send_mpath(struct sk_buff *msg, u32 portid, u32 seq, | 2564 | static int nl80211_send_mpath(struct sk_buff *msg, u32 pid, u32 seq, |
3452 | int flags, struct net_device *dev, | 2565 | int flags, struct net_device *dev, |
3453 | u8 *dst, u8 *next_hop, | 2566 | u8 *dst, u8 *next_hop, |
3454 | struct mpath_info *pinfo) | 2567 | struct mpath_info *pinfo) |
@@ -3456,41 +2569,40 @@ static int nl80211_send_mpath(struct sk_buff *msg, u32 portid, u32 seq, | |||
3456 | void *hdr; | 2569 | void *hdr; |
3457 | struct nlattr *pinfoattr; | 2570 | struct nlattr *pinfoattr; |
3458 | 2571 | ||
3459 | hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_STATION); | 2572 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION); |
3460 | if (!hdr) | 2573 | if (!hdr) |
3461 | return -1; | 2574 | return -1; |
3462 | 2575 | ||
3463 | if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || | 2576 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); |
3464 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, dst) || | 2577 | NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst); |
3465 | nla_put(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop) || | 2578 | NLA_PUT(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop); |
3466 | nla_put_u32(msg, NL80211_ATTR_GENERATION, pinfo->generation)) | 2579 | |
3467 | goto nla_put_failure; | 2580 | NLA_PUT_U32(msg, NL80211_ATTR_GENERATION, pinfo->generation); |
3468 | 2581 | ||
3469 | pinfoattr = nla_nest_start(msg, NL80211_ATTR_MPATH_INFO); | 2582 | pinfoattr = nla_nest_start(msg, NL80211_ATTR_MPATH_INFO); |
3470 | if (!pinfoattr) | 2583 | if (!pinfoattr) |
3471 | goto nla_put_failure; | 2584 | goto nla_put_failure; |
3472 | if ((pinfo->filled & MPATH_INFO_FRAME_QLEN) && | 2585 | if (pinfo->filled & MPATH_INFO_FRAME_QLEN) |
3473 | nla_put_u32(msg, NL80211_MPATH_INFO_FRAME_QLEN, | 2586 | NLA_PUT_U32(msg, NL80211_MPATH_INFO_FRAME_QLEN, |
3474 | pinfo->frame_qlen)) | 2587 | pinfo->frame_qlen); |
3475 | goto nla_put_failure; | 2588 | if (pinfo->filled & MPATH_INFO_SN) |
3476 | if (((pinfo->filled & MPATH_INFO_SN) && | 2589 | NLA_PUT_U32(msg, NL80211_MPATH_INFO_SN, |
3477 | nla_put_u32(msg, NL80211_MPATH_INFO_SN, pinfo->sn)) || | 2590 | pinfo->sn); |
3478 | ((pinfo->filled & MPATH_INFO_METRIC) && | 2591 | if (pinfo->filled & MPATH_INFO_METRIC) |
3479 | nla_put_u32(msg, NL80211_MPATH_INFO_METRIC, | 2592 | NLA_PUT_U32(msg, NL80211_MPATH_INFO_METRIC, |
3480 | pinfo->metric)) || | 2593 | pinfo->metric); |
3481 | ((pinfo->filled & MPATH_INFO_EXPTIME) && | 2594 | if (pinfo->filled & MPATH_INFO_EXPTIME) |
3482 | nla_put_u32(msg, NL80211_MPATH_INFO_EXPTIME, | 2595 | NLA_PUT_U32(msg, NL80211_MPATH_INFO_EXPTIME, |
3483 | pinfo->exptime)) || | 2596 | pinfo->exptime); |
3484 | ((pinfo->filled & MPATH_INFO_FLAGS) && | 2597 | if (pinfo->filled & MPATH_INFO_FLAGS) |
3485 | nla_put_u8(msg, NL80211_MPATH_INFO_FLAGS, | 2598 | NLA_PUT_U8(msg, NL80211_MPATH_INFO_FLAGS, |
3486 | pinfo->flags)) || | 2599 | pinfo->flags); |
3487 | ((pinfo->filled & MPATH_INFO_DISCOVERY_TIMEOUT) && | 2600 | if (pinfo->filled & MPATH_INFO_DISCOVERY_TIMEOUT) |
3488 | nla_put_u32(msg, NL80211_MPATH_INFO_DISCOVERY_TIMEOUT, | 2601 | NLA_PUT_U32(msg, NL80211_MPATH_INFO_DISCOVERY_TIMEOUT, |
3489 | pinfo->discovery_timeout)) || | 2602 | pinfo->discovery_timeout); |
3490 | ((pinfo->filled & MPATH_INFO_DISCOVERY_RETRIES) && | 2603 | if (pinfo->filled & MPATH_INFO_DISCOVERY_RETRIES) |
3491 | nla_put_u8(msg, NL80211_MPATH_INFO_DISCOVERY_RETRIES, | 2604 | NLA_PUT_U8(msg, NL80211_MPATH_INFO_DISCOVERY_RETRIES, |
3492 | pinfo->discovery_retries))) | 2605 | pinfo->discovery_retries); |
3493 | goto nla_put_failure; | ||
3494 | 2606 | ||
3495 | nla_nest_end(msg, pinfoattr); | 2607 | nla_nest_end(msg, pinfoattr); |
3496 | 2608 | ||
@@ -3527,14 +2639,14 @@ static int nl80211_dump_mpath(struct sk_buff *skb, | |||
3527 | } | 2639 | } |
3528 | 2640 | ||
3529 | while (1) { | 2641 | while (1) { |
3530 | err = rdev_dump_mpath(dev, netdev, path_idx, dst, next_hop, | 2642 | err = dev->ops->dump_mpath(&dev->wiphy, netdev, path_idx, |
3531 | &pinfo); | 2643 | dst, next_hop, &pinfo); |
3532 | if (err == -ENOENT) | 2644 | if (err == -ENOENT) |
3533 | break; | 2645 | break; |
3534 | if (err) | 2646 | if (err) |
3535 | goto out_err; | 2647 | goto out_err; |
3536 | 2648 | ||
3537 | if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).portid, | 2649 | if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).pid, |
3538 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 2650 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
3539 | netdev, dst, next_hop, | 2651 | netdev, dst, next_hop, |
3540 | &pinfo) < 0) | 2652 | &pinfo) < 0) |
@@ -3575,7 +2687,7 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info) | |||
3575 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) | 2687 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) |
3576 | return -EOPNOTSUPP; | 2688 | return -EOPNOTSUPP; |
3577 | 2689 | ||
3578 | err = rdev_get_mpath(rdev, dev, dst, next_hop, &pinfo); | 2690 | err = rdev->ops->get_mpath(&rdev->wiphy, dev, dst, next_hop, &pinfo); |
3579 | if (err) | 2691 | if (err) |
3580 | return err; | 2692 | return err; |
3581 | 2693 | ||
@@ -3583,7 +2695,7 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info) | |||
3583 | if (!msg) | 2695 | if (!msg) |
3584 | return -ENOMEM; | 2696 | return -ENOMEM; |
3585 | 2697 | ||
3586 | if (nl80211_send_mpath(msg, info->snd_portid, info->snd_seq, 0, | 2698 | if (nl80211_send_mpath(msg, info->snd_pid, info->snd_seq, 0, |
3587 | dev, dst, next_hop, &pinfo) < 0) { | 2699 | dev, dst, next_hop, &pinfo) < 0) { |
3588 | nlmsg_free(msg); | 2700 | nlmsg_free(msg); |
3589 | return -ENOBUFS; | 2701 | return -ENOBUFS; |
@@ -3614,7 +2726,7 @@ static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info) | |||
3614 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) | 2726 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) |
3615 | return -EOPNOTSUPP; | 2727 | return -EOPNOTSUPP; |
3616 | 2728 | ||
3617 | return rdev_change_mpath(rdev, dev, dst, next_hop); | 2729 | return rdev->ops->change_mpath(&rdev->wiphy, dev, dst, next_hop); |
3618 | } | 2730 | } |
3619 | 2731 | ||
3620 | static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info) | 2732 | static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info) |
@@ -3639,7 +2751,7 @@ static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info) | |||
3639 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) | 2751 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) |
3640 | return -EOPNOTSUPP; | 2752 | return -EOPNOTSUPP; |
3641 | 2753 | ||
3642 | return rdev_add_mpath(rdev, dev, dst, next_hop); | 2754 | return rdev->ops->add_mpath(&rdev->wiphy, dev, dst, next_hop); |
3643 | } | 2755 | } |
3644 | 2756 | ||
3645 | static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info) | 2757 | static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info) |
@@ -3654,7 +2766,7 @@ static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info) | |||
3654 | if (!rdev->ops->del_mpath) | 2766 | if (!rdev->ops->del_mpath) |
3655 | return -EOPNOTSUPP; | 2767 | return -EOPNOTSUPP; |
3656 | 2768 | ||
3657 | return rdev_del_mpath(rdev, dev, dst); | 2769 | return rdev->ops->del_mpath(&rdev->wiphy, dev, dst); |
3658 | } | 2770 | } |
3659 | 2771 | ||
3660 | static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) | 2772 | static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) |
@@ -3670,8 +2782,6 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) | |||
3670 | params.use_short_slot_time = -1; | 2782 | params.use_short_slot_time = -1; |
3671 | params.ap_isolate = -1; | 2783 | params.ap_isolate = -1; |
3672 | params.ht_opmode = -1; | 2784 | params.ht_opmode = -1; |
3673 | params.p2p_ctwindow = -1; | ||
3674 | params.p2p_opp_ps = -1; | ||
3675 | 2785 | ||
3676 | if (info->attrs[NL80211_ATTR_BSS_CTS_PROT]) | 2786 | if (info->attrs[NL80211_ATTR_BSS_CTS_PROT]) |
3677 | params.use_cts_prot = | 2787 | params.use_cts_prot = |
@@ -3694,32 +2804,6 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) | |||
3694 | params.ht_opmode = | 2804 | params.ht_opmode = |
3695 | nla_get_u16(info->attrs[NL80211_ATTR_BSS_HT_OPMODE]); | 2805 | nla_get_u16(info->attrs[NL80211_ATTR_BSS_HT_OPMODE]); |
3696 | 2806 | ||
3697 | if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) { | ||
3698 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) | ||
3699 | return -EINVAL; | ||
3700 | params.p2p_ctwindow = | ||
3701 | nla_get_s8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]); | ||
3702 | if (params.p2p_ctwindow < 0) | ||
3703 | return -EINVAL; | ||
3704 | if (params.p2p_ctwindow != 0 && | ||
3705 | !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN)) | ||
3706 | return -EINVAL; | ||
3707 | } | ||
3708 | |||
3709 | if (info->attrs[NL80211_ATTR_P2P_OPPPS]) { | ||
3710 | u8 tmp; | ||
3711 | |||
3712 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) | ||
3713 | return -EINVAL; | ||
3714 | tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]); | ||
3715 | if (tmp > 1) | ||
3716 | return -EINVAL; | ||
3717 | params.p2p_opp_ps = tmp; | ||
3718 | if (params.p2p_opp_ps && | ||
3719 | !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS)) | ||
3720 | return -EINVAL; | ||
3721 | } | ||
3722 | |||
3723 | if (!rdev->ops->change_bss) | 2807 | if (!rdev->ops->change_bss) |
3724 | return -EOPNOTSUPP; | 2808 | return -EOPNOTSUPP; |
3725 | 2809 | ||
@@ -3727,7 +2811,7 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) | |||
3727 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) | 2811 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) |
3728 | return -EOPNOTSUPP; | 2812 | return -EOPNOTSUPP; |
3729 | 2813 | ||
3730 | return rdev_change_bss(rdev, dev, ¶ms); | 2814 | return rdev->ops->change_bss(&rdev->wiphy, dev, ¶ms); |
3731 | } | 2815 | } |
3732 | 2816 | ||
3733 | static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = { | 2817 | static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = { |
@@ -3779,7 +2863,6 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
3779 | { | 2863 | { |
3780 | int r; | 2864 | int r; |
3781 | char *data = NULL; | 2865 | char *data = NULL; |
3782 | enum nl80211_user_reg_hint_type user_reg_hint_type; | ||
3783 | 2866 | ||
3784 | /* | 2867 | /* |
3785 | * You should only get this when cfg80211 hasn't yet initialized | 2868 | * You should only get this when cfg80211 hasn't yet initialized |
@@ -3799,21 +2882,7 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
3799 | 2882 | ||
3800 | data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]); | 2883 | data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]); |
3801 | 2884 | ||
3802 | if (info->attrs[NL80211_ATTR_USER_REG_HINT_TYPE]) | 2885 | r = regulatory_hint_user(data); |
3803 | user_reg_hint_type = | ||
3804 | nla_get_u32(info->attrs[NL80211_ATTR_USER_REG_HINT_TYPE]); | ||
3805 | else | ||
3806 | user_reg_hint_type = NL80211_USER_REG_HINT_USER; | ||
3807 | |||
3808 | switch (user_reg_hint_type) { | ||
3809 | case NL80211_USER_REG_HINT_USER: | ||
3810 | case NL80211_USER_REG_HINT_CELL_BASE: | ||
3811 | break; | ||
3812 | default: | ||
3813 | return -EINVAL; | ||
3814 | } | ||
3815 | |||
3816 | r = regulatory_hint_user(data, user_reg_hint_type); | ||
3817 | 2886 | ||
3818 | return r; | 2887 | return r; |
3819 | } | 2888 | } |
@@ -3841,7 +2910,8 @@ static int nl80211_get_mesh_config(struct sk_buff *skb, | |||
3841 | if (!wdev->mesh_id_len) | 2910 | if (!wdev->mesh_id_len) |
3842 | memcpy(&cur_params, &default_mesh_config, sizeof(cur_params)); | 2911 | memcpy(&cur_params, &default_mesh_config, sizeof(cur_params)); |
3843 | else | 2912 | else |
3844 | err = rdev_get_mesh_config(rdev, dev, &cur_params); | 2913 | err = rdev->ops->get_mesh_config(&rdev->wiphy, dev, |
2914 | &cur_params); | ||
3845 | wdev_unlock(wdev); | 2915 | wdev_unlock(wdev); |
3846 | 2916 | ||
3847 | if (err) | 2917 | if (err) |
@@ -3851,65 +2921,44 @@ static int nl80211_get_mesh_config(struct sk_buff *skb, | |||
3851 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 2921 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
3852 | if (!msg) | 2922 | if (!msg) |
3853 | return -ENOMEM; | 2923 | return -ENOMEM; |
3854 | hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0, | 2924 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, |
3855 | NL80211_CMD_GET_MESH_CONFIG); | 2925 | NL80211_CMD_GET_MESH_CONFIG); |
3856 | if (!hdr) | 2926 | if (!hdr) |
3857 | goto out; | 2927 | goto out; |
3858 | pinfoattr = nla_nest_start(msg, NL80211_ATTR_MESH_CONFIG); | 2928 | pinfoattr = nla_nest_start(msg, NL80211_ATTR_MESH_CONFIG); |
3859 | if (!pinfoattr) | 2929 | if (!pinfoattr) |
3860 | goto nla_put_failure; | 2930 | goto nla_put_failure; |
3861 | if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || | 2931 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); |
3862 | nla_put_u16(msg, NL80211_MESHCONF_RETRY_TIMEOUT, | 2932 | NLA_PUT_U16(msg, NL80211_MESHCONF_RETRY_TIMEOUT, |
3863 | cur_params.dot11MeshRetryTimeout) || | 2933 | cur_params.dot11MeshRetryTimeout); |
3864 | nla_put_u16(msg, NL80211_MESHCONF_CONFIRM_TIMEOUT, | 2934 | NLA_PUT_U16(msg, NL80211_MESHCONF_CONFIRM_TIMEOUT, |
3865 | cur_params.dot11MeshConfirmTimeout) || | 2935 | cur_params.dot11MeshConfirmTimeout); |
3866 | nla_put_u16(msg, NL80211_MESHCONF_HOLDING_TIMEOUT, | 2936 | NLA_PUT_U16(msg, NL80211_MESHCONF_HOLDING_TIMEOUT, |
3867 | cur_params.dot11MeshHoldingTimeout) || | 2937 | cur_params.dot11MeshHoldingTimeout); |
3868 | nla_put_u16(msg, NL80211_MESHCONF_MAX_PEER_LINKS, | 2938 | NLA_PUT_U16(msg, NL80211_MESHCONF_MAX_PEER_LINKS, |
3869 | cur_params.dot11MeshMaxPeerLinks) || | 2939 | cur_params.dot11MeshMaxPeerLinks); |
3870 | nla_put_u8(msg, NL80211_MESHCONF_MAX_RETRIES, | 2940 | NLA_PUT_U8(msg, NL80211_MESHCONF_MAX_RETRIES, |
3871 | cur_params.dot11MeshMaxRetries) || | 2941 | cur_params.dot11MeshMaxRetries); |
3872 | nla_put_u8(msg, NL80211_MESHCONF_TTL, | 2942 | NLA_PUT_U8(msg, NL80211_MESHCONF_TTL, |
3873 | cur_params.dot11MeshTTL) || | 2943 | cur_params.dot11MeshTTL); |
3874 | nla_put_u8(msg, NL80211_MESHCONF_ELEMENT_TTL, | 2944 | NLA_PUT_U8(msg, NL80211_MESHCONF_ELEMENT_TTL, |
3875 | cur_params.element_ttl) || | 2945 | cur_params.element_ttl); |
3876 | nla_put_u8(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS, | 2946 | NLA_PUT_U8(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS, |
3877 | cur_params.auto_open_plinks) || | 2947 | cur_params.auto_open_plinks); |
3878 | nla_put_u32(msg, NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, | 2948 | NLA_PUT_U8(msg, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, |
3879 | cur_params.dot11MeshNbrOffsetMaxNeighbor) || | 2949 | cur_params.dot11MeshHWMPmaxPREQretries); |
3880 | nla_put_u8(msg, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, | 2950 | NLA_PUT_U32(msg, NL80211_MESHCONF_PATH_REFRESH_TIME, |
3881 | cur_params.dot11MeshHWMPmaxPREQretries) || | 2951 | cur_params.path_refresh_time); |
3882 | nla_put_u32(msg, NL80211_MESHCONF_PATH_REFRESH_TIME, | 2952 | NLA_PUT_U16(msg, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, |
3883 | cur_params.path_refresh_time) || | 2953 | cur_params.min_discovery_timeout); |
3884 | nla_put_u16(msg, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, | 2954 | NLA_PUT_U32(msg, NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, |
3885 | cur_params.min_discovery_timeout) || | 2955 | cur_params.dot11MeshHWMPactivePathTimeout); |
3886 | nla_put_u32(msg, NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, | 2956 | NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, |
3887 | cur_params.dot11MeshHWMPactivePathTimeout) || | 2957 | cur_params.dot11MeshHWMPpreqMinInterval); |
3888 | nla_put_u16(msg, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, | 2958 | NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, |
3889 | cur_params.dot11MeshHWMPpreqMinInterval) || | 2959 | cur_params.dot11MeshHWMPnetDiameterTraversalTime); |
3890 | nla_put_u16(msg, NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL, | 2960 | NLA_PUT_U8(msg, NL80211_MESHCONF_HWMP_ROOTMODE, |
3891 | cur_params.dot11MeshHWMPperrMinInterval) || | 2961 | cur_params.dot11MeshHWMPRootMode); |
3892 | nla_put_u16(msg, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, | ||
3893 | cur_params.dot11MeshHWMPnetDiameterTraversalTime) || | ||
3894 | nla_put_u8(msg, NL80211_MESHCONF_HWMP_ROOTMODE, | ||
3895 | cur_params.dot11MeshHWMPRootMode) || | ||
3896 | nla_put_u16(msg, NL80211_MESHCONF_HWMP_RANN_INTERVAL, | ||
3897 | cur_params.dot11MeshHWMPRannInterval) || | ||
3898 | nla_put_u8(msg, NL80211_MESHCONF_GATE_ANNOUNCEMENTS, | ||
3899 | cur_params.dot11MeshGateAnnouncementProtocol) || | ||
3900 | nla_put_u8(msg, NL80211_MESHCONF_FORWARDING, | ||
3901 | cur_params.dot11MeshForwarding) || | ||
3902 | nla_put_u32(msg, NL80211_MESHCONF_RSSI_THRESHOLD, | ||
3903 | cur_params.rssi_threshold) || | ||
3904 | nla_put_u32(msg, NL80211_MESHCONF_HT_OPMODE, | ||
3905 | cur_params.ht_opmode) || | ||
3906 | nla_put_u32(msg, NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT, | ||
3907 | cur_params.dot11MeshHWMPactivePathToRootTimeout) || | ||
3908 | nla_put_u16(msg, NL80211_MESHCONF_HWMP_ROOT_INTERVAL, | ||
3909 | cur_params.dot11MeshHWMProotInterval) || | ||
3910 | nla_put_u16(msg, NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL, | ||
3911 | cur_params.dot11MeshHWMPconfirmationInterval)) | ||
3912 | goto nla_put_failure; | ||
3913 | nla_nest_end(msg, pinfoattr); | 2962 | nla_nest_end(msg, pinfoattr); |
3914 | genlmsg_end(msg, hdr); | 2963 | genlmsg_end(msg, hdr); |
3915 | return genlmsg_reply(msg, info); | 2964 | return genlmsg_reply(msg, info); |
@@ -3930,33 +2979,22 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A | |||
3930 | [NL80211_MESHCONF_TTL] = { .type = NLA_U8 }, | 2979 | [NL80211_MESHCONF_TTL] = { .type = NLA_U8 }, |
3931 | [NL80211_MESHCONF_ELEMENT_TTL] = { .type = NLA_U8 }, | 2980 | [NL80211_MESHCONF_ELEMENT_TTL] = { .type = NLA_U8 }, |
3932 | [NL80211_MESHCONF_AUTO_OPEN_PLINKS] = { .type = NLA_U8 }, | 2981 | [NL80211_MESHCONF_AUTO_OPEN_PLINKS] = { .type = NLA_U8 }, |
3933 | [NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR] = { .type = NLA_U32 }, | 2982 | |
3934 | [NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 }, | 2983 | [NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 }, |
3935 | [NL80211_MESHCONF_PATH_REFRESH_TIME] = { .type = NLA_U32 }, | 2984 | [NL80211_MESHCONF_PATH_REFRESH_TIME] = { .type = NLA_U32 }, |
3936 | [NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT] = { .type = NLA_U16 }, | 2985 | [NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT] = { .type = NLA_U16 }, |
3937 | [NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 }, | 2986 | [NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 }, |
3938 | [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] = { .type = NLA_U16 }, | 2987 | [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] = { .type = NLA_U16 }, |
3939 | [NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL] = { .type = NLA_U16 }, | ||
3940 | [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 }, | 2988 | [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 }, |
3941 | [NL80211_MESHCONF_HWMP_ROOTMODE] = { .type = NLA_U8 }, | ||
3942 | [NL80211_MESHCONF_HWMP_RANN_INTERVAL] = { .type = NLA_U16 }, | ||
3943 | [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = { .type = NLA_U8 }, | ||
3944 | [NL80211_MESHCONF_FORWARDING] = { .type = NLA_U8 }, | ||
3945 | [NL80211_MESHCONF_RSSI_THRESHOLD] = { .type = NLA_U32 }, | ||
3946 | [NL80211_MESHCONF_HT_OPMODE] = { .type = NLA_U16 }, | ||
3947 | [NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT] = { .type = NLA_U32 }, | ||
3948 | [NL80211_MESHCONF_HWMP_ROOT_INTERVAL] = { .type = NLA_U16 }, | ||
3949 | [NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL] = { .type = NLA_U16 }, | ||
3950 | }; | 2989 | }; |
3951 | 2990 | ||
3952 | static const struct nla_policy | 2991 | static const struct nla_policy |
3953 | nl80211_mesh_setup_params_policy[NL80211_MESH_SETUP_ATTR_MAX+1] = { | 2992 | nl80211_mesh_setup_params_policy[NL80211_MESH_SETUP_ATTR_MAX+1] = { |
3954 | [NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC] = { .type = NLA_U8 }, | ||
3955 | [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 }, | 2993 | [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 }, |
3956 | [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 }, | 2994 | [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 }, |
3957 | [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG }, | 2995 | [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG }, |
3958 | [NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY, | 2996 | [NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY, |
3959 | .len = IEEE80211_MAX_DATA_LEN }, | 2997 | .len = IEEE80211_MAX_DATA_LEN }, |
3960 | [NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG }, | 2998 | [NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG }, |
3961 | }; | 2999 | }; |
3962 | 3000 | ||
@@ -3989,82 +3027,43 @@ do {\ | |||
3989 | 3027 | ||
3990 | /* Fill in the params struct */ | 3028 | /* Fill in the params struct */ |
3991 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, | 3029 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, |
3992 | mask, NL80211_MESHCONF_RETRY_TIMEOUT, | 3030 | mask, NL80211_MESHCONF_RETRY_TIMEOUT, nla_get_u16); |
3993 | nla_get_u16); | ||
3994 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, | 3031 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, |
3995 | mask, NL80211_MESHCONF_CONFIRM_TIMEOUT, | 3032 | mask, NL80211_MESHCONF_CONFIRM_TIMEOUT, nla_get_u16); |
3996 | nla_get_u16); | ||
3997 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, | 3033 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, |
3998 | mask, NL80211_MESHCONF_HOLDING_TIMEOUT, | 3034 | mask, NL80211_MESHCONF_HOLDING_TIMEOUT, nla_get_u16); |
3999 | nla_get_u16); | ||
4000 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, | 3035 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, |
4001 | mask, NL80211_MESHCONF_MAX_PEER_LINKS, | 3036 | mask, NL80211_MESHCONF_MAX_PEER_LINKS, nla_get_u16); |
4002 | nla_get_u16); | ||
4003 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, | 3037 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, |
4004 | mask, NL80211_MESHCONF_MAX_RETRIES, | 3038 | mask, NL80211_MESHCONF_MAX_RETRIES, nla_get_u8); |
4005 | nla_get_u8); | ||
4006 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, | 3039 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, |
4007 | mask, NL80211_MESHCONF_TTL, nla_get_u8); | 3040 | mask, NL80211_MESHCONF_TTL, nla_get_u8); |
4008 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, element_ttl, | 3041 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, element_ttl, |
4009 | mask, NL80211_MESHCONF_ELEMENT_TTL, | 3042 | mask, NL80211_MESHCONF_ELEMENT_TTL, nla_get_u8); |
4010 | nla_get_u8); | ||
4011 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, | 3043 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, |
4012 | mask, NL80211_MESHCONF_AUTO_OPEN_PLINKS, | 3044 | mask, NL80211_MESHCONF_AUTO_OPEN_PLINKS, nla_get_u8); |
4013 | nla_get_u8); | ||
4014 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNbrOffsetMaxNeighbor, mask, | ||
4015 | NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, | ||
4016 | nla_get_u32); | ||
4017 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, | 3045 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, |
4018 | mask, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, | 3046 | mask, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, |
4019 | nla_get_u8); | 3047 | nla_get_u8); |
4020 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, | 3048 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, |
4021 | mask, NL80211_MESHCONF_PATH_REFRESH_TIME, | 3049 | mask, NL80211_MESHCONF_PATH_REFRESH_TIME, nla_get_u32); |
4022 | nla_get_u32); | ||
4023 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout, | 3050 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout, |
4024 | mask, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, | 3051 | mask, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, |
4025 | nla_get_u16); | 3052 | nla_get_u16); |
4026 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout, mask, | 3053 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout, |
4027 | NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, | 3054 | mask, NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, |
4028 | nla_get_u32); | 3055 | nla_get_u32); |
4029 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval, | 3056 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval, |
4030 | mask, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, | 3057 | mask, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, |
4031 | nla_get_u16); | 3058 | nla_get_u16); |
4032 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPperrMinInterval, | ||
4033 | mask, NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL, | ||
4034 | nla_get_u16); | ||
4035 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, | ||
4036 | dot11MeshHWMPnetDiameterTraversalTime, mask, | ||
4037 | NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, | ||
4038 | nla_get_u16); | ||
4039 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRootMode, mask, | ||
4040 | NL80211_MESHCONF_HWMP_ROOTMODE, nla_get_u8); | ||
4041 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRannInterval, mask, | ||
4042 | NL80211_MESHCONF_HWMP_RANN_INTERVAL, | ||
4043 | nla_get_u16); | ||
4044 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, | 3059 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, |
4045 | dot11MeshGateAnnouncementProtocol, mask, | 3060 | dot11MeshHWMPnetDiameterTraversalTime, |
4046 | NL80211_MESHCONF_GATE_ANNOUNCEMENTS, | 3061 | mask, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, |
4047 | nla_get_u8); | 3062 | nla_get_u16); |
4048 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, | ||
4049 | mask, NL80211_MESHCONF_FORWARDING, | ||
4050 | nla_get_u8); | ||
4051 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, | ||
4052 | mask, NL80211_MESHCONF_RSSI_THRESHOLD, | ||
4053 | nla_get_u32); | ||
4054 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, ht_opmode, | ||
4055 | mask, NL80211_MESHCONF_HT_OPMODE, | ||
4056 | nla_get_u16); | ||
4057 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathToRootTimeout, | ||
4058 | mask, | ||
4059 | NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT, | ||
4060 | nla_get_u32); | ||
4061 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMProotInterval, | ||
4062 | mask, NL80211_MESHCONF_HWMP_ROOT_INTERVAL, | ||
4063 | nla_get_u16); | ||
4064 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, | 3063 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, |
4065 | dot11MeshHWMPconfirmationInterval, mask, | 3064 | dot11MeshHWMPRootMode, mask, |
4066 | NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL, | 3065 | NL80211_MESHCONF_HWMP_ROOTMODE, |
4067 | nla_get_u16); | 3066 | nla_get_u8); |
4068 | if (mask_out) | 3067 | if (mask_out) |
4069 | *mask_out = mask; | 3068 | *mask_out = mask; |
4070 | 3069 | ||
@@ -4085,12 +3084,6 @@ static int nl80211_parse_mesh_setup(struct genl_info *info, | |||
4085 | nl80211_mesh_setup_params_policy)) | 3084 | nl80211_mesh_setup_params_policy)) |
4086 | return -EINVAL; | 3085 | return -EINVAL; |
4087 | 3086 | ||
4088 | if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC]) | ||
4089 | setup->sync_method = | ||
4090 | (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC])) ? | ||
4091 | IEEE80211_SYNC_METHOD_VENDOR : | ||
4092 | IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET; | ||
4093 | |||
4094 | if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL]) | 3087 | if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL]) |
4095 | setup->path_sel_proto = | 3088 | setup->path_sel_proto = |
4096 | (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL])) ? | 3089 | (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL])) ? |
@@ -4143,7 +3136,8 @@ static int nl80211_update_mesh_config(struct sk_buff *skb, | |||
4143 | err = -ENOLINK; | 3136 | err = -ENOLINK; |
4144 | 3137 | ||
4145 | if (!err) | 3138 | if (!err) |
4146 | err = rdev_update_mesh_config(rdev, dev, mask, &cfg); | 3139 | err = rdev->ops->update_mesh_config(&rdev->wiphy, dev, |
3140 | mask, &cfg); | ||
4147 | 3141 | ||
4148 | wdev_unlock(wdev); | 3142 | wdev_unlock(wdev); |
4149 | 3143 | ||
@@ -4169,22 +3163,13 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) | |||
4169 | goto out; | 3163 | goto out; |
4170 | } | 3164 | } |
4171 | 3165 | ||
4172 | hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0, | 3166 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, |
4173 | NL80211_CMD_GET_REG); | 3167 | NL80211_CMD_GET_REG); |
4174 | if (!hdr) | 3168 | if (!hdr) |
4175 | goto put_failure; | 3169 | goto put_failure; |
4176 | 3170 | ||
4177 | if (nla_put_string(msg, NL80211_ATTR_REG_ALPHA2, | 3171 | NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, |
4178 | cfg80211_regdomain->alpha2) || | 3172 | cfg80211_regdomain->alpha2); |
4179 | (cfg80211_regdomain->dfs_region && | ||
4180 | nla_put_u8(msg, NL80211_ATTR_DFS_REGION, | ||
4181 | cfg80211_regdomain->dfs_region))) | ||
4182 | goto nla_put_failure; | ||
4183 | |||
4184 | if (reg_last_request_cell_base() && | ||
4185 | nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE, | ||
4186 | NL80211_USER_REG_HINT_CELL_BASE)) | ||
4187 | goto nla_put_failure; | ||
4188 | 3173 | ||
4189 | nl_reg_rules = nla_nest_start(msg, NL80211_ATTR_REG_RULES); | 3174 | nl_reg_rules = nla_nest_start(msg, NL80211_ATTR_REG_RULES); |
4190 | if (!nl_reg_rules) | 3175 | if (!nl_reg_rules) |
@@ -4204,19 +3189,18 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) | |||
4204 | if (!nl_reg_rule) | 3189 | if (!nl_reg_rule) |
4205 | goto nla_put_failure; | 3190 | goto nla_put_failure; |
4206 | 3191 | ||
4207 | if (nla_put_u32(msg, NL80211_ATTR_REG_RULE_FLAGS, | 3192 | NLA_PUT_U32(msg, NL80211_ATTR_REG_RULE_FLAGS, |
4208 | reg_rule->flags) || | 3193 | reg_rule->flags); |
4209 | nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_START, | 3194 | NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_START, |
4210 | freq_range->start_freq_khz) || | 3195 | freq_range->start_freq_khz); |
4211 | nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_END, | 3196 | NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_END, |
4212 | freq_range->end_freq_khz) || | 3197 | freq_range->end_freq_khz); |
4213 | nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_MAX_BW, | 3198 | NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_MAX_BW, |
4214 | freq_range->max_bandwidth_khz) || | 3199 | freq_range->max_bandwidth_khz); |
4215 | nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN, | 3200 | NLA_PUT_U32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN, |
4216 | power_rule->max_antenna_gain) || | 3201 | power_rule->max_antenna_gain); |
4217 | nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP, | 3202 | NLA_PUT_U32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP, |
4218 | power_rule->max_eirp)) | 3203 | power_rule->max_eirp); |
4219 | goto nla_put_failure; | ||
4220 | 3204 | ||
4221 | nla_nest_end(msg, nl_reg_rule); | 3205 | nla_nest_end(msg, nl_reg_rule); |
4222 | } | 3206 | } |
@@ -4244,7 +3228,6 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
4244 | char *alpha2 = NULL; | 3228 | char *alpha2 = NULL; |
4245 | int rem_reg_rules = 0, r = 0; | 3229 | int rem_reg_rules = 0, r = 0; |
4246 | u32 num_rules = 0, rule_idx = 0, size_of_regd; | 3230 | u32 num_rules = 0, rule_idx = 0, size_of_regd; |
4247 | u8 dfs_region = 0; | ||
4248 | struct ieee80211_regdomain *rd = NULL; | 3231 | struct ieee80211_regdomain *rd = NULL; |
4249 | 3232 | ||
4250 | if (!info->attrs[NL80211_ATTR_REG_ALPHA2]) | 3233 | if (!info->attrs[NL80211_ATTR_REG_ALPHA2]) |
@@ -4255,9 +3238,6 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
4255 | 3238 | ||
4256 | alpha2 = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]); | 3239 | alpha2 = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]); |
4257 | 3240 | ||
4258 | if (info->attrs[NL80211_ATTR_DFS_REGION]) | ||
4259 | dfs_region = nla_get_u8(info->attrs[NL80211_ATTR_DFS_REGION]); | ||
4260 | |||
4261 | nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES], | 3241 | nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES], |
4262 | rem_reg_rules) { | 3242 | rem_reg_rules) { |
4263 | num_rules++; | 3243 | num_rules++; |
@@ -4285,13 +3265,6 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
4285 | rd->alpha2[0] = alpha2[0]; | 3265 | rd->alpha2[0] = alpha2[0]; |
4286 | rd->alpha2[1] = alpha2[1]; | 3266 | rd->alpha2[1] = alpha2[1]; |
4287 | 3267 | ||
4288 | /* | ||
4289 | * Disable DFS master mode if the DFS region was | ||
4290 | * not supported or known on this kernel. | ||
4291 | */ | ||
4292 | if (reg_supported_dfs_region(dfs_region)) | ||
4293 | rd->dfs_region = dfs_region; | ||
4294 | |||
4295 | nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES], | 3268 | nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES], |
4296 | rem_reg_rules) { | 3269 | rem_reg_rules) { |
4297 | nla_parse(tb, NL80211_REG_RULE_ATTR_MAX, | 3270 | nla_parse(tb, NL80211_REG_RULE_ATTR_MAX, |
@@ -4351,7 +3324,7 @@ static int validate_scan_freqs(struct nlattr *freqs) | |||
4351 | static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | 3324 | static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) |
4352 | { | 3325 | { |
4353 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 3326 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
4354 | struct wireless_dev *wdev = info->user_ptr[1]; | 3327 | struct net_device *dev = info->user_ptr[1]; |
4355 | struct cfg80211_scan_request *request; | 3328 | struct cfg80211_scan_request *request; |
4356 | struct nlattr *attr; | 3329 | struct nlattr *attr; |
4357 | struct wiphy *wiphy; | 3330 | struct wiphy *wiphy; |
@@ -4508,32 +3481,15 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
4508 | } | 3481 | } |
4509 | } | 3482 | } |
4510 | 3483 | ||
4511 | if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) { | 3484 | request->dev = dev; |
4512 | request->flags = nla_get_u32( | ||
4513 | info->attrs[NL80211_ATTR_SCAN_FLAGS]); | ||
4514 | if (((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) && | ||
4515 | !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) || | ||
4516 | ((request->flags & NL80211_SCAN_FLAG_FLUSH) && | ||
4517 | !(wiphy->features & NL80211_FEATURE_SCAN_FLUSH))) { | ||
4518 | err = -EOPNOTSUPP; | ||
4519 | goto out_free; | ||
4520 | } | ||
4521 | } | ||
4522 | |||
4523 | request->no_cck = | ||
4524 | nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]); | ||
4525 | |||
4526 | request->wdev = wdev; | ||
4527 | request->wiphy = &rdev->wiphy; | 3485 | request->wiphy = &rdev->wiphy; |
4528 | request->scan_start = jiffies; | ||
4529 | 3486 | ||
4530 | rdev->scan_req = request; | 3487 | rdev->scan_req = request; |
4531 | err = rdev_scan(rdev, request); | 3488 | err = rdev->ops->scan(&rdev->wiphy, dev, request); |
4532 | 3489 | ||
4533 | if (!err) { | 3490 | if (!err) { |
4534 | nl80211_send_scan_start(rdev, wdev); | 3491 | nl80211_send_scan_start(rdev, dev); |
4535 | if (wdev->netdev) | 3492 | dev_hold(dev); |
4536 | dev_hold(wdev->netdev); | ||
4537 | } else { | 3493 | } else { |
4538 | out_free: | 3494 | out_free: |
4539 | rdev->scan_req = NULL; | 3495 | rdev->scan_req = NULL; |
@@ -4551,11 +3507,10 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, | |||
4551 | struct net_device *dev = info->user_ptr[1]; | 3507 | struct net_device *dev = info->user_ptr[1]; |
4552 | struct nlattr *attr; | 3508 | struct nlattr *attr; |
4553 | struct wiphy *wiphy; | 3509 | struct wiphy *wiphy; |
4554 | int err, tmp, n_ssids = 0, n_match_sets = 0, n_channels, i; | 3510 | int err, tmp, n_ssids = 0, n_channels, i; |
4555 | u32 interval; | 3511 | u32 interval; |
4556 | enum ieee80211_band band; | 3512 | enum ieee80211_band band; |
4557 | size_t ie_len; | 3513 | size_t ie_len; |
4558 | struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1]; | ||
4559 | 3514 | ||
4560 | if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || | 3515 | if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || |
4561 | !rdev->ops->sched_scan_start) | 3516 | !rdev->ops->sched_scan_start) |
@@ -4594,15 +3549,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, | |||
4594 | if (n_ssids > wiphy->max_sched_scan_ssids) | 3549 | if (n_ssids > wiphy->max_sched_scan_ssids) |
4595 | return -EINVAL; | 3550 | return -EINVAL; |
4596 | 3551 | ||
4597 | if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) | ||
4598 | nla_for_each_nested(attr, | ||
4599 | info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH], | ||
4600 | tmp) | ||
4601 | n_match_sets++; | ||
4602 | |||
4603 | if (n_match_sets > wiphy->max_match_sets) | ||
4604 | return -EINVAL; | ||
4605 | |||
4606 | if (info->attrs[NL80211_ATTR_IE]) | 3552 | if (info->attrs[NL80211_ATTR_IE]) |
4607 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | 3553 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); |
4608 | else | 3554 | else |
@@ -4620,7 +3566,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, | |||
4620 | 3566 | ||
4621 | request = kzalloc(sizeof(*request) | 3567 | request = kzalloc(sizeof(*request) |
4622 | + sizeof(*request->ssids) * n_ssids | 3568 | + sizeof(*request->ssids) * n_ssids |
4623 | + sizeof(*request->match_sets) * n_match_sets | ||
4624 | + sizeof(*request->channels) * n_channels | 3569 | + sizeof(*request->channels) * n_channels |
4625 | + ie_len, GFP_KERNEL); | 3570 | + ie_len, GFP_KERNEL); |
4626 | if (!request) { | 3571 | if (!request) { |
@@ -4638,18 +3583,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, | |||
4638 | request->ie = (void *)(request->channels + n_channels); | 3583 | request->ie = (void *)(request->channels + n_channels); |
4639 | } | 3584 | } |
4640 | 3585 | ||
4641 | if (n_match_sets) { | ||
4642 | if (request->ie) | ||
4643 | request->match_sets = (void *)(request->ie + ie_len); | ||
4644 | else if (request->ssids) | ||
4645 | request->match_sets = | ||
4646 | (void *)(request->ssids + n_ssids); | ||
4647 | else | ||
4648 | request->match_sets = | ||
4649 | (void *)(request->channels + n_channels); | ||
4650 | } | ||
4651 | request->n_match_sets = n_match_sets; | ||
4652 | |||
4653 | i = 0; | 3586 | i = 0; |
4654 | if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { | 3587 | if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { |
4655 | /* user specified, bail out if channel not found */ | 3588 | /* user specified, bail out if channel not found */ |
@@ -4714,37 +3647,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, | |||
4714 | } | 3647 | } |
4715 | } | 3648 | } |
4716 | 3649 | ||
4717 | i = 0; | ||
4718 | if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) { | ||
4719 | nla_for_each_nested(attr, | ||
4720 | info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH], | ||
4721 | tmp) { | ||
4722 | struct nlattr *ssid, *rssi; | ||
4723 | |||
4724 | nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX, | ||
4725 | nla_data(attr), nla_len(attr), | ||
4726 | nl80211_match_policy); | ||
4727 | ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID]; | ||
4728 | if (ssid) { | ||
4729 | if (nla_len(ssid) > IEEE80211_MAX_SSID_LEN) { | ||
4730 | err = -EINVAL; | ||
4731 | goto out_free; | ||
4732 | } | ||
4733 | memcpy(request->match_sets[i].ssid.ssid, | ||
4734 | nla_data(ssid), nla_len(ssid)); | ||
4735 | request->match_sets[i].ssid.ssid_len = | ||
4736 | nla_len(ssid); | ||
4737 | } | ||
4738 | rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI]; | ||
4739 | if (rssi) | ||
4740 | request->rssi_thold = nla_get_u32(rssi); | ||
4741 | else | ||
4742 | request->rssi_thold = | ||
4743 | NL80211_SCAN_RSSI_THOLD_OFF; | ||
4744 | i++; | ||
4745 | } | ||
4746 | } | ||
4747 | |||
4748 | if (info->attrs[NL80211_ATTR_IE]) { | 3650 | if (info->attrs[NL80211_ATTR_IE]) { |
4749 | request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | 3651 | request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); |
4750 | memcpy((void *)request->ie, | 3652 | memcpy((void *)request->ie, |
@@ -4752,24 +3654,11 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, | |||
4752 | request->ie_len); | 3654 | request->ie_len); |
4753 | } | 3655 | } |
4754 | 3656 | ||
4755 | if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) { | ||
4756 | request->flags = nla_get_u32( | ||
4757 | info->attrs[NL80211_ATTR_SCAN_FLAGS]); | ||
4758 | if (((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) && | ||
4759 | !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) || | ||
4760 | ((request->flags & NL80211_SCAN_FLAG_FLUSH) && | ||
4761 | !(wiphy->features & NL80211_FEATURE_SCAN_FLUSH))) { | ||
4762 | err = -EOPNOTSUPP; | ||
4763 | goto out_free; | ||
4764 | } | ||
4765 | } | ||
4766 | |||
4767 | request->dev = dev; | 3657 | request->dev = dev; |
4768 | request->wiphy = &rdev->wiphy; | 3658 | request->wiphy = &rdev->wiphy; |
4769 | request->interval = interval; | 3659 | request->interval = interval; |
4770 | request->scan_start = jiffies; | ||
4771 | 3660 | ||
4772 | err = rdev_sched_scan_start(rdev, dev, request); | 3661 | err = rdev->ops->sched_scan_start(&rdev->wiphy, dev, request); |
4773 | if (!err) { | 3662 | if (!err) { |
4774 | rdev->sched_scan_req = request; | 3663 | rdev->sched_scan_req = request; |
4775 | nl80211_send_sched_scan(rdev, dev, | 3664 | nl80211_send_sched_scan(rdev, dev, |
@@ -4808,65 +3697,50 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, | |||
4808 | struct cfg80211_internal_bss *intbss) | 3697 | struct cfg80211_internal_bss *intbss) |
4809 | { | 3698 | { |
4810 | struct cfg80211_bss *res = &intbss->pub; | 3699 | struct cfg80211_bss *res = &intbss->pub; |
4811 | const struct cfg80211_bss_ies *ies; | ||
4812 | void *hdr; | 3700 | void *hdr; |
4813 | struct nlattr *bss; | 3701 | struct nlattr *bss; |
3702 | int i; | ||
4814 | 3703 | ||
4815 | ASSERT_WDEV_LOCK(wdev); | 3704 | ASSERT_WDEV_LOCK(wdev); |
4816 | 3705 | ||
4817 | hdr = nl80211hdr_put(msg, NETLINK_CB(cb->skb).portid, seq, flags, | 3706 | hdr = nl80211hdr_put(msg, NETLINK_CB(cb->skb).pid, seq, flags, |
4818 | NL80211_CMD_NEW_SCAN_RESULTS); | 3707 | NL80211_CMD_NEW_SCAN_RESULTS); |
4819 | if (!hdr) | 3708 | if (!hdr) |
4820 | return -1; | 3709 | return -1; |
4821 | 3710 | ||
4822 | genl_dump_check_consistent(cb, hdr, &nl80211_fam); | 3711 | genl_dump_check_consistent(cb, hdr, &nl80211_fam); |
4823 | 3712 | ||
4824 | if (nla_put_u32(msg, NL80211_ATTR_GENERATION, rdev->bss_generation) || | 3713 | NLA_PUT_U32(msg, NL80211_ATTR_GENERATION, rdev->bss_generation); |
4825 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex)) | 3714 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex); |
4826 | goto nla_put_failure; | ||
4827 | 3715 | ||
4828 | bss = nla_nest_start(msg, NL80211_ATTR_BSS); | 3716 | bss = nla_nest_start(msg, NL80211_ATTR_BSS); |
4829 | if (!bss) | 3717 | if (!bss) |
4830 | goto nla_put_failure; | 3718 | goto nla_put_failure; |
4831 | if ((!is_zero_ether_addr(res->bssid) && | 3719 | if (!is_zero_ether_addr(res->bssid)) |
4832 | nla_put(msg, NL80211_BSS_BSSID, ETH_ALEN, res->bssid))) | 3720 | NLA_PUT(msg, NL80211_BSS_BSSID, ETH_ALEN, res->bssid); |
4833 | goto nla_put_failure; | 3721 | if (res->information_elements && res->len_information_elements) |
4834 | 3722 | NLA_PUT(msg, NL80211_BSS_INFORMATION_ELEMENTS, | |
4835 | rcu_read_lock(); | 3723 | res->len_information_elements, |
4836 | ies = rcu_dereference(res->ies); | 3724 | res->information_elements); |
4837 | if (ies && ies->len && nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS, | 3725 | if (res->beacon_ies && res->len_beacon_ies && |
4838 | ies->len, ies->data)) { | 3726 | res->beacon_ies != res->information_elements) |
4839 | rcu_read_unlock(); | 3727 | NLA_PUT(msg, NL80211_BSS_BEACON_IES, |
4840 | goto nla_put_failure; | 3728 | res->len_beacon_ies, res->beacon_ies); |
4841 | } | 3729 | if (res->tsf) |
4842 | ies = rcu_dereference(res->beacon_ies); | 3730 | NLA_PUT_U64(msg, NL80211_BSS_TSF, res->tsf); |
4843 | if (ies && ies->len && nla_put(msg, NL80211_BSS_BEACON_IES, | 3731 | if (res->beacon_interval) |
4844 | ies->len, ies->data)) { | 3732 | NLA_PUT_U16(msg, NL80211_BSS_BEACON_INTERVAL, res->beacon_interval); |
4845 | rcu_read_unlock(); | 3733 | NLA_PUT_U16(msg, NL80211_BSS_CAPABILITY, res->capability); |
4846 | goto nla_put_failure; | 3734 | NLA_PUT_U32(msg, NL80211_BSS_FREQUENCY, res->channel->center_freq); |
4847 | } | 3735 | NLA_PUT_U32(msg, NL80211_BSS_SEEN_MS_AGO, |
4848 | rcu_read_unlock(); | 3736 | jiffies_to_msecs(jiffies - intbss->ts)); |
4849 | |||
4850 | if (res->tsf && | ||
4851 | nla_put_u64(msg, NL80211_BSS_TSF, res->tsf)) | ||
4852 | goto nla_put_failure; | ||
4853 | if (res->beacon_interval && | ||
4854 | nla_put_u16(msg, NL80211_BSS_BEACON_INTERVAL, res->beacon_interval)) | ||
4855 | goto nla_put_failure; | ||
4856 | if (nla_put_u16(msg, NL80211_BSS_CAPABILITY, res->capability) || | ||
4857 | nla_put_u32(msg, NL80211_BSS_FREQUENCY, res->channel->center_freq) || | ||
4858 | nla_put_u32(msg, NL80211_BSS_SEEN_MS_AGO, | ||
4859 | jiffies_to_msecs(jiffies - intbss->ts))) | ||
4860 | goto nla_put_failure; | ||
4861 | 3737 | ||
4862 | switch (rdev->wiphy.signal_type) { | 3738 | switch (rdev->wiphy.signal_type) { |
4863 | case CFG80211_SIGNAL_TYPE_MBM: | 3739 | case CFG80211_SIGNAL_TYPE_MBM: |
4864 | if (nla_put_u32(msg, NL80211_BSS_SIGNAL_MBM, res->signal)) | 3740 | NLA_PUT_U32(msg, NL80211_BSS_SIGNAL_MBM, res->signal); |
4865 | goto nla_put_failure; | ||
4866 | break; | 3741 | break; |
4867 | case CFG80211_SIGNAL_TYPE_UNSPEC: | 3742 | case CFG80211_SIGNAL_TYPE_UNSPEC: |
4868 | if (nla_put_u8(msg, NL80211_BSS_SIGNAL_UNSPEC, res->signal)) | 3743 | NLA_PUT_U8(msg, NL80211_BSS_SIGNAL_UNSPEC, res->signal); |
4869 | goto nla_put_failure; | ||
4870 | break; | 3744 | break; |
4871 | default: | 3745 | default: |
4872 | break; | 3746 | break; |
@@ -4875,16 +3749,21 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, | |||
4875 | switch (wdev->iftype) { | 3749 | switch (wdev->iftype) { |
4876 | case NL80211_IFTYPE_P2P_CLIENT: | 3750 | case NL80211_IFTYPE_P2P_CLIENT: |
4877 | case NL80211_IFTYPE_STATION: | 3751 | case NL80211_IFTYPE_STATION: |
4878 | if (intbss == wdev->current_bss && | 3752 | if (intbss == wdev->current_bss) |
4879 | nla_put_u32(msg, NL80211_BSS_STATUS, | 3753 | NLA_PUT_U32(msg, NL80211_BSS_STATUS, |
4880 | NL80211_BSS_STATUS_ASSOCIATED)) | 3754 | NL80211_BSS_STATUS_ASSOCIATED); |
4881 | goto nla_put_failure; | 3755 | else for (i = 0; i < MAX_AUTH_BSSES; i++) { |
3756 | if (intbss != wdev->auth_bsses[i]) | ||
3757 | continue; | ||
3758 | NLA_PUT_U32(msg, NL80211_BSS_STATUS, | ||
3759 | NL80211_BSS_STATUS_AUTHENTICATED); | ||
3760 | break; | ||
3761 | } | ||
4882 | break; | 3762 | break; |
4883 | case NL80211_IFTYPE_ADHOC: | 3763 | case NL80211_IFTYPE_ADHOC: |
4884 | if (intbss == wdev->current_bss && | 3764 | if (intbss == wdev->current_bss) |
4885 | nla_put_u32(msg, NL80211_BSS_STATUS, | 3765 | NLA_PUT_U32(msg, NL80211_BSS_STATUS, |
4886 | NL80211_BSS_STATUS_IBSS_JOINED)) | 3766 | NL80211_BSS_STATUS_IBSS_JOINED); |
4887 | goto nla_put_failure; | ||
4888 | break; | 3767 | break; |
4889 | default: | 3768 | default: |
4890 | break; | 3769 | break; |
@@ -4941,55 +3820,46 @@ static int nl80211_dump_scan(struct sk_buff *skb, | |||
4941 | return skb->len; | 3820 | return skb->len; |
4942 | } | 3821 | } |
4943 | 3822 | ||
4944 | static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq, | 3823 | static int nl80211_send_survey(struct sk_buff *msg, u32 pid, u32 seq, |
4945 | int flags, struct net_device *dev, | 3824 | int flags, struct net_device *dev, |
4946 | struct survey_info *survey) | 3825 | struct survey_info *survey) |
4947 | { | 3826 | { |
4948 | void *hdr; | 3827 | void *hdr; |
4949 | struct nlattr *infoattr; | 3828 | struct nlattr *infoattr; |
4950 | 3829 | ||
4951 | hdr = nl80211hdr_put(msg, portid, seq, flags, | 3830 | hdr = nl80211hdr_put(msg, pid, seq, flags, |
4952 | NL80211_CMD_NEW_SURVEY_RESULTS); | 3831 | NL80211_CMD_NEW_SURVEY_RESULTS); |
4953 | if (!hdr) | 3832 | if (!hdr) |
4954 | return -ENOMEM; | 3833 | return -ENOMEM; |
4955 | 3834 | ||
4956 | if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex)) | 3835 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); |
4957 | goto nla_put_failure; | ||
4958 | 3836 | ||
4959 | infoattr = nla_nest_start(msg, NL80211_ATTR_SURVEY_INFO); | 3837 | infoattr = nla_nest_start(msg, NL80211_ATTR_SURVEY_INFO); |
4960 | if (!infoattr) | 3838 | if (!infoattr) |
4961 | goto nla_put_failure; | 3839 | goto nla_put_failure; |
4962 | 3840 | ||
4963 | if (nla_put_u32(msg, NL80211_SURVEY_INFO_FREQUENCY, | 3841 | NLA_PUT_U32(msg, NL80211_SURVEY_INFO_FREQUENCY, |
4964 | survey->channel->center_freq)) | 3842 | survey->channel->center_freq); |
4965 | goto nla_put_failure; | 3843 | if (survey->filled & SURVEY_INFO_NOISE_DBM) |
4966 | 3844 | NLA_PUT_U8(msg, NL80211_SURVEY_INFO_NOISE, | |
4967 | if ((survey->filled & SURVEY_INFO_NOISE_DBM) && | 3845 | survey->noise); |
4968 | nla_put_u8(msg, NL80211_SURVEY_INFO_NOISE, survey->noise)) | 3846 | if (survey->filled & SURVEY_INFO_IN_USE) |
4969 | goto nla_put_failure; | 3847 | NLA_PUT_FLAG(msg, NL80211_SURVEY_INFO_IN_USE); |
4970 | if ((survey->filled & SURVEY_INFO_IN_USE) && | 3848 | if (survey->filled & SURVEY_INFO_CHANNEL_TIME) |
4971 | nla_put_flag(msg, NL80211_SURVEY_INFO_IN_USE)) | 3849 | NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME, |
4972 | goto nla_put_failure; | 3850 | survey->channel_time); |
4973 | if ((survey->filled & SURVEY_INFO_CHANNEL_TIME) && | 3851 | if (survey->filled & SURVEY_INFO_CHANNEL_TIME_BUSY) |
4974 | nla_put_u64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME, | 3852 | NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY, |
4975 | survey->channel_time)) | 3853 | survey->channel_time_busy); |
4976 | goto nla_put_failure; | 3854 | if (survey->filled & SURVEY_INFO_CHANNEL_TIME_EXT_BUSY) |
4977 | if ((survey->filled & SURVEY_INFO_CHANNEL_TIME_BUSY) && | 3855 | NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY, |
4978 | nla_put_u64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY, | 3856 | survey->channel_time_ext_busy); |
4979 | survey->channel_time_busy)) | 3857 | if (survey->filled & SURVEY_INFO_CHANNEL_TIME_RX) |
4980 | goto nla_put_failure; | 3858 | NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_RX, |
4981 | if ((survey->filled & SURVEY_INFO_CHANNEL_TIME_EXT_BUSY) && | 3859 | survey->channel_time_rx); |
4982 | nla_put_u64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY, | 3860 | if (survey->filled & SURVEY_INFO_CHANNEL_TIME_TX) |
4983 | survey->channel_time_ext_busy)) | 3861 | NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_TX, |
4984 | goto nla_put_failure; | 3862 | survey->channel_time_tx); |
4985 | if ((survey->filled & SURVEY_INFO_CHANNEL_TIME_RX) && | ||
4986 | nla_put_u64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_RX, | ||
4987 | survey->channel_time_rx)) | ||
4988 | goto nla_put_failure; | ||
4989 | if ((survey->filled & SURVEY_INFO_CHANNEL_TIME_TX) && | ||
4990 | nla_put_u64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_TX, | ||
4991 | survey->channel_time_tx)) | ||
4992 | goto nla_put_failure; | ||
4993 | 3863 | ||
4994 | nla_nest_end(msg, infoattr); | 3864 | nla_nest_end(msg, infoattr); |
4995 | 3865 | ||
@@ -5021,7 +3891,8 @@ static int nl80211_dump_survey(struct sk_buff *skb, | |||
5021 | while (1) { | 3891 | while (1) { |
5022 | struct ieee80211_channel *chan; | 3892 | struct ieee80211_channel *chan; |
5023 | 3893 | ||
5024 | res = rdev_dump_survey(dev, netdev, survey_idx, &survey); | 3894 | res = dev->ops->dump_survey(&dev->wiphy, netdev, survey_idx, |
3895 | &survey); | ||
5025 | if (res == -ENOENT) | 3896 | if (res == -ENOENT) |
5026 | break; | 3897 | break; |
5027 | if (res) | 3898 | if (res) |
@@ -5041,7 +3912,7 @@ static int nl80211_dump_survey(struct sk_buff *skb, | |||
5041 | } | 3912 | } |
5042 | 3913 | ||
5043 | if (nl80211_send_survey(skb, | 3914 | if (nl80211_send_survey(skb, |
5044 | NETLINK_CB(cb->skb).portid, | 3915 | NETLINK_CB(cb->skb).pid, |
5045 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 3916 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
5046 | netdev, | 3917 | netdev, |
5047 | &survey) < 0) | 3918 | &survey) < 0) |
@@ -5057,19 +3928,40 @@ static int nl80211_dump_survey(struct sk_buff *skb, | |||
5057 | return res; | 3928 | return res; |
5058 | } | 3929 | } |
5059 | 3930 | ||
3931 | static bool nl80211_valid_auth_type(enum nl80211_auth_type auth_type) | ||
3932 | { | ||
3933 | return auth_type <= NL80211_AUTHTYPE_MAX; | ||
3934 | } | ||
3935 | |||
5060 | static bool nl80211_valid_wpa_versions(u32 wpa_versions) | 3936 | static bool nl80211_valid_wpa_versions(u32 wpa_versions) |
5061 | { | 3937 | { |
5062 | return !(wpa_versions & ~(NL80211_WPA_VERSION_1 | | 3938 | return !(wpa_versions & ~(NL80211_WPA_VERSION_1 | |
5063 | NL80211_WPA_VERSION_2)); | 3939 | NL80211_WPA_VERSION_2)); |
5064 | } | 3940 | } |
5065 | 3941 | ||
3942 | static bool nl80211_valid_akm_suite(u32 akm) | ||
3943 | { | ||
3944 | return akm == WLAN_AKM_SUITE_8021X || | ||
3945 | akm == WLAN_AKM_SUITE_PSK; | ||
3946 | } | ||
3947 | |||
3948 | static bool nl80211_valid_cipher_suite(u32 cipher) | ||
3949 | { | ||
3950 | return cipher == WLAN_CIPHER_SUITE_WEP40 || | ||
3951 | cipher == WLAN_CIPHER_SUITE_WEP104 || | ||
3952 | cipher == WLAN_CIPHER_SUITE_TKIP || | ||
3953 | cipher == WLAN_CIPHER_SUITE_CCMP || | ||
3954 | cipher == WLAN_CIPHER_SUITE_AES_CMAC; | ||
3955 | } | ||
3956 | |||
3957 | |||
5066 | static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | 3958 | static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) |
5067 | { | 3959 | { |
5068 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 3960 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
5069 | struct net_device *dev = info->user_ptr[1]; | 3961 | struct net_device *dev = info->user_ptr[1]; |
5070 | struct ieee80211_channel *chan; | 3962 | struct ieee80211_channel *chan; |
5071 | const u8 *bssid, *ssid, *ie = NULL, *sae_data = NULL; | 3963 | const u8 *bssid, *ssid, *ie = NULL; |
5072 | int err, ssid_len, ie_len = 0, sae_data_len = 0; | 3964 | int err, ssid_len, ie_len = 0; |
5073 | enum nl80211_auth_type auth_type; | 3965 | enum nl80211_auth_type auth_type; |
5074 | struct key_parse key; | 3966 | struct key_parse key; |
5075 | bool local_state_change; | 3967 | bool local_state_change; |
@@ -5145,36 +4037,15 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
5145 | } | 4037 | } |
5146 | 4038 | ||
5147 | auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]); | 4039 | auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]); |
5148 | if (!nl80211_valid_auth_type(rdev, auth_type, NL80211_CMD_AUTHENTICATE)) | 4040 | if (!nl80211_valid_auth_type(auth_type)) |
5149 | return -EINVAL; | ||
5150 | |||
5151 | if (auth_type == NL80211_AUTHTYPE_SAE && | ||
5152 | !info->attrs[NL80211_ATTR_SAE_DATA]) | ||
5153 | return -EINVAL; | 4041 | return -EINVAL; |
5154 | 4042 | ||
5155 | if (info->attrs[NL80211_ATTR_SAE_DATA]) { | ||
5156 | if (auth_type != NL80211_AUTHTYPE_SAE) | ||
5157 | return -EINVAL; | ||
5158 | sae_data = nla_data(info->attrs[NL80211_ATTR_SAE_DATA]); | ||
5159 | sae_data_len = nla_len(info->attrs[NL80211_ATTR_SAE_DATA]); | ||
5160 | /* need to include at least Auth Transaction and Status Code */ | ||
5161 | if (sae_data_len < 4) | ||
5162 | return -EINVAL; | ||
5163 | } | ||
5164 | |||
5165 | local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; | 4043 | local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; |
5166 | 4044 | ||
5167 | /* | ||
5168 | * Since we no longer track auth state, ignore | ||
5169 | * requests to only change local state. | ||
5170 | */ | ||
5171 | if (local_state_change) | ||
5172 | return 0; | ||
5173 | |||
5174 | return cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, | 4045 | return cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, |
5175 | ssid, ssid_len, ie, ie_len, | 4046 | ssid, ssid_len, ie, ie_len, |
5176 | key.p.key, key.p.key_len, key.idx, | 4047 | key.p.key, key.p.key_len, key.idx, |
5177 | sae_data, sae_data_len); | 4048 | local_state_change); |
5178 | } | 4049 | } |
5179 | 4050 | ||
5180 | static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, | 4051 | static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, |
@@ -5216,8 +4087,7 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, | |||
5216 | memcpy(settings->ciphers_pairwise, data, len); | 4087 | memcpy(settings->ciphers_pairwise, data, len); |
5217 | 4088 | ||
5218 | for (i = 0; i < settings->n_ciphers_pairwise; i++) | 4089 | for (i = 0; i < settings->n_ciphers_pairwise; i++) |
5219 | if (!cfg80211_supported_cipher_suite( | 4090 | if (!nl80211_valid_cipher_suite( |
5220 | &rdev->wiphy, | ||
5221 | settings->ciphers_pairwise[i])) | 4091 | settings->ciphers_pairwise[i])) |
5222 | return -EINVAL; | 4092 | return -EINVAL; |
5223 | } | 4093 | } |
@@ -5225,8 +4095,7 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, | |||
5225 | if (info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]) { | 4095 | if (info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]) { |
5226 | settings->cipher_group = | 4096 | settings->cipher_group = |
5227 | nla_get_u32(info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]); | 4097 | nla_get_u32(info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]); |
5228 | if (!cfg80211_supported_cipher_suite(&rdev->wiphy, | 4098 | if (!nl80211_valid_cipher_suite(settings->cipher_group)) |
5229 | settings->cipher_group)) | ||
5230 | return -EINVAL; | 4099 | return -EINVAL; |
5231 | } | 4100 | } |
5232 | 4101 | ||
@@ -5239,7 +4108,7 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, | |||
5239 | 4108 | ||
5240 | if (info->attrs[NL80211_ATTR_AKM_SUITES]) { | 4109 | if (info->attrs[NL80211_ATTR_AKM_SUITES]) { |
5241 | void *data; | 4110 | void *data; |
5242 | int len; | 4111 | int len, i; |
5243 | 4112 | ||
5244 | data = nla_data(info->attrs[NL80211_ATTR_AKM_SUITES]); | 4113 | data = nla_data(info->attrs[NL80211_ATTR_AKM_SUITES]); |
5245 | len = nla_len(info->attrs[NL80211_ATTR_AKM_SUITES]); | 4114 | len = nla_len(info->attrs[NL80211_ATTR_AKM_SUITES]); |
@@ -5252,6 +4121,10 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, | |||
5252 | return -EINVAL; | 4121 | return -EINVAL; |
5253 | 4122 | ||
5254 | memcpy(settings->akm_suites, data, len); | 4123 | memcpy(settings->akm_suites, data, len); |
4124 | |||
4125 | for (i = 0; i < settings->n_akm_suites; i++) | ||
4126 | if (!nl80211_valid_akm_suite(settings->akm_suites[i])) | ||
4127 | return -EINVAL; | ||
5255 | } | 4128 | } |
5256 | 4129 | ||
5257 | return 0; | 4130 | return 0; |
@@ -5266,9 +4139,6 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) | |||
5266 | const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL; | 4139 | const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL; |
5267 | int err, ssid_len, ie_len = 0; | 4140 | int err, ssid_len, ie_len = 0; |
5268 | bool use_mfp = false; | 4141 | bool use_mfp = false; |
5269 | u32 flags = 0; | ||
5270 | struct ieee80211_ht_cap *ht_capa = NULL; | ||
5271 | struct ieee80211_ht_cap *ht_capa_mask = NULL; | ||
5272 | 4142 | ||
5273 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | 4143 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) |
5274 | return -EINVAL; | 4144 | return -EINVAL; |
@@ -5312,25 +4182,11 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) | |||
5312 | if (info->attrs[NL80211_ATTR_PREV_BSSID]) | 4182 | if (info->attrs[NL80211_ATTR_PREV_BSSID]) |
5313 | prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]); | 4183 | prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]); |
5314 | 4184 | ||
5315 | if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT])) | ||
5316 | flags |= ASSOC_REQ_DISABLE_HT; | ||
5317 | |||
5318 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) | ||
5319 | ht_capa_mask = | ||
5320 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]); | ||
5321 | |||
5322 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) { | ||
5323 | if (!ht_capa_mask) | ||
5324 | return -EINVAL; | ||
5325 | ht_capa = nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); | ||
5326 | } | ||
5327 | |||
5328 | err = nl80211_crypto_settings(rdev, info, &crypto, 1); | 4185 | err = nl80211_crypto_settings(rdev, info, &crypto, 1); |
5329 | if (!err) | 4186 | if (!err) |
5330 | err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid, | 4187 | err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid, |
5331 | ssid, ssid_len, ie, ie_len, use_mfp, | 4188 | ssid, ssid_len, ie, ie_len, use_mfp, |
5332 | &crypto, flags, ht_capa, | 4189 | &crypto); |
5333 | ht_capa_mask); | ||
5334 | 4190 | ||
5335 | return err; | 4191 | return err; |
5336 | } | 4192 | } |
@@ -5465,7 +4321,8 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
5465 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | 4321 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) |
5466 | return -EINVAL; | 4322 | return -EINVAL; |
5467 | 4323 | ||
5468 | if (!info->attrs[NL80211_ATTR_SSID] || | 4324 | if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] || |
4325 | !info->attrs[NL80211_ATTR_SSID] || | ||
5469 | !nla_len(info->attrs[NL80211_ATTR_SSID])) | 4326 | !nla_len(info->attrs[NL80211_ATTR_SSID])) |
5470 | return -EINVAL; | 4327 | return -EINVAL; |
5471 | 4328 | ||
@@ -5486,12 +4343,8 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
5486 | 4343 | ||
5487 | wiphy = &rdev->wiphy; | 4344 | wiphy = &rdev->wiphy; |
5488 | 4345 | ||
5489 | if (info->attrs[NL80211_ATTR_MAC]) { | 4346 | if (info->attrs[NL80211_ATTR_MAC]) |
5490 | ibss.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); | 4347 | ibss.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); |
5491 | |||
5492 | if (!is_valid_ether_addr(ibss.bssid)) | ||
5493 | return -EINVAL; | ||
5494 | } | ||
5495 | ibss.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); | 4348 | ibss.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); |
5496 | ibss.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); | 4349 | ibss.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); |
5497 | 4350 | ||
@@ -5500,17 +4353,11 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
5500 | ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | 4353 | ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); |
5501 | } | 4354 | } |
5502 | 4355 | ||
5503 | err = nl80211_parse_chandef(rdev, info, &ibss.chandef); | 4356 | ibss.channel = ieee80211_get_channel(wiphy, |
5504 | if (err) | 4357 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); |
5505 | return err; | 4358 | if (!ibss.channel || |
5506 | 4359 | ibss.channel->flags & IEEE80211_CHAN_NO_IBSS || | |
5507 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef)) | 4360 | ibss.channel->flags & IEEE80211_CHAN_DISABLED) |
5508 | return -EINVAL; | ||
5509 | |||
5510 | if (ibss.chandef.width > NL80211_CHAN_WIDTH_40) | ||
5511 | return -EINVAL; | ||
5512 | if (ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT && | ||
5513 | !(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS)) | ||
5514 | return -EINVAL; | 4361 | return -EINVAL; |
5515 | 4362 | ||
5516 | ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; | 4363 | ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; |
@@ -5522,7 +4369,8 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
5522 | int n_rates = | 4369 | int n_rates = |
5523 | nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); | 4370 | nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); |
5524 | struct ieee80211_supported_band *sband = | 4371 | struct ieee80211_supported_band *sband = |
5525 | wiphy->bands[ibss.chandef.chan->band]; | 4372 | wiphy->bands[ibss.channel->band]; |
4373 | int err; | ||
5526 | 4374 | ||
5527 | err = ieee80211_get_ratemask(sband, rates, n_rates, | 4375 | err = ieee80211_get_ratemask(sband, rates, n_rates, |
5528 | &ibss.basic_rates); | 4376 | &ibss.basic_rates); |
@@ -5536,24 +4384,12 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
5536 | return -EINVAL; | 4384 | return -EINVAL; |
5537 | 4385 | ||
5538 | if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) { | 4386 | if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) { |
5539 | bool no_ht = false; | ||
5540 | |||
5541 | connkeys = nl80211_parse_connkeys(rdev, | 4387 | connkeys = nl80211_parse_connkeys(rdev, |
5542 | info->attrs[NL80211_ATTR_KEYS], | 4388 | info->attrs[NL80211_ATTR_KEYS]); |
5543 | &no_ht); | ||
5544 | if (IS_ERR(connkeys)) | 4389 | if (IS_ERR(connkeys)) |
5545 | return PTR_ERR(connkeys); | 4390 | return PTR_ERR(connkeys); |
5546 | |||
5547 | if ((ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) && | ||
5548 | no_ht) { | ||
5549 | kfree(connkeys); | ||
5550 | return -EINVAL; | ||
5551 | } | ||
5552 | } | 4391 | } |
5553 | 4392 | ||
5554 | ibss.control_port = | ||
5555 | nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT]); | ||
5556 | |||
5557 | err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys); | 4393 | err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys); |
5558 | if (err) | 4394 | if (err) |
5559 | kfree(connkeys); | 4395 | kfree(connkeys); |
@@ -5574,36 +4410,6 @@ static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info) | |||
5574 | return cfg80211_leave_ibss(rdev, dev, false); | 4410 | return cfg80211_leave_ibss(rdev, dev, false); |
5575 | } | 4411 | } |
5576 | 4412 | ||
5577 | static int nl80211_set_mcast_rate(struct sk_buff *skb, struct genl_info *info) | ||
5578 | { | ||
5579 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
5580 | struct net_device *dev = info->user_ptr[1]; | ||
5581 | int mcast_rate[IEEE80211_NUM_BANDS]; | ||
5582 | u32 nla_rate; | ||
5583 | int err; | ||
5584 | |||
5585 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC && | ||
5586 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) | ||
5587 | return -EOPNOTSUPP; | ||
5588 | |||
5589 | if (!rdev->ops->set_mcast_rate) | ||
5590 | return -EOPNOTSUPP; | ||
5591 | |||
5592 | memset(mcast_rate, 0, sizeof(mcast_rate)); | ||
5593 | |||
5594 | if (!info->attrs[NL80211_ATTR_MCAST_RATE]) | ||
5595 | return -EINVAL; | ||
5596 | |||
5597 | nla_rate = nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE]); | ||
5598 | if (!nl80211_parse_mcast_rate(rdev, mcast_rate, nla_rate)) | ||
5599 | return -EINVAL; | ||
5600 | |||
5601 | err = rdev->ops->set_mcast_rate(&rdev->wiphy, dev, mcast_rate); | ||
5602 | |||
5603 | return err; | ||
5604 | } | ||
5605 | |||
5606 | |||
5607 | #ifdef CONFIG_NL80211_TESTMODE | 4413 | #ifdef CONFIG_NL80211_TESTMODE |
5608 | static struct genl_multicast_group nl80211_testmode_mcgrp = { | 4414 | static struct genl_multicast_group nl80211_testmode_mcgrp = { |
5609 | .name = "testmode", | 4415 | .name = "testmode", |
@@ -5620,7 +4426,7 @@ static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info) | |||
5620 | err = -EOPNOTSUPP; | 4426 | err = -EOPNOTSUPP; |
5621 | if (rdev->ops->testmode_cmd) { | 4427 | if (rdev->ops->testmode_cmd) { |
5622 | rdev->testmode_info = info; | 4428 | rdev->testmode_info = info; |
5623 | err = rdev_testmode_cmd(rdev, | 4429 | err = rdev->ops->testmode_cmd(&rdev->wiphy, |
5624 | nla_data(info->attrs[NL80211_ATTR_TESTDATA]), | 4430 | nla_data(info->attrs[NL80211_ATTR_TESTDATA]), |
5625 | nla_len(info->attrs[NL80211_ATTR_TESTDATA])); | 4431 | nla_len(info->attrs[NL80211_ATTR_TESTDATA])); |
5626 | rdev->testmode_info = NULL; | 4432 | rdev->testmode_info = NULL; |
@@ -5632,7 +4438,7 @@ static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info) | |||
5632 | static int nl80211_testmode_dump(struct sk_buff *skb, | 4438 | static int nl80211_testmode_dump(struct sk_buff *skb, |
5633 | struct netlink_callback *cb) | 4439 | struct netlink_callback *cb) |
5634 | { | 4440 | { |
5635 | struct cfg80211_registered_device *rdev; | 4441 | struct cfg80211_registered_device *dev; |
5636 | int err; | 4442 | int err; |
5637 | long phy_idx; | 4443 | long phy_idx; |
5638 | void *data = NULL; | 4444 | void *data = NULL; |
@@ -5650,18 +4456,9 @@ static int nl80211_testmode_dump(struct sk_buff *skb, | |||
5650 | nl80211_policy); | 4456 | nl80211_policy); |
5651 | if (err) | 4457 | if (err) |
5652 | return err; | 4458 | return err; |
5653 | 4459 | if (!nl80211_fam.attrbuf[NL80211_ATTR_WIPHY]) | |
5654 | mutex_lock(&cfg80211_mutex); | 4460 | return -EINVAL; |
5655 | rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), | 4461 | phy_idx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_WIPHY]); |
5656 | nl80211_fam.attrbuf); | ||
5657 | if (IS_ERR(rdev)) { | ||
5658 | mutex_unlock(&cfg80211_mutex); | ||
5659 | return PTR_ERR(rdev); | ||
5660 | } | ||
5661 | phy_idx = rdev->wiphy_idx; | ||
5662 | rdev = NULL; | ||
5663 | mutex_unlock(&cfg80211_mutex); | ||
5664 | |||
5665 | if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA]) | 4462 | if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA]) |
5666 | cb->args[1] = | 4463 | cb->args[1] = |
5667 | (long)nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA]; | 4464 | (long)nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA]; |
@@ -5673,26 +4470,26 @@ static int nl80211_testmode_dump(struct sk_buff *skb, | |||
5673 | } | 4470 | } |
5674 | 4471 | ||
5675 | mutex_lock(&cfg80211_mutex); | 4472 | mutex_lock(&cfg80211_mutex); |
5676 | rdev = cfg80211_rdev_by_wiphy_idx(phy_idx); | 4473 | dev = cfg80211_rdev_by_wiphy_idx(phy_idx); |
5677 | if (!rdev) { | 4474 | if (!dev) { |
5678 | mutex_unlock(&cfg80211_mutex); | 4475 | mutex_unlock(&cfg80211_mutex); |
5679 | return -ENOENT; | 4476 | return -ENOENT; |
5680 | } | 4477 | } |
5681 | cfg80211_lock_rdev(rdev); | 4478 | cfg80211_lock_rdev(dev); |
5682 | mutex_unlock(&cfg80211_mutex); | 4479 | mutex_unlock(&cfg80211_mutex); |
5683 | 4480 | ||
5684 | if (!rdev->ops->testmode_dump) { | 4481 | if (!dev->ops->testmode_dump) { |
5685 | err = -EOPNOTSUPP; | 4482 | err = -EOPNOTSUPP; |
5686 | goto out_err; | 4483 | goto out_err; |
5687 | } | 4484 | } |
5688 | 4485 | ||
5689 | while (1) { | 4486 | while (1) { |
5690 | void *hdr = nl80211hdr_put(skb, NETLINK_CB(cb->skb).portid, | 4487 | void *hdr = nl80211hdr_put(skb, NETLINK_CB(cb->skb).pid, |
5691 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 4488 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
5692 | NL80211_CMD_TESTMODE); | 4489 | NL80211_CMD_TESTMODE); |
5693 | struct nlattr *tmdata; | 4490 | struct nlattr *tmdata; |
5694 | 4491 | ||
5695 | if (nla_put_u32(skb, NL80211_ATTR_WIPHY, phy_idx)) { | 4492 | if (nla_put_u32(skb, NL80211_ATTR_WIPHY, dev->wiphy_idx) < 0) { |
5696 | genlmsg_cancel(skb, hdr); | 4493 | genlmsg_cancel(skb, hdr); |
5697 | break; | 4494 | break; |
5698 | } | 4495 | } |
@@ -5702,7 +4499,8 @@ static int nl80211_testmode_dump(struct sk_buff *skb, | |||
5702 | genlmsg_cancel(skb, hdr); | 4499 | genlmsg_cancel(skb, hdr); |
5703 | break; | 4500 | break; |
5704 | } | 4501 | } |
5705 | err = rdev_testmode_dump(rdev, skb, cb, data, data_len); | 4502 | err = dev->ops->testmode_dump(&dev->wiphy, skb, cb, |
4503 | data, data_len); | ||
5706 | nla_nest_end(skb, tmdata); | 4504 | nla_nest_end(skb, tmdata); |
5707 | 4505 | ||
5708 | if (err == -ENOBUFS || err == -ENOENT) { | 4506 | if (err == -ENOBUFS || err == -ENOENT) { |
@@ -5720,13 +4518,13 @@ static int nl80211_testmode_dump(struct sk_buff *skb, | |||
5720 | /* see above */ | 4518 | /* see above */ |
5721 | cb->args[0] = phy_idx + 1; | 4519 | cb->args[0] = phy_idx + 1; |
5722 | out_err: | 4520 | out_err: |
5723 | cfg80211_unlock_rdev(rdev); | 4521 | cfg80211_unlock_rdev(dev); |
5724 | return err; | 4522 | return err; |
5725 | } | 4523 | } |
5726 | 4524 | ||
5727 | static struct sk_buff * | 4525 | static struct sk_buff * |
5728 | __cfg80211_testmode_alloc_skb(struct cfg80211_registered_device *rdev, | 4526 | __cfg80211_testmode_alloc_skb(struct cfg80211_registered_device *rdev, |
5729 | int approxlen, u32 portid, u32 seq, gfp_t gfp) | 4527 | int approxlen, u32 pid, u32 seq, gfp_t gfp) |
5730 | { | 4528 | { |
5731 | struct sk_buff *skb; | 4529 | struct sk_buff *skb; |
5732 | void *hdr; | 4530 | void *hdr; |
@@ -5736,14 +4534,13 @@ __cfg80211_testmode_alloc_skb(struct cfg80211_registered_device *rdev, | |||
5736 | if (!skb) | 4534 | if (!skb) |
5737 | return NULL; | 4535 | return NULL; |
5738 | 4536 | ||
5739 | hdr = nl80211hdr_put(skb, portid, seq, 0, NL80211_CMD_TESTMODE); | 4537 | hdr = nl80211hdr_put(skb, pid, seq, 0, NL80211_CMD_TESTMODE); |
5740 | if (!hdr) { | 4538 | if (!hdr) { |
5741 | kfree_skb(skb); | 4539 | kfree_skb(skb); |
5742 | return NULL; | 4540 | return NULL; |
5743 | } | 4541 | } |
5744 | 4542 | ||
5745 | if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx)) | 4543 | NLA_PUT_U32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx); |
5746 | goto nla_put_failure; | ||
5747 | data = nla_nest_start(skb, NL80211_ATTR_TESTDATA); | 4544 | data = nla_nest_start(skb, NL80211_ATTR_TESTDATA); |
5748 | 4545 | ||
5749 | ((void **)skb->cb)[0] = rdev; | 4546 | ((void **)skb->cb)[0] = rdev; |
@@ -5766,7 +4563,7 @@ struct sk_buff *cfg80211_testmode_alloc_reply_skb(struct wiphy *wiphy, | |||
5766 | return NULL; | 4563 | return NULL; |
5767 | 4564 | ||
5768 | return __cfg80211_testmode_alloc_skb(rdev, approxlen, | 4565 | return __cfg80211_testmode_alloc_skb(rdev, approxlen, |
5769 | rdev->testmode_info->snd_portid, | 4566 | rdev->testmode_info->snd_pid, |
5770 | rdev->testmode_info->snd_seq, | 4567 | rdev->testmode_info->snd_seq, |
5771 | GFP_KERNEL); | 4568 | GFP_KERNEL); |
5772 | } | 4569 | } |
@@ -5831,8 +4628,7 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) | |||
5831 | if (info->attrs[NL80211_ATTR_AUTH_TYPE]) { | 4628 | if (info->attrs[NL80211_ATTR_AUTH_TYPE]) { |
5832 | connect.auth_type = | 4629 | connect.auth_type = |
5833 | nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]); | 4630 | nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]); |
5834 | if (!nl80211_valid_auth_type(rdev, connect.auth_type, | 4631 | if (!nl80211_valid_auth_type(connect.auth_type)) |
5835 | NL80211_CMD_CONNECT)) | ||
5836 | return -EINVAL; | 4632 | return -EINVAL; |
5837 | } else | 4633 | } else |
5838 | connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; | 4634 | connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; |
@@ -5850,13 +4646,6 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) | |||
5850 | 4646 | ||
5851 | wiphy = &rdev->wiphy; | 4647 | wiphy = &rdev->wiphy; |
5852 | 4648 | ||
5853 | connect.bg_scan_period = -1; | ||
5854 | if (info->attrs[NL80211_ATTR_BG_SCAN_PERIOD] && | ||
5855 | (wiphy->flags & WIPHY_FLAG_SUPPORTS_FW_ROAM)) { | ||
5856 | connect.bg_scan_period = | ||
5857 | nla_get_u16(info->attrs[NL80211_ATTR_BG_SCAN_PERIOD]); | ||
5858 | } | ||
5859 | |||
5860 | if (info->attrs[NL80211_ATTR_MAC]) | 4649 | if (info->attrs[NL80211_ATTR_MAC]) |
5861 | connect.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); | 4650 | connect.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); |
5862 | connect.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); | 4651 | connect.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); |
@@ -5878,29 +4667,11 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) | |||
5878 | 4667 | ||
5879 | if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) { | 4668 | if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) { |
5880 | connkeys = nl80211_parse_connkeys(rdev, | 4669 | connkeys = nl80211_parse_connkeys(rdev, |
5881 | info->attrs[NL80211_ATTR_KEYS], NULL); | 4670 | info->attrs[NL80211_ATTR_KEYS]); |
5882 | if (IS_ERR(connkeys)) | 4671 | if (IS_ERR(connkeys)) |
5883 | return PTR_ERR(connkeys); | 4672 | return PTR_ERR(connkeys); |
5884 | } | 4673 | } |
5885 | 4674 | ||
5886 | if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT])) | ||
5887 | connect.flags |= ASSOC_REQ_DISABLE_HT; | ||
5888 | |||
5889 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) | ||
5890 | memcpy(&connect.ht_capa_mask, | ||
5891 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]), | ||
5892 | sizeof(connect.ht_capa_mask)); | ||
5893 | |||
5894 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) { | ||
5895 | if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) { | ||
5896 | kfree(connkeys); | ||
5897 | return -EINVAL; | ||
5898 | } | ||
5899 | memcpy(&connect.ht_capa, | ||
5900 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]), | ||
5901 | sizeof(connect.ht_capa)); | ||
5902 | } | ||
5903 | |||
5904 | err = cfg80211_connect(rdev, dev, &connect, connkeys); | 4675 | err = cfg80211_connect(rdev, dev, &connect, connkeys); |
5905 | if (err) | 4676 | if (err) |
5906 | kfree(connkeys); | 4677 | kfree(connkeys); |
@@ -6007,70 +4778,20 @@ static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info) | |||
6007 | if (!rdev->ops->flush_pmksa) | 4778 | if (!rdev->ops->flush_pmksa) |
6008 | return -EOPNOTSUPP; | 4779 | return -EOPNOTSUPP; |
6009 | 4780 | ||
6010 | return rdev_flush_pmksa(rdev, dev); | 4781 | return rdev->ops->flush_pmksa(&rdev->wiphy, dev); |
6011 | } | ||
6012 | |||
6013 | static int nl80211_tdls_mgmt(struct sk_buff *skb, struct genl_info *info) | ||
6014 | { | ||
6015 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
6016 | struct net_device *dev = info->user_ptr[1]; | ||
6017 | u8 action_code, dialog_token; | ||
6018 | u16 status_code; | ||
6019 | u8 *peer; | ||
6020 | |||
6021 | if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) || | ||
6022 | !rdev->ops->tdls_mgmt) | ||
6023 | return -EOPNOTSUPP; | ||
6024 | |||
6025 | if (!info->attrs[NL80211_ATTR_TDLS_ACTION] || | ||
6026 | !info->attrs[NL80211_ATTR_STATUS_CODE] || | ||
6027 | !info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN] || | ||
6028 | !info->attrs[NL80211_ATTR_IE] || | ||
6029 | !info->attrs[NL80211_ATTR_MAC]) | ||
6030 | return -EINVAL; | ||
6031 | |||
6032 | peer = nla_data(info->attrs[NL80211_ATTR_MAC]); | ||
6033 | action_code = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_ACTION]); | ||
6034 | status_code = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]); | ||
6035 | dialog_token = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN]); | ||
6036 | |||
6037 | return rdev_tdls_mgmt(rdev, dev, peer, action_code, | ||
6038 | dialog_token, status_code, | ||
6039 | nla_data(info->attrs[NL80211_ATTR_IE]), | ||
6040 | nla_len(info->attrs[NL80211_ATTR_IE])); | ||
6041 | } | ||
6042 | |||
6043 | static int nl80211_tdls_oper(struct sk_buff *skb, struct genl_info *info) | ||
6044 | { | ||
6045 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
6046 | struct net_device *dev = info->user_ptr[1]; | ||
6047 | enum nl80211_tdls_operation operation; | ||
6048 | u8 *peer; | ||
6049 | |||
6050 | if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) || | ||
6051 | !rdev->ops->tdls_oper) | ||
6052 | return -EOPNOTSUPP; | ||
6053 | |||
6054 | if (!info->attrs[NL80211_ATTR_TDLS_OPERATION] || | ||
6055 | !info->attrs[NL80211_ATTR_MAC]) | ||
6056 | return -EINVAL; | ||
6057 | |||
6058 | operation = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_OPERATION]); | ||
6059 | peer = nla_data(info->attrs[NL80211_ATTR_MAC]); | ||
6060 | |||
6061 | return rdev_tdls_oper(rdev, dev, peer, operation); | ||
6062 | } | 4782 | } |
6063 | 4783 | ||
6064 | static int nl80211_remain_on_channel(struct sk_buff *skb, | 4784 | static int nl80211_remain_on_channel(struct sk_buff *skb, |
6065 | struct genl_info *info) | 4785 | struct genl_info *info) |
6066 | { | 4786 | { |
6067 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 4787 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
6068 | struct wireless_dev *wdev = info->user_ptr[1]; | 4788 | struct net_device *dev = info->user_ptr[1]; |
6069 | struct cfg80211_chan_def chandef; | 4789 | struct ieee80211_channel *chan; |
6070 | struct sk_buff *msg; | 4790 | struct sk_buff *msg; |
6071 | void *hdr; | 4791 | void *hdr; |
6072 | u64 cookie; | 4792 | u64 cookie; |
6073 | u32 duration; | 4793 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; |
4794 | u32 freq, duration; | ||
6074 | int err; | 4795 | int err; |
6075 | 4796 | ||
6076 | if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] || | 4797 | if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] || |
@@ -6079,27 +4800,37 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, | |||
6079 | 4800 | ||
6080 | duration = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]); | 4801 | duration = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]); |
6081 | 4802 | ||
6082 | if (!rdev->ops->remain_on_channel || | ||
6083 | !(rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL)) | ||
6084 | return -EOPNOTSUPP; | ||
6085 | |||
6086 | /* | 4803 | /* |
6087 | * We should be on that channel for at least a minimum amount of | 4804 | * We should be on that channel for at least one jiffie, |
6088 | * time (10ms) but no longer than the driver supports. | 4805 | * and more than 5 seconds seems excessive. |
6089 | */ | 4806 | */ |
6090 | if (duration < NL80211_MIN_REMAIN_ON_CHANNEL_TIME || | 4807 | if (!duration || !msecs_to_jiffies(duration) || |
6091 | duration > rdev->wiphy.max_remain_on_channel_duration) | 4808 | duration > rdev->wiphy.max_remain_on_channel_duration) |
6092 | return -EINVAL; | 4809 | return -EINVAL; |
6093 | 4810 | ||
6094 | err = nl80211_parse_chandef(rdev, info, &chandef); | 4811 | if (!rdev->ops->remain_on_channel) |
6095 | if (err) | 4812 | return -EOPNOTSUPP; |
6096 | return err; | 4813 | |
4814 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { | ||
4815 | channel_type = nla_get_u32( | ||
4816 | info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]); | ||
4817 | if (channel_type != NL80211_CHAN_NO_HT && | ||
4818 | channel_type != NL80211_CHAN_HT20 && | ||
4819 | channel_type != NL80211_CHAN_HT40PLUS && | ||
4820 | channel_type != NL80211_CHAN_HT40MINUS) | ||
4821 | return -EINVAL; | ||
4822 | } | ||
4823 | |||
4824 | freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); | ||
4825 | chan = rdev_freq_to_chan(rdev, freq, channel_type); | ||
4826 | if (chan == NULL) | ||
4827 | return -EINVAL; | ||
6097 | 4828 | ||
6098 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 4829 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
6099 | if (!msg) | 4830 | if (!msg) |
6100 | return -ENOMEM; | 4831 | return -ENOMEM; |
6101 | 4832 | ||
6102 | hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0, | 4833 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, |
6103 | NL80211_CMD_REMAIN_ON_CHANNEL); | 4834 | NL80211_CMD_REMAIN_ON_CHANNEL); |
6104 | 4835 | ||
6105 | if (IS_ERR(hdr)) { | 4836 | if (IS_ERR(hdr)) { |
@@ -6107,14 +4838,13 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, | |||
6107 | goto free_msg; | 4838 | goto free_msg; |
6108 | } | 4839 | } |
6109 | 4840 | ||
6110 | err = rdev_remain_on_channel(rdev, wdev, chandef.chan, | 4841 | err = rdev->ops->remain_on_channel(&rdev->wiphy, dev, chan, |
6111 | duration, &cookie); | 4842 | channel_type, duration, &cookie); |
6112 | 4843 | ||
6113 | if (err) | 4844 | if (err) |
6114 | goto free_msg; | 4845 | goto free_msg; |
6115 | 4846 | ||
6116 | if (nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie)) | 4847 | NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie); |
6117 | goto nla_put_failure; | ||
6118 | 4848 | ||
6119 | genlmsg_end(msg, hdr); | 4849 | genlmsg_end(msg, hdr); |
6120 | 4850 | ||
@@ -6131,7 +4861,7 @@ static int nl80211_cancel_remain_on_channel(struct sk_buff *skb, | |||
6131 | struct genl_info *info) | 4861 | struct genl_info *info) |
6132 | { | 4862 | { |
6133 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 4863 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
6134 | struct wireless_dev *wdev = info->user_ptr[1]; | 4864 | struct net_device *dev = info->user_ptr[1]; |
6135 | u64 cookie; | 4865 | u64 cookie; |
6136 | 4866 | ||
6137 | if (!info->attrs[NL80211_ATTR_COOKIE]) | 4867 | if (!info->attrs[NL80211_ATTR_COOKIE]) |
@@ -6142,7 +4872,7 @@ static int nl80211_cancel_remain_on_channel(struct sk_buff *skb, | |||
6142 | 4872 | ||
6143 | cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]); | 4873 | cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]); |
6144 | 4874 | ||
6145 | return rdev_cancel_remain_on_channel(rdev, wdev, cookie); | 4875 | return rdev->ops->cancel_remain_on_channel(&rdev->wiphy, dev, cookie); |
6146 | } | 4876 | } |
6147 | 4877 | ||
6148 | static u32 rateset_to_mask(struct ieee80211_supported_band *sband, | 4878 | static u32 rateset_to_mask(struct ieee80211_supported_band *sband, |
@@ -6169,39 +4899,9 @@ static u32 rateset_to_mask(struct ieee80211_supported_band *sband, | |||
6169 | return mask; | 4899 | return mask; |
6170 | } | 4900 | } |
6171 | 4901 | ||
6172 | static bool ht_rateset_to_mask(struct ieee80211_supported_band *sband, | ||
6173 | u8 *rates, u8 rates_len, | ||
6174 | u8 mcs[IEEE80211_HT_MCS_MASK_LEN]) | ||
6175 | { | ||
6176 | u8 i; | ||
6177 | |||
6178 | memset(mcs, 0, IEEE80211_HT_MCS_MASK_LEN); | ||
6179 | |||
6180 | for (i = 0; i < rates_len; i++) { | ||
6181 | int ridx, rbit; | ||
6182 | |||
6183 | ridx = rates[i] / 8; | ||
6184 | rbit = BIT(rates[i] % 8); | ||
6185 | |||
6186 | /* check validity */ | ||
6187 | if ((ridx < 0) || (ridx >= IEEE80211_HT_MCS_MASK_LEN)) | ||
6188 | return false; | ||
6189 | |||
6190 | /* check availability */ | ||
6191 | if (sband->ht_cap.mcs.rx_mask[ridx] & rbit) | ||
6192 | mcs[ridx] |= rbit; | ||
6193 | else | ||
6194 | return false; | ||
6195 | } | ||
6196 | |||
6197 | return true; | ||
6198 | } | ||
6199 | |||
6200 | static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = { | 4902 | static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = { |
6201 | [NL80211_TXRATE_LEGACY] = { .type = NLA_BINARY, | 4903 | [NL80211_TXRATE_LEGACY] = { .type = NLA_BINARY, |
6202 | .len = NL80211_MAX_SUPP_RATES }, | 4904 | .len = NL80211_MAX_SUPP_RATES }, |
6203 | [NL80211_TXRATE_MCS] = { .type = NLA_BINARY, | ||
6204 | .len = NL80211_MAX_SUPP_HT_RATES }, | ||
6205 | }; | 4905 | }; |
6206 | 4906 | ||
6207 | static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, | 4907 | static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, |
@@ -6227,20 +4927,12 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, | |||
6227 | sband = rdev->wiphy.bands[i]; | 4927 | sband = rdev->wiphy.bands[i]; |
6228 | mask.control[i].legacy = | 4928 | mask.control[i].legacy = |
6229 | sband ? (1 << sband->n_bitrates) - 1 : 0; | 4929 | sband ? (1 << sband->n_bitrates) - 1 : 0; |
6230 | if (sband) | ||
6231 | memcpy(mask.control[i].mcs, | ||
6232 | sband->ht_cap.mcs.rx_mask, | ||
6233 | sizeof(mask.control[i].mcs)); | ||
6234 | else | ||
6235 | memset(mask.control[i].mcs, 0, | ||
6236 | sizeof(mask.control[i].mcs)); | ||
6237 | } | 4930 | } |
6238 | 4931 | ||
6239 | /* | 4932 | /* |
6240 | * The nested attribute uses enum nl80211_band as the index. This maps | 4933 | * The nested attribute uses enum nl80211_band as the index. This maps |
6241 | * directly to the enum ieee80211_band values used in cfg80211. | 4934 | * directly to the enum ieee80211_band values used in cfg80211. |
6242 | */ | 4935 | */ |
6243 | BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8); | ||
6244 | nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) | 4936 | nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) |
6245 | { | 4937 | { |
6246 | enum ieee80211_band band = nla_type(tx_rates); | 4938 | enum ieee80211_band band = nla_type(tx_rates); |
@@ -6256,42 +4948,18 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, | |||
6256 | sband, | 4948 | sband, |
6257 | nla_data(tb[NL80211_TXRATE_LEGACY]), | 4949 | nla_data(tb[NL80211_TXRATE_LEGACY]), |
6258 | nla_len(tb[NL80211_TXRATE_LEGACY])); | 4950 | nla_len(tb[NL80211_TXRATE_LEGACY])); |
6259 | if ((mask.control[band].legacy == 0) && | 4951 | if (mask.control[band].legacy == 0) |
6260 | nla_len(tb[NL80211_TXRATE_LEGACY])) | ||
6261 | return -EINVAL; | ||
6262 | } | ||
6263 | if (tb[NL80211_TXRATE_MCS]) { | ||
6264 | if (!ht_rateset_to_mask( | ||
6265 | sband, | ||
6266 | nla_data(tb[NL80211_TXRATE_MCS]), | ||
6267 | nla_len(tb[NL80211_TXRATE_MCS]), | ||
6268 | mask.control[band].mcs)) | ||
6269 | return -EINVAL; | ||
6270 | } | ||
6271 | |||
6272 | if (mask.control[band].legacy == 0) { | ||
6273 | /* don't allow empty legacy rates if HT | ||
6274 | * is not even supported. */ | ||
6275 | if (!rdev->wiphy.bands[band]->ht_cap.ht_supported) | ||
6276 | return -EINVAL; | ||
6277 | |||
6278 | for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) | ||
6279 | if (mask.control[band].mcs[i]) | ||
6280 | break; | ||
6281 | |||
6282 | /* legacy and mcs rates may not be both empty */ | ||
6283 | if (i == IEEE80211_HT_MCS_MASK_LEN) | ||
6284 | return -EINVAL; | 4952 | return -EINVAL; |
6285 | } | 4953 | } |
6286 | } | 4954 | } |
6287 | 4955 | ||
6288 | return rdev_set_bitrate_mask(rdev, dev, NULL, &mask); | 4956 | return rdev->ops->set_bitrate_mask(&rdev->wiphy, dev, NULL, &mask); |
6289 | } | 4957 | } |
6290 | 4958 | ||
6291 | static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info) | 4959 | static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info) |
6292 | { | 4960 | { |
6293 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 4961 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
6294 | struct wireless_dev *wdev = info->user_ptr[1]; | 4962 | struct net_device *dev = info->user_ptr[1]; |
6295 | u16 frame_type = IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION; | 4963 | u16 frame_type = IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION; |
6296 | 4964 | ||
6297 | if (!info->attrs[NL80211_ATTR_FRAME_MATCH]) | 4965 | if (!info->attrs[NL80211_ATTR_FRAME_MATCH]) |
@@ -6300,25 +4968,21 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
6300 | if (info->attrs[NL80211_ATTR_FRAME_TYPE]) | 4968 | if (info->attrs[NL80211_ATTR_FRAME_TYPE]) |
6301 | frame_type = nla_get_u16(info->attrs[NL80211_ATTR_FRAME_TYPE]); | 4969 | frame_type = nla_get_u16(info->attrs[NL80211_ATTR_FRAME_TYPE]); |
6302 | 4970 | ||
6303 | switch (wdev->iftype) { | 4971 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
6304 | case NL80211_IFTYPE_STATION: | 4972 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC && |
6305 | case NL80211_IFTYPE_ADHOC: | 4973 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT && |
6306 | case NL80211_IFTYPE_P2P_CLIENT: | 4974 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
6307 | case NL80211_IFTYPE_AP: | 4975 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && |
6308 | case NL80211_IFTYPE_AP_VLAN: | 4976 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT && |
6309 | case NL80211_IFTYPE_MESH_POINT: | 4977 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) |
6310 | case NL80211_IFTYPE_P2P_GO: | ||
6311 | case NL80211_IFTYPE_P2P_DEVICE: | ||
6312 | break; | ||
6313 | default: | ||
6314 | return -EOPNOTSUPP; | 4978 | return -EOPNOTSUPP; |
6315 | } | ||
6316 | 4979 | ||
6317 | /* not much point in registering if we can't reply */ | 4980 | /* not much point in registering if we can't reply */ |
6318 | if (!rdev->ops->mgmt_tx) | 4981 | if (!rdev->ops->mgmt_tx) |
6319 | return -EOPNOTSUPP; | 4982 | return -EOPNOTSUPP; |
6320 | 4983 | ||
6321 | return cfg80211_mlme_register_mgmt(wdev, info->snd_portid, frame_type, | 4984 | return cfg80211_mlme_register_mgmt(dev->ieee80211_ptr, info->snd_pid, |
4985 | frame_type, | ||
6322 | nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]), | 4986 | nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]), |
6323 | nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH])); | 4987 | nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH])); |
6324 | } | 4988 | } |
@@ -6326,93 +4990,81 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
6326 | static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | 4990 | static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) |
6327 | { | 4991 | { |
6328 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 4992 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
6329 | struct wireless_dev *wdev = info->user_ptr[1]; | 4993 | struct net_device *dev = info->user_ptr[1]; |
6330 | struct cfg80211_chan_def chandef; | 4994 | struct ieee80211_channel *chan; |
4995 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | ||
4996 | bool channel_type_valid = false; | ||
4997 | u32 freq; | ||
6331 | int err; | 4998 | int err; |
6332 | void *hdr = NULL; | 4999 | void *hdr; |
6333 | u64 cookie; | 5000 | u64 cookie; |
6334 | struct sk_buff *msg = NULL; | 5001 | struct sk_buff *msg; |
6335 | unsigned int wait = 0; | 5002 | unsigned int wait = 0; |
6336 | bool offchan, no_cck, dont_wait_for_ack; | 5003 | bool offchan; |
6337 | 5004 | ||
6338 | dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK]; | 5005 | if (!info->attrs[NL80211_ATTR_FRAME] || |
6339 | 5006 | !info->attrs[NL80211_ATTR_WIPHY_FREQ]) | |
6340 | if (!info->attrs[NL80211_ATTR_FRAME]) | ||
6341 | return -EINVAL; | 5007 | return -EINVAL; |
6342 | 5008 | ||
6343 | if (!rdev->ops->mgmt_tx) | 5009 | if (!rdev->ops->mgmt_tx) |
6344 | return -EOPNOTSUPP; | 5010 | return -EOPNOTSUPP; |
6345 | 5011 | ||
6346 | switch (wdev->iftype) { | 5012 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
6347 | case NL80211_IFTYPE_STATION: | 5013 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC && |
6348 | case NL80211_IFTYPE_ADHOC: | 5014 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT && |
6349 | case NL80211_IFTYPE_P2P_CLIENT: | 5015 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
6350 | case NL80211_IFTYPE_AP: | 5016 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && |
6351 | case NL80211_IFTYPE_AP_VLAN: | 5017 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT && |
6352 | case NL80211_IFTYPE_MESH_POINT: | 5018 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) |
6353 | case NL80211_IFTYPE_P2P_GO: | ||
6354 | case NL80211_IFTYPE_P2P_DEVICE: | ||
6355 | break; | ||
6356 | default: | ||
6357 | return -EOPNOTSUPP; | 5019 | return -EOPNOTSUPP; |
6358 | } | ||
6359 | 5020 | ||
6360 | if (info->attrs[NL80211_ATTR_DURATION]) { | 5021 | if (info->attrs[NL80211_ATTR_DURATION]) { |
6361 | if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX)) | 5022 | if (!rdev->ops->mgmt_tx_cancel_wait) |
6362 | return -EINVAL; | 5023 | return -EINVAL; |
6363 | wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]); | 5024 | wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]); |
5025 | } | ||
6364 | 5026 | ||
6365 | /* | 5027 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { |
6366 | * We should wait on the channel for at least a minimum amount | 5028 | channel_type = nla_get_u32( |
6367 | * of time (10ms) but no longer than the driver supports. | 5029 | info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]); |
6368 | */ | 5030 | if (channel_type != NL80211_CHAN_NO_HT && |
6369 | if (wait < NL80211_MIN_REMAIN_ON_CHANNEL_TIME || | 5031 | channel_type != NL80211_CHAN_HT20 && |
6370 | wait > rdev->wiphy.max_remain_on_channel_duration) | 5032 | channel_type != NL80211_CHAN_HT40PLUS && |
5033 | channel_type != NL80211_CHAN_HT40MINUS) | ||
6371 | return -EINVAL; | 5034 | return -EINVAL; |
6372 | 5035 | channel_type_valid = true; | |
6373 | } | 5036 | } |
6374 | 5037 | ||
6375 | offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK]; | 5038 | offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK]; |
6376 | 5039 | ||
6377 | if (offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX)) | 5040 | freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); |
5041 | chan = rdev_freq_to_chan(rdev, freq, channel_type); | ||
5042 | if (chan == NULL) | ||
6378 | return -EINVAL; | 5043 | return -EINVAL; |
6379 | 5044 | ||
6380 | no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]); | 5045 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
6381 | 5046 | if (!msg) | |
6382 | err = nl80211_parse_chandef(rdev, info, &chandef); | 5047 | return -ENOMEM; |
6383 | if (err) | ||
6384 | return err; | ||
6385 | |||
6386 | if (!dont_wait_for_ack) { | ||
6387 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
6388 | if (!msg) | ||
6389 | return -ENOMEM; | ||
6390 | 5048 | ||
6391 | hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0, | 5049 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, |
6392 | NL80211_CMD_FRAME); | 5050 | NL80211_CMD_FRAME); |
6393 | 5051 | ||
6394 | if (IS_ERR(hdr)) { | 5052 | if (IS_ERR(hdr)) { |
6395 | err = PTR_ERR(hdr); | 5053 | err = PTR_ERR(hdr); |
6396 | goto free_msg; | 5054 | goto free_msg; |
6397 | } | ||
6398 | } | 5055 | } |
6399 | 5056 | err = cfg80211_mlme_mgmt_tx(rdev, dev, chan, offchan, channel_type, | |
6400 | err = cfg80211_mlme_mgmt_tx(rdev, wdev, chandef.chan, offchan, wait, | 5057 | channel_type_valid, wait, |
6401 | nla_data(info->attrs[NL80211_ATTR_FRAME]), | 5058 | nla_data(info->attrs[NL80211_ATTR_FRAME]), |
6402 | nla_len(info->attrs[NL80211_ATTR_FRAME]), | 5059 | nla_len(info->attrs[NL80211_ATTR_FRAME]), |
6403 | no_cck, dont_wait_for_ack, &cookie); | 5060 | &cookie); |
6404 | if (err) | 5061 | if (err) |
6405 | goto free_msg; | 5062 | goto free_msg; |
6406 | 5063 | ||
6407 | if (msg) { | 5064 | NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie); |
6408 | if (nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie)) | ||
6409 | goto nla_put_failure; | ||
6410 | |||
6411 | genlmsg_end(msg, hdr); | ||
6412 | return genlmsg_reply(msg, info); | ||
6413 | } | ||
6414 | 5065 | ||
6415 | return 0; | 5066 | genlmsg_end(msg, hdr); |
5067 | return genlmsg_reply(msg, info); | ||
6416 | 5068 | ||
6417 | nla_put_failure: | 5069 | nla_put_failure: |
6418 | err = -ENOBUFS; | 5070 | err = -ENOBUFS; |
@@ -6424,7 +5076,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
6424 | static int nl80211_tx_mgmt_cancel_wait(struct sk_buff *skb, struct genl_info *info) | 5076 | static int nl80211_tx_mgmt_cancel_wait(struct sk_buff *skb, struct genl_info *info) |
6425 | { | 5077 | { |
6426 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 5078 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
6427 | struct wireless_dev *wdev = info->user_ptr[1]; | 5079 | struct net_device *dev = info->user_ptr[1]; |
6428 | u64 cookie; | 5080 | u64 cookie; |
6429 | 5081 | ||
6430 | if (!info->attrs[NL80211_ATTR_COOKIE]) | 5082 | if (!info->attrs[NL80211_ATTR_COOKIE]) |
@@ -6433,22 +5085,17 @@ static int nl80211_tx_mgmt_cancel_wait(struct sk_buff *skb, struct genl_info *in | |||
6433 | if (!rdev->ops->mgmt_tx_cancel_wait) | 5085 | if (!rdev->ops->mgmt_tx_cancel_wait) |
6434 | return -EOPNOTSUPP; | 5086 | return -EOPNOTSUPP; |
6435 | 5087 | ||
6436 | switch (wdev->iftype) { | 5088 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
6437 | case NL80211_IFTYPE_STATION: | 5089 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC && |
6438 | case NL80211_IFTYPE_ADHOC: | 5090 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT && |
6439 | case NL80211_IFTYPE_P2P_CLIENT: | 5091 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
6440 | case NL80211_IFTYPE_AP: | 5092 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && |
6441 | case NL80211_IFTYPE_AP_VLAN: | 5093 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) |
6442 | case NL80211_IFTYPE_P2P_GO: | ||
6443 | case NL80211_IFTYPE_P2P_DEVICE: | ||
6444 | break; | ||
6445 | default: | ||
6446 | return -EOPNOTSUPP; | 5094 | return -EOPNOTSUPP; |
6447 | } | ||
6448 | 5095 | ||
6449 | cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]); | 5096 | cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]); |
6450 | 5097 | ||
6451 | return rdev_mgmt_tx_cancel_wait(rdev, wdev, cookie); | 5098 | return rdev->ops->mgmt_tx_cancel_wait(&rdev->wiphy, dev, cookie); |
6452 | } | 5099 | } |
6453 | 5100 | ||
6454 | static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info) | 5101 | static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info) |
@@ -6478,7 +5125,8 @@ static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info) | |||
6478 | if (state == wdev->ps) | 5125 | if (state == wdev->ps) |
6479 | return 0; | 5126 | return 0; |
6480 | 5127 | ||
6481 | err = rdev_set_power_mgmt(rdev, dev, state, wdev->ps_timeout); | 5128 | err = rdev->ops->set_power_mgmt(wdev->wiphy, dev, state, |
5129 | wdev->ps_timeout); | ||
6482 | if (!err) | 5130 | if (!err) |
6483 | wdev->ps = state; | 5131 | wdev->ps = state; |
6484 | return err; | 5132 | return err; |
@@ -6503,7 +5151,7 @@ static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info) | |||
6503 | if (!msg) | 5151 | if (!msg) |
6504 | return -ENOMEM; | 5152 | return -ENOMEM; |
6505 | 5153 | ||
6506 | hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0, | 5154 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, |
6507 | NL80211_CMD_GET_POWER_SAVE); | 5155 | NL80211_CMD_GET_POWER_SAVE); |
6508 | if (!hdr) { | 5156 | if (!hdr) { |
6509 | err = -ENOBUFS; | 5157 | err = -ENOBUFS; |
@@ -6515,8 +5163,7 @@ static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info) | |||
6515 | else | 5163 | else |
6516 | ps_state = NL80211_PS_DISABLED; | 5164 | ps_state = NL80211_PS_DISABLED; |
6517 | 5165 | ||
6518 | if (nla_put_u32(msg, NL80211_ATTR_PS_STATE, ps_state)) | 5166 | NLA_PUT_U32(msg, NL80211_ATTR_PS_STATE, ps_state); |
6519 | goto nla_put_failure; | ||
6520 | 5167 | ||
6521 | genlmsg_end(msg, hdr); | 5168 | genlmsg_end(msg, hdr); |
6522 | return genlmsg_reply(msg, info); | 5169 | return genlmsg_reply(msg, info); |
@@ -6533,33 +5180,8 @@ nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] __read_mostly = { | |||
6533 | [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 }, | 5180 | [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 }, |
6534 | [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 }, | 5181 | [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 }, |
6535 | [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 }, | 5182 | [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 }, |
6536 | [NL80211_ATTR_CQM_TXE_RATE] = { .type = NLA_U32 }, | ||
6537 | [NL80211_ATTR_CQM_TXE_PKTS] = { .type = NLA_U32 }, | ||
6538 | [NL80211_ATTR_CQM_TXE_INTVL] = { .type = NLA_U32 }, | ||
6539 | }; | 5183 | }; |
6540 | 5184 | ||
6541 | static int nl80211_set_cqm_txe(struct genl_info *info, | ||
6542 | u32 rate, u32 pkts, u32 intvl) | ||
6543 | { | ||
6544 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
6545 | struct wireless_dev *wdev; | ||
6546 | struct net_device *dev = info->user_ptr[1]; | ||
6547 | |||
6548 | if (rate > 100 || intvl > NL80211_CQM_TXE_MAX_INTVL) | ||
6549 | return -EINVAL; | ||
6550 | |||
6551 | wdev = dev->ieee80211_ptr; | ||
6552 | |||
6553 | if (!rdev->ops->set_cqm_txe_config) | ||
6554 | return -EOPNOTSUPP; | ||
6555 | |||
6556 | if (wdev->iftype != NL80211_IFTYPE_STATION && | ||
6557 | wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) | ||
6558 | return -EOPNOTSUPP; | ||
6559 | |||
6560 | return rdev_set_cqm_txe_config(rdev, dev, rate, pkts, intvl); | ||
6561 | } | ||
6562 | |||
6563 | static int nl80211_set_cqm_rssi(struct genl_info *info, | 5185 | static int nl80211_set_cqm_rssi(struct genl_info *info, |
6564 | s32 threshold, u32 hysteresis) | 5186 | s32 threshold, u32 hysteresis) |
6565 | { | 5187 | { |
@@ -6579,7 +5201,8 @@ static int nl80211_set_cqm_rssi(struct genl_info *info, | |||
6579 | wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) | 5201 | wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) |
6580 | return -EOPNOTSUPP; | 5202 | return -EOPNOTSUPP; |
6581 | 5203 | ||
6582 | return rdev_set_cqm_rssi_config(rdev, dev, threshold, hysteresis); | 5204 | return rdev->ops->set_cqm_rssi_config(wdev->wiphy, dev, |
5205 | threshold, hysteresis); | ||
6583 | } | 5206 | } |
6584 | 5207 | ||
6585 | static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info) | 5208 | static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info) |
@@ -6606,14 +5229,6 @@ static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info) | |||
6606 | threshold = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_THOLD]); | 5229 | threshold = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_THOLD]); |
6607 | hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]); | 5230 | hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]); |
6608 | err = nl80211_set_cqm_rssi(info, threshold, hysteresis); | 5231 | err = nl80211_set_cqm_rssi(info, threshold, hysteresis); |
6609 | } else if (attrs[NL80211_ATTR_CQM_TXE_RATE] && | ||
6610 | attrs[NL80211_ATTR_CQM_TXE_PKTS] && | ||
6611 | attrs[NL80211_ATTR_CQM_TXE_INTVL]) { | ||
6612 | u32 rate, pkts, intvl; | ||
6613 | rate = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_RATE]); | ||
6614 | pkts = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_PKTS]); | ||
6615 | intvl = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_INTVL]); | ||
6616 | err = nl80211_set_cqm_txe(info, rate, pkts, intvl); | ||
6617 | } else | 5232 | } else |
6618 | err = -EINVAL; | 5233 | err = -EINVAL; |
6619 | 5234 | ||
@@ -6647,11 +5262,6 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info) | |||
6647 | setup.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]); | 5262 | setup.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]); |
6648 | setup.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); | 5263 | setup.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); |
6649 | 5264 | ||
6650 | if (info->attrs[NL80211_ATTR_MCAST_RATE] && | ||
6651 | !nl80211_parse_mcast_rate(rdev, setup.mcast_rate, | ||
6652 | nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE]))) | ||
6653 | return -EINVAL; | ||
6654 | |||
6655 | if (info->attrs[NL80211_ATTR_MESH_SETUP]) { | 5265 | if (info->attrs[NL80211_ATTR_MESH_SETUP]) { |
6656 | /* parse additional setup parameters if given */ | 5266 | /* parse additional setup parameters if given */ |
6657 | err = nl80211_parse_mesh_setup(info, &setup); | 5267 | err = nl80211_parse_mesh_setup(info, &setup); |
@@ -6659,15 +5269,6 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info) | |||
6659 | return err; | 5269 | return err; |
6660 | } | 5270 | } |
6661 | 5271 | ||
6662 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { | ||
6663 | err = nl80211_parse_chandef(rdev, info, &setup.chandef); | ||
6664 | if (err) | ||
6665 | return err; | ||
6666 | } else { | ||
6667 | /* cfg80211_join_mesh() will sort it out */ | ||
6668 | setup.chandef.chan = NULL; | ||
6669 | } | ||
6670 | |||
6671 | return cfg80211_join_mesh(rdev, dev, &setup, &cfg); | 5272 | return cfg80211_join_mesh(rdev, dev, &setup, &cfg); |
6672 | } | 5273 | } |
6673 | 5274 | ||
@@ -6679,7 +5280,6 @@ static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info) | |||
6679 | return cfg80211_leave_mesh(rdev, dev); | 5280 | return cfg80211_leave_mesh(rdev, dev); |
6680 | } | 5281 | } |
6681 | 5282 | ||
6682 | #ifdef CONFIG_PM | ||
6683 | static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info) | 5283 | static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info) |
6684 | { | 5284 | { |
6685 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 5285 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
@@ -6693,7 +5293,7 @@ static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
6693 | if (!msg) | 5293 | if (!msg) |
6694 | return -ENOMEM; | 5294 | return -ENOMEM; |
6695 | 5295 | ||
6696 | hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0, | 5296 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, |
6697 | NL80211_CMD_GET_WOWLAN); | 5297 | NL80211_CMD_GET_WOWLAN); |
6698 | if (!hdr) | 5298 | if (!hdr) |
6699 | goto nla_put_failure; | 5299 | goto nla_put_failure; |
@@ -6705,21 +5305,20 @@ static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
6705 | if (!nl_wowlan) | 5305 | if (!nl_wowlan) |
6706 | goto nla_put_failure; | 5306 | goto nla_put_failure; |
6707 | 5307 | ||
6708 | if ((rdev->wowlan->any && | 5308 | if (rdev->wowlan->any) |
6709 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) || | 5309 | NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_ANY); |
6710 | (rdev->wowlan->disconnect && | 5310 | if (rdev->wowlan->disconnect) |
6711 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) || | 5311 | NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_DISCONNECT); |
6712 | (rdev->wowlan->magic_pkt && | 5312 | if (rdev->wowlan->magic_pkt) |
6713 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) || | 5313 | NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT); |
6714 | (rdev->wowlan->gtk_rekey_failure && | 5314 | if (rdev->wowlan->gtk_rekey_failure) |
6715 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) || | 5315 | NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE); |
6716 | (rdev->wowlan->eap_identity_req && | 5316 | if (rdev->wowlan->eap_identity_req) |
6717 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) || | 5317 | NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST); |
6718 | (rdev->wowlan->four_way_handshake && | 5318 | if (rdev->wowlan->four_way_handshake) |
6719 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) || | 5319 | NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE); |
6720 | (rdev->wowlan->rfkill_release && | 5320 | if (rdev->wowlan->rfkill_release) |
6721 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))) | 5321 | NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE); |
6722 | goto nla_put_failure; | ||
6723 | if (rdev->wowlan->n_patterns) { | 5322 | if (rdev->wowlan->n_patterns) { |
6724 | struct nlattr *nl_pats, *nl_pat; | 5323 | struct nlattr *nl_pats, *nl_pat; |
6725 | int i, pat_len; | 5324 | int i, pat_len; |
@@ -6734,13 +5333,12 @@ static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
6734 | if (!nl_pat) | 5333 | if (!nl_pat) |
6735 | goto nla_put_failure; | 5334 | goto nla_put_failure; |
6736 | pat_len = rdev->wowlan->patterns[i].pattern_len; | 5335 | pat_len = rdev->wowlan->patterns[i].pattern_len; |
6737 | if (nla_put(msg, NL80211_WOWLAN_PKTPAT_MASK, | 5336 | NLA_PUT(msg, NL80211_WOWLAN_PKTPAT_MASK, |
6738 | DIV_ROUND_UP(pat_len, 8), | 5337 | DIV_ROUND_UP(pat_len, 8), |
6739 | rdev->wowlan->patterns[i].mask) || | 5338 | rdev->wowlan->patterns[i].mask); |
6740 | nla_put(msg, NL80211_WOWLAN_PKTPAT_PATTERN, | 5339 | NLA_PUT(msg, NL80211_WOWLAN_PKTPAT_PATTERN, |
6741 | pat_len, | 5340 | pat_len, |
6742 | rdev->wowlan->patterns[i].pattern)) | 5341 | rdev->wowlan->patterns[i].pattern); |
6743 | goto nla_put_failure; | ||
6744 | nla_nest_end(msg, nl_pat); | 5342 | nla_nest_end(msg, nl_pat); |
6745 | } | 5343 | } |
6746 | nla_nest_end(msg, nl_pats); | 5344 | nla_nest_end(msg, nl_pats); |
@@ -6761,20 +5359,16 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
6761 | { | 5359 | { |
6762 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 5360 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
6763 | struct nlattr *tb[NUM_NL80211_WOWLAN_TRIG]; | 5361 | struct nlattr *tb[NUM_NL80211_WOWLAN_TRIG]; |
5362 | struct cfg80211_wowlan no_triggers = {}; | ||
6764 | struct cfg80211_wowlan new_triggers = {}; | 5363 | struct cfg80211_wowlan new_triggers = {}; |
6765 | struct cfg80211_wowlan *ntrig; | ||
6766 | struct wiphy_wowlan_support *wowlan = &rdev->wiphy.wowlan; | 5364 | struct wiphy_wowlan_support *wowlan = &rdev->wiphy.wowlan; |
6767 | int err, i; | 5365 | int err, i; |
6768 | bool prev_enabled = rdev->wowlan; | ||
6769 | 5366 | ||
6770 | if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns) | 5367 | if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns) |
6771 | return -EOPNOTSUPP; | 5368 | return -EOPNOTSUPP; |
6772 | 5369 | ||
6773 | if (!info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) { | 5370 | if (!info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) |
6774 | cfg80211_rdev_free_wowlan(rdev); | 5371 | goto no_triggers; |
6775 | rdev->wowlan = NULL; | ||
6776 | goto set_wakeup; | ||
6777 | } | ||
6778 | 5372 | ||
6779 | err = nla_parse(tb, MAX_NL80211_WOWLAN_TRIG, | 5373 | err = nla_parse(tb, MAX_NL80211_WOWLAN_TRIG, |
6780 | nla_data(info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]), | 5374 | nla_data(info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]), |
@@ -6885,17 +5479,21 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
6885 | } | 5479 | } |
6886 | } | 5480 | } |
6887 | 5481 | ||
6888 | ntrig = kmemdup(&new_triggers, sizeof(new_triggers), GFP_KERNEL); | 5482 | if (memcmp(&new_triggers, &no_triggers, sizeof(new_triggers))) { |
6889 | if (!ntrig) { | 5483 | struct cfg80211_wowlan *ntrig; |
6890 | err = -ENOMEM; | 5484 | ntrig = kmemdup(&new_triggers, sizeof(new_triggers), |
6891 | goto error; | 5485 | GFP_KERNEL); |
5486 | if (!ntrig) { | ||
5487 | err = -ENOMEM; | ||
5488 | goto error; | ||
5489 | } | ||
5490 | cfg80211_rdev_free_wowlan(rdev); | ||
5491 | rdev->wowlan = ntrig; | ||
5492 | } else { | ||
5493 | no_triggers: | ||
5494 | cfg80211_rdev_free_wowlan(rdev); | ||
5495 | rdev->wowlan = NULL; | ||
6892 | } | 5496 | } |
6893 | cfg80211_rdev_free_wowlan(rdev); | ||
6894 | rdev->wowlan = ntrig; | ||
6895 | |||
6896 | set_wakeup: | ||
6897 | if (rdev->ops->set_wakeup && prev_enabled != !!rdev->wowlan) | ||
6898 | rdev_set_wakeup(rdev, rdev->wowlan); | ||
6899 | 5497 | ||
6900 | return 0; | 5498 | return 0; |
6901 | error: | 5499 | error: |
@@ -6904,7 +5502,6 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
6904 | kfree(new_triggers.patterns); | 5502 | kfree(new_triggers.patterns); |
6905 | return err; | 5503 | return err; |
6906 | } | 5504 | } |
6907 | #endif | ||
6908 | 5505 | ||
6909 | static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info) | 5506 | static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info) |
6910 | { | 5507 | { |
@@ -6951,261 +5548,55 @@ static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info) | |||
6951 | goto out; | 5548 | goto out; |
6952 | } | 5549 | } |
6953 | 5550 | ||
6954 | err = rdev_set_rekey_data(rdev, dev, &rekey_data); | 5551 | err = rdev->ops->set_rekey_data(&rdev->wiphy, dev, &rekey_data); |
6955 | out: | 5552 | out: |
6956 | wdev_unlock(wdev); | 5553 | wdev_unlock(wdev); |
6957 | return err; | 5554 | return err; |
6958 | } | 5555 | } |
6959 | 5556 | ||
6960 | static int nl80211_register_unexpected_frame(struct sk_buff *skb, | ||
6961 | struct genl_info *info) | ||
6962 | { | ||
6963 | struct net_device *dev = info->user_ptr[1]; | ||
6964 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
6965 | |||
6966 | if (wdev->iftype != NL80211_IFTYPE_AP && | ||
6967 | wdev->iftype != NL80211_IFTYPE_P2P_GO) | ||
6968 | return -EINVAL; | ||
6969 | |||
6970 | if (wdev->ap_unexpected_nlportid) | ||
6971 | return -EBUSY; | ||
6972 | |||
6973 | wdev->ap_unexpected_nlportid = info->snd_portid; | ||
6974 | return 0; | ||
6975 | } | ||
6976 | |||
6977 | static int nl80211_probe_client(struct sk_buff *skb, | ||
6978 | struct genl_info *info) | ||
6979 | { | ||
6980 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
6981 | struct net_device *dev = info->user_ptr[1]; | ||
6982 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
6983 | struct sk_buff *msg; | ||
6984 | void *hdr; | ||
6985 | const u8 *addr; | ||
6986 | u64 cookie; | ||
6987 | int err; | ||
6988 | |||
6989 | if (wdev->iftype != NL80211_IFTYPE_AP && | ||
6990 | wdev->iftype != NL80211_IFTYPE_P2P_GO) | ||
6991 | return -EOPNOTSUPP; | ||
6992 | |||
6993 | if (!info->attrs[NL80211_ATTR_MAC]) | ||
6994 | return -EINVAL; | ||
6995 | |||
6996 | if (!rdev->ops->probe_client) | ||
6997 | return -EOPNOTSUPP; | ||
6998 | |||
6999 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
7000 | if (!msg) | ||
7001 | return -ENOMEM; | ||
7002 | |||
7003 | hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0, | ||
7004 | NL80211_CMD_PROBE_CLIENT); | ||
7005 | |||
7006 | if (IS_ERR(hdr)) { | ||
7007 | err = PTR_ERR(hdr); | ||
7008 | goto free_msg; | ||
7009 | } | ||
7010 | |||
7011 | addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | ||
7012 | |||
7013 | err = rdev_probe_client(rdev, dev, addr, &cookie); | ||
7014 | if (err) | ||
7015 | goto free_msg; | ||
7016 | |||
7017 | if (nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie)) | ||
7018 | goto nla_put_failure; | ||
7019 | |||
7020 | genlmsg_end(msg, hdr); | ||
7021 | |||
7022 | return genlmsg_reply(msg, info); | ||
7023 | |||
7024 | nla_put_failure: | ||
7025 | err = -ENOBUFS; | ||
7026 | free_msg: | ||
7027 | nlmsg_free(msg); | ||
7028 | return err; | ||
7029 | } | ||
7030 | |||
7031 | static int nl80211_register_beacons(struct sk_buff *skb, struct genl_info *info) | ||
7032 | { | ||
7033 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
7034 | struct cfg80211_beacon_registration *reg, *nreg; | ||
7035 | int rv; | ||
7036 | |||
7037 | if (!(rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS)) | ||
7038 | return -EOPNOTSUPP; | ||
7039 | |||
7040 | nreg = kzalloc(sizeof(*nreg), GFP_KERNEL); | ||
7041 | if (!nreg) | ||
7042 | return -ENOMEM; | ||
7043 | |||
7044 | /* First, check if already registered. */ | ||
7045 | spin_lock_bh(&rdev->beacon_registrations_lock); | ||
7046 | list_for_each_entry(reg, &rdev->beacon_registrations, list) { | ||
7047 | if (reg->nlportid == info->snd_portid) { | ||
7048 | rv = -EALREADY; | ||
7049 | goto out_err; | ||
7050 | } | ||
7051 | } | ||
7052 | /* Add it to the list */ | ||
7053 | nreg->nlportid = info->snd_portid; | ||
7054 | list_add(&nreg->list, &rdev->beacon_registrations); | ||
7055 | |||
7056 | spin_unlock_bh(&rdev->beacon_registrations_lock); | ||
7057 | |||
7058 | return 0; | ||
7059 | out_err: | ||
7060 | spin_unlock_bh(&rdev->beacon_registrations_lock); | ||
7061 | kfree(nreg); | ||
7062 | return rv; | ||
7063 | } | ||
7064 | |||
7065 | static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info) | ||
7066 | { | ||
7067 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
7068 | struct wireless_dev *wdev = info->user_ptr[1]; | ||
7069 | int err; | ||
7070 | |||
7071 | if (!rdev->ops->start_p2p_device) | ||
7072 | return -EOPNOTSUPP; | ||
7073 | |||
7074 | if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE) | ||
7075 | return -EOPNOTSUPP; | ||
7076 | |||
7077 | if (wdev->p2p_started) | ||
7078 | return 0; | ||
7079 | |||
7080 | mutex_lock(&rdev->devlist_mtx); | ||
7081 | err = cfg80211_can_add_interface(rdev, wdev->iftype); | ||
7082 | mutex_unlock(&rdev->devlist_mtx); | ||
7083 | if (err) | ||
7084 | return err; | ||
7085 | |||
7086 | err = rdev_start_p2p_device(rdev, wdev); | ||
7087 | if (err) | ||
7088 | return err; | ||
7089 | |||
7090 | wdev->p2p_started = true; | ||
7091 | mutex_lock(&rdev->devlist_mtx); | ||
7092 | rdev->opencount++; | ||
7093 | mutex_unlock(&rdev->devlist_mtx); | ||
7094 | |||
7095 | return 0; | ||
7096 | } | ||
7097 | |||
7098 | static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info) | ||
7099 | { | ||
7100 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
7101 | struct wireless_dev *wdev = info->user_ptr[1]; | ||
7102 | |||
7103 | if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE) | ||
7104 | return -EOPNOTSUPP; | ||
7105 | |||
7106 | if (!rdev->ops->stop_p2p_device) | ||
7107 | return -EOPNOTSUPP; | ||
7108 | |||
7109 | if (!wdev->p2p_started) | ||
7110 | return 0; | ||
7111 | |||
7112 | rdev_stop_p2p_device(rdev, wdev); | ||
7113 | wdev->p2p_started = false; | ||
7114 | |||
7115 | mutex_lock(&rdev->devlist_mtx); | ||
7116 | rdev->opencount--; | ||
7117 | mutex_unlock(&rdev->devlist_mtx); | ||
7118 | |||
7119 | if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) { | ||
7120 | rdev->scan_req->aborted = true; | ||
7121 | ___cfg80211_scan_done(rdev, true); | ||
7122 | } | ||
7123 | |||
7124 | return 0; | ||
7125 | } | ||
7126 | |||
7127 | #define NL80211_FLAG_NEED_WIPHY 0x01 | 5557 | #define NL80211_FLAG_NEED_WIPHY 0x01 |
7128 | #define NL80211_FLAG_NEED_NETDEV 0x02 | 5558 | #define NL80211_FLAG_NEED_NETDEV 0x02 |
7129 | #define NL80211_FLAG_NEED_RTNL 0x04 | 5559 | #define NL80211_FLAG_NEED_RTNL 0x04 |
7130 | #define NL80211_FLAG_CHECK_NETDEV_UP 0x08 | 5560 | #define NL80211_FLAG_CHECK_NETDEV_UP 0x08 |
7131 | #define NL80211_FLAG_NEED_NETDEV_UP (NL80211_FLAG_NEED_NETDEV |\ | 5561 | #define NL80211_FLAG_NEED_NETDEV_UP (NL80211_FLAG_NEED_NETDEV |\ |
7132 | NL80211_FLAG_CHECK_NETDEV_UP) | 5562 | NL80211_FLAG_CHECK_NETDEV_UP) |
7133 | #define NL80211_FLAG_NEED_WDEV 0x10 | ||
7134 | /* If a netdev is associated, it must be UP, P2P must be started */ | ||
7135 | #define NL80211_FLAG_NEED_WDEV_UP (NL80211_FLAG_NEED_WDEV |\ | ||
7136 | NL80211_FLAG_CHECK_NETDEV_UP) | ||
7137 | 5563 | ||
7138 | static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, | 5564 | static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, |
7139 | struct genl_info *info) | 5565 | struct genl_info *info) |
7140 | { | 5566 | { |
7141 | struct cfg80211_registered_device *rdev; | 5567 | struct cfg80211_registered_device *rdev; |
7142 | struct wireless_dev *wdev; | ||
7143 | struct net_device *dev; | 5568 | struct net_device *dev; |
5569 | int err; | ||
7144 | bool rtnl = ops->internal_flags & NL80211_FLAG_NEED_RTNL; | 5570 | bool rtnl = ops->internal_flags & NL80211_FLAG_NEED_RTNL; |
7145 | 5571 | ||
7146 | if (rtnl) | 5572 | if (rtnl) |
7147 | rtnl_lock(); | 5573 | rtnl_lock(); |
7148 | 5574 | ||
7149 | if (ops->internal_flags & NL80211_FLAG_NEED_WIPHY) { | 5575 | if (ops->internal_flags & NL80211_FLAG_NEED_WIPHY) { |
7150 | rdev = cfg80211_get_dev_from_info(genl_info_net(info), info); | 5576 | rdev = cfg80211_get_dev_from_info(info); |
7151 | if (IS_ERR(rdev)) { | 5577 | if (IS_ERR(rdev)) { |
7152 | if (rtnl) | 5578 | if (rtnl) |
7153 | rtnl_unlock(); | 5579 | rtnl_unlock(); |
7154 | return PTR_ERR(rdev); | 5580 | return PTR_ERR(rdev); |
7155 | } | 5581 | } |
7156 | info->user_ptr[0] = rdev; | 5582 | info->user_ptr[0] = rdev; |
7157 | } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV || | 5583 | } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) { |
7158 | ops->internal_flags & NL80211_FLAG_NEED_WDEV) { | 5584 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); |
7159 | mutex_lock(&cfg80211_mutex); | 5585 | if (err) { |
7160 | wdev = __cfg80211_wdev_from_attrs(genl_info_net(info), | ||
7161 | info->attrs); | ||
7162 | if (IS_ERR(wdev)) { | ||
7163 | mutex_unlock(&cfg80211_mutex); | ||
7164 | if (rtnl) | 5586 | if (rtnl) |
7165 | rtnl_unlock(); | 5587 | rtnl_unlock(); |
7166 | return PTR_ERR(wdev); | 5588 | return err; |
7167 | } | ||
7168 | |||
7169 | dev = wdev->netdev; | ||
7170 | rdev = wiphy_to_dev(wdev->wiphy); | ||
7171 | |||
7172 | if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) { | ||
7173 | if (!dev) { | ||
7174 | mutex_unlock(&cfg80211_mutex); | ||
7175 | if (rtnl) | ||
7176 | rtnl_unlock(); | ||
7177 | return -EINVAL; | ||
7178 | } | ||
7179 | |||
7180 | info->user_ptr[1] = dev; | ||
7181 | } else { | ||
7182 | info->user_ptr[1] = wdev; | ||
7183 | } | 5589 | } |
7184 | 5590 | if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP && | |
7185 | if (dev) { | 5591 | !netif_running(dev)) { |
7186 | if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP && | 5592 | cfg80211_unlock_rdev(rdev); |
7187 | !netif_running(dev)) { | 5593 | dev_put(dev); |
7188 | mutex_unlock(&cfg80211_mutex); | 5594 | if (rtnl) |
7189 | if (rtnl) | 5595 | rtnl_unlock(); |
7190 | rtnl_unlock(); | 5596 | return -ENETDOWN; |
7191 | return -ENETDOWN; | ||
7192 | } | ||
7193 | |||
7194 | dev_hold(dev); | ||
7195 | } else if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP) { | ||
7196 | if (!wdev->p2p_started) { | ||
7197 | mutex_unlock(&cfg80211_mutex); | ||
7198 | if (rtnl) | ||
7199 | rtnl_unlock(); | ||
7200 | return -ENETDOWN; | ||
7201 | } | ||
7202 | } | 5597 | } |
7203 | |||
7204 | cfg80211_lock_rdev(rdev); | ||
7205 | |||
7206 | mutex_unlock(&cfg80211_mutex); | ||
7207 | |||
7208 | info->user_ptr[0] = rdev; | 5598 | info->user_ptr[0] = rdev; |
5599 | info->user_ptr[1] = dev; | ||
7209 | } | 5600 | } |
7210 | 5601 | ||
7211 | return 0; | 5602 | return 0; |
@@ -7216,16 +5607,8 @@ static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb, | |||
7216 | { | 5607 | { |
7217 | if (info->user_ptr[0]) | 5608 | if (info->user_ptr[0]) |
7218 | cfg80211_unlock_rdev(info->user_ptr[0]); | 5609 | cfg80211_unlock_rdev(info->user_ptr[0]); |
7219 | if (info->user_ptr[1]) { | 5610 | if (info->user_ptr[1]) |
7220 | if (ops->internal_flags & NL80211_FLAG_NEED_WDEV) { | 5611 | dev_put(info->user_ptr[1]); |
7221 | struct wireless_dev *wdev = info->user_ptr[1]; | ||
7222 | |||
7223 | if (wdev->netdev) | ||
7224 | dev_put(wdev->netdev); | ||
7225 | } else { | ||
7226 | dev_put(info->user_ptr[1]); | ||
7227 | } | ||
7228 | } | ||
7229 | if (ops->internal_flags & NL80211_FLAG_NEED_RTNL) | 5612 | if (ops->internal_flags & NL80211_FLAG_NEED_RTNL) |
7230 | rtnl_unlock(); | 5613 | rtnl_unlock(); |
7231 | } | 5614 | } |
@@ -7252,7 +5635,7 @@ static struct genl_ops nl80211_ops[] = { | |||
7252 | .dumpit = nl80211_dump_interface, | 5635 | .dumpit = nl80211_dump_interface, |
7253 | .policy = nl80211_policy, | 5636 | .policy = nl80211_policy, |
7254 | /* can be retrieved by unprivileged users */ | 5637 | /* can be retrieved by unprivileged users */ |
7255 | .internal_flags = NL80211_FLAG_NEED_WDEV, | 5638 | .internal_flags = NL80211_FLAG_NEED_NETDEV, |
7256 | }, | 5639 | }, |
7257 | { | 5640 | { |
7258 | .cmd = NL80211_CMD_SET_INTERFACE, | 5641 | .cmd = NL80211_CMD_SET_INTERFACE, |
@@ -7275,7 +5658,7 @@ static struct genl_ops nl80211_ops[] = { | |||
7275 | .doit = nl80211_del_interface, | 5658 | .doit = nl80211_del_interface, |
7276 | .policy = nl80211_policy, | 5659 | .policy = nl80211_policy, |
7277 | .flags = GENL_ADMIN_PERM, | 5660 | .flags = GENL_ADMIN_PERM, |
7278 | .internal_flags = NL80211_FLAG_NEED_WDEV | | 5661 | .internal_flags = NL80211_FLAG_NEED_NETDEV | |
7279 | NL80211_FLAG_NEED_RTNL, | 5662 | NL80211_FLAG_NEED_RTNL, |
7280 | }, | 5663 | }, |
7281 | { | 5664 | { |
@@ -7283,7 +5666,7 @@ static struct genl_ops nl80211_ops[] = { | |||
7283 | .doit = nl80211_get_key, | 5666 | .doit = nl80211_get_key, |
7284 | .policy = nl80211_policy, | 5667 | .policy = nl80211_policy, |
7285 | .flags = GENL_ADMIN_PERM, | 5668 | .flags = GENL_ADMIN_PERM, |
7286 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | 5669 | .internal_flags = NL80211_FLAG_NEED_NETDEV | |
7287 | NL80211_FLAG_NEED_RTNL, | 5670 | NL80211_FLAG_NEED_RTNL, |
7288 | }, | 5671 | }, |
7289 | { | 5672 | { |
@@ -7314,24 +5697,24 @@ static struct genl_ops nl80211_ops[] = { | |||
7314 | .cmd = NL80211_CMD_SET_BEACON, | 5697 | .cmd = NL80211_CMD_SET_BEACON, |
7315 | .policy = nl80211_policy, | 5698 | .policy = nl80211_policy, |
7316 | .flags = GENL_ADMIN_PERM, | 5699 | .flags = GENL_ADMIN_PERM, |
7317 | .doit = nl80211_set_beacon, | 5700 | .doit = nl80211_addset_beacon, |
7318 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | 5701 | .internal_flags = NL80211_FLAG_NEED_NETDEV | |
7319 | NL80211_FLAG_NEED_RTNL, | 5702 | NL80211_FLAG_NEED_RTNL, |
7320 | }, | 5703 | }, |
7321 | { | 5704 | { |
7322 | .cmd = NL80211_CMD_START_AP, | 5705 | .cmd = NL80211_CMD_NEW_BEACON, |
7323 | .policy = nl80211_policy, | 5706 | .policy = nl80211_policy, |
7324 | .flags = GENL_ADMIN_PERM, | 5707 | .flags = GENL_ADMIN_PERM, |
7325 | .doit = nl80211_start_ap, | 5708 | .doit = nl80211_addset_beacon, |
7326 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | 5709 | .internal_flags = NL80211_FLAG_NEED_NETDEV | |
7327 | NL80211_FLAG_NEED_RTNL, | 5710 | NL80211_FLAG_NEED_RTNL, |
7328 | }, | 5711 | }, |
7329 | { | 5712 | { |
7330 | .cmd = NL80211_CMD_STOP_AP, | 5713 | .cmd = NL80211_CMD_DEL_BEACON, |
7331 | .policy = nl80211_policy, | 5714 | .policy = nl80211_policy, |
7332 | .flags = GENL_ADMIN_PERM, | 5715 | .flags = GENL_ADMIN_PERM, |
7333 | .doit = nl80211_stop_ap, | 5716 | .doit = nl80211_del_beacon, |
7334 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | 5717 | .internal_flags = NL80211_FLAG_NEED_NETDEV | |
7335 | NL80211_FLAG_NEED_RTNL, | 5718 | NL80211_FLAG_NEED_RTNL, |
7336 | }, | 5719 | }, |
7337 | { | 5720 | { |
@@ -7347,7 +5730,7 @@ static struct genl_ops nl80211_ops[] = { | |||
7347 | .doit = nl80211_set_station, | 5730 | .doit = nl80211_set_station, |
7348 | .policy = nl80211_policy, | 5731 | .policy = nl80211_policy, |
7349 | .flags = GENL_ADMIN_PERM, | 5732 | .flags = GENL_ADMIN_PERM, |
7350 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | 5733 | .internal_flags = NL80211_FLAG_NEED_NETDEV | |
7351 | NL80211_FLAG_NEED_RTNL, | 5734 | NL80211_FLAG_NEED_RTNL, |
7352 | }, | 5735 | }, |
7353 | { | 5736 | { |
@@ -7363,7 +5746,7 @@ static struct genl_ops nl80211_ops[] = { | |||
7363 | .doit = nl80211_del_station, | 5746 | .doit = nl80211_del_station, |
7364 | .policy = nl80211_policy, | 5747 | .policy = nl80211_policy, |
7365 | .flags = GENL_ADMIN_PERM, | 5748 | .flags = GENL_ADMIN_PERM, |
7366 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | 5749 | .internal_flags = NL80211_FLAG_NEED_NETDEV | |
7367 | NL80211_FLAG_NEED_RTNL, | 5750 | NL80211_FLAG_NEED_RTNL, |
7368 | }, | 5751 | }, |
7369 | { | 5752 | { |
@@ -7396,7 +5779,7 @@ static struct genl_ops nl80211_ops[] = { | |||
7396 | .doit = nl80211_del_mpath, | 5779 | .doit = nl80211_del_mpath, |
7397 | .policy = nl80211_policy, | 5780 | .policy = nl80211_policy, |
7398 | .flags = GENL_ADMIN_PERM, | 5781 | .flags = GENL_ADMIN_PERM, |
7399 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | 5782 | .internal_flags = NL80211_FLAG_NEED_NETDEV | |
7400 | NL80211_FLAG_NEED_RTNL, | 5783 | NL80211_FLAG_NEED_RTNL, |
7401 | }, | 5784 | }, |
7402 | { | 5785 | { |
@@ -7404,7 +5787,7 @@ static struct genl_ops nl80211_ops[] = { | |||
7404 | .doit = nl80211_set_bss, | 5787 | .doit = nl80211_set_bss, |
7405 | .policy = nl80211_policy, | 5788 | .policy = nl80211_policy, |
7406 | .flags = GENL_ADMIN_PERM, | 5789 | .flags = GENL_ADMIN_PERM, |
7407 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | 5790 | .internal_flags = NL80211_FLAG_NEED_NETDEV | |
7408 | NL80211_FLAG_NEED_RTNL, | 5791 | NL80211_FLAG_NEED_RTNL, |
7409 | }, | 5792 | }, |
7410 | { | 5793 | { |
@@ -7430,7 +5813,7 @@ static struct genl_ops nl80211_ops[] = { | |||
7430 | .doit = nl80211_get_mesh_config, | 5813 | .doit = nl80211_get_mesh_config, |
7431 | .policy = nl80211_policy, | 5814 | .policy = nl80211_policy, |
7432 | /* can be retrieved by unprivileged users */ | 5815 | /* can be retrieved by unprivileged users */ |
7433 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | 5816 | .internal_flags = NL80211_FLAG_NEED_NETDEV | |
7434 | NL80211_FLAG_NEED_RTNL, | 5817 | NL80211_FLAG_NEED_RTNL, |
7435 | }, | 5818 | }, |
7436 | { | 5819 | { |
@@ -7446,7 +5829,7 @@ static struct genl_ops nl80211_ops[] = { | |||
7446 | .doit = nl80211_trigger_scan, | 5829 | .doit = nl80211_trigger_scan, |
7447 | .policy = nl80211_policy, | 5830 | .policy = nl80211_policy, |
7448 | .flags = GENL_ADMIN_PERM, | 5831 | .flags = GENL_ADMIN_PERM, |
7449 | .internal_flags = NL80211_FLAG_NEED_WDEV_UP | | 5832 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
7450 | NL80211_FLAG_NEED_RTNL, | 5833 | NL80211_FLAG_NEED_RTNL, |
7451 | }, | 5834 | }, |
7452 | { | 5835 | { |
@@ -7563,7 +5946,7 @@ static struct genl_ops nl80211_ops[] = { | |||
7563 | .doit = nl80211_setdel_pmksa, | 5946 | .doit = nl80211_setdel_pmksa, |
7564 | .policy = nl80211_policy, | 5947 | .policy = nl80211_policy, |
7565 | .flags = GENL_ADMIN_PERM, | 5948 | .flags = GENL_ADMIN_PERM, |
7566 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | 5949 | .internal_flags = NL80211_FLAG_NEED_NETDEV | |
7567 | NL80211_FLAG_NEED_RTNL, | 5950 | NL80211_FLAG_NEED_RTNL, |
7568 | }, | 5951 | }, |
7569 | { | 5952 | { |
@@ -7571,7 +5954,7 @@ static struct genl_ops nl80211_ops[] = { | |||
7571 | .doit = nl80211_setdel_pmksa, | 5954 | .doit = nl80211_setdel_pmksa, |
7572 | .policy = nl80211_policy, | 5955 | .policy = nl80211_policy, |
7573 | .flags = GENL_ADMIN_PERM, | 5956 | .flags = GENL_ADMIN_PERM, |
7574 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | 5957 | .internal_flags = NL80211_FLAG_NEED_NETDEV | |
7575 | NL80211_FLAG_NEED_RTNL, | 5958 | NL80211_FLAG_NEED_RTNL, |
7576 | }, | 5959 | }, |
7577 | { | 5960 | { |
@@ -7579,7 +5962,7 @@ static struct genl_ops nl80211_ops[] = { | |||
7579 | .doit = nl80211_flush_pmksa, | 5962 | .doit = nl80211_flush_pmksa, |
7580 | .policy = nl80211_policy, | 5963 | .policy = nl80211_policy, |
7581 | .flags = GENL_ADMIN_PERM, | 5964 | .flags = GENL_ADMIN_PERM, |
7582 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | 5965 | .internal_flags = NL80211_FLAG_NEED_NETDEV | |
7583 | NL80211_FLAG_NEED_RTNL, | 5966 | NL80211_FLAG_NEED_RTNL, |
7584 | }, | 5967 | }, |
7585 | { | 5968 | { |
@@ -7587,7 +5970,7 @@ static struct genl_ops nl80211_ops[] = { | |||
7587 | .doit = nl80211_remain_on_channel, | 5970 | .doit = nl80211_remain_on_channel, |
7588 | .policy = nl80211_policy, | 5971 | .policy = nl80211_policy, |
7589 | .flags = GENL_ADMIN_PERM, | 5972 | .flags = GENL_ADMIN_PERM, |
7590 | .internal_flags = NL80211_FLAG_NEED_WDEV_UP | | 5973 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
7591 | NL80211_FLAG_NEED_RTNL, | 5974 | NL80211_FLAG_NEED_RTNL, |
7592 | }, | 5975 | }, |
7593 | { | 5976 | { |
@@ -7595,7 +5978,7 @@ static struct genl_ops nl80211_ops[] = { | |||
7595 | .doit = nl80211_cancel_remain_on_channel, | 5978 | .doit = nl80211_cancel_remain_on_channel, |
7596 | .policy = nl80211_policy, | 5979 | .policy = nl80211_policy, |
7597 | .flags = GENL_ADMIN_PERM, | 5980 | .flags = GENL_ADMIN_PERM, |
7598 | .internal_flags = NL80211_FLAG_NEED_WDEV_UP | | 5981 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
7599 | NL80211_FLAG_NEED_RTNL, | 5982 | NL80211_FLAG_NEED_RTNL, |
7600 | }, | 5983 | }, |
7601 | { | 5984 | { |
@@ -7611,7 +5994,7 @@ static struct genl_ops nl80211_ops[] = { | |||
7611 | .doit = nl80211_register_mgmt, | 5994 | .doit = nl80211_register_mgmt, |
7612 | .policy = nl80211_policy, | 5995 | .policy = nl80211_policy, |
7613 | .flags = GENL_ADMIN_PERM, | 5996 | .flags = GENL_ADMIN_PERM, |
7614 | .internal_flags = NL80211_FLAG_NEED_WDEV | | 5997 | .internal_flags = NL80211_FLAG_NEED_NETDEV | |
7615 | NL80211_FLAG_NEED_RTNL, | 5998 | NL80211_FLAG_NEED_RTNL, |
7616 | }, | 5999 | }, |
7617 | { | 6000 | { |
@@ -7619,7 +6002,7 @@ static struct genl_ops nl80211_ops[] = { | |||
7619 | .doit = nl80211_tx_mgmt, | 6002 | .doit = nl80211_tx_mgmt, |
7620 | .policy = nl80211_policy, | 6003 | .policy = nl80211_policy, |
7621 | .flags = GENL_ADMIN_PERM, | 6004 | .flags = GENL_ADMIN_PERM, |
7622 | .internal_flags = NL80211_FLAG_NEED_WDEV_UP | | 6005 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
7623 | NL80211_FLAG_NEED_RTNL, | 6006 | NL80211_FLAG_NEED_RTNL, |
7624 | }, | 6007 | }, |
7625 | { | 6008 | { |
@@ -7627,7 +6010,7 @@ static struct genl_ops nl80211_ops[] = { | |||
7627 | .doit = nl80211_tx_mgmt_cancel_wait, | 6010 | .doit = nl80211_tx_mgmt_cancel_wait, |
7628 | .policy = nl80211_policy, | 6011 | .policy = nl80211_policy, |
7629 | .flags = GENL_ADMIN_PERM, | 6012 | .flags = GENL_ADMIN_PERM, |
7630 | .internal_flags = NL80211_FLAG_NEED_WDEV_UP | | 6013 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
7631 | NL80211_FLAG_NEED_RTNL, | 6014 | NL80211_FLAG_NEED_RTNL, |
7632 | }, | 6015 | }, |
7633 | { | 6016 | { |
@@ -7686,7 +6069,6 @@ static struct genl_ops nl80211_ops[] = { | |||
7686 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | 6069 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
7687 | NL80211_FLAG_NEED_RTNL, | 6070 | NL80211_FLAG_NEED_RTNL, |
7688 | }, | 6071 | }, |
7689 | #ifdef CONFIG_PM | ||
7690 | { | 6072 | { |
7691 | .cmd = NL80211_CMD_GET_WOWLAN, | 6073 | .cmd = NL80211_CMD_GET_WOWLAN, |
7692 | .doit = nl80211_get_wowlan, | 6074 | .doit = nl80211_get_wowlan, |
@@ -7703,7 +6085,6 @@ static struct genl_ops nl80211_ops[] = { | |||
7703 | .internal_flags = NL80211_FLAG_NEED_WIPHY | | 6085 | .internal_flags = NL80211_FLAG_NEED_WIPHY | |
7704 | NL80211_FLAG_NEED_RTNL, | 6086 | NL80211_FLAG_NEED_RTNL, |
7705 | }, | 6087 | }, |
7706 | #endif | ||
7707 | { | 6088 | { |
7708 | .cmd = NL80211_CMD_SET_REKEY_OFFLOAD, | 6089 | .cmd = NL80211_CMD_SET_REKEY_OFFLOAD, |
7709 | .doit = nl80211_set_rekey_data, | 6090 | .doit = nl80211_set_rekey_data, |
@@ -7712,78 +6093,6 @@ static struct genl_ops nl80211_ops[] = { | |||
7712 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | 6093 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
7713 | NL80211_FLAG_NEED_RTNL, | 6094 | NL80211_FLAG_NEED_RTNL, |
7714 | }, | 6095 | }, |
7715 | { | ||
7716 | .cmd = NL80211_CMD_TDLS_MGMT, | ||
7717 | .doit = nl80211_tdls_mgmt, | ||
7718 | .policy = nl80211_policy, | ||
7719 | .flags = GENL_ADMIN_PERM, | ||
7720 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
7721 | NL80211_FLAG_NEED_RTNL, | ||
7722 | }, | ||
7723 | { | ||
7724 | .cmd = NL80211_CMD_TDLS_OPER, | ||
7725 | .doit = nl80211_tdls_oper, | ||
7726 | .policy = nl80211_policy, | ||
7727 | .flags = GENL_ADMIN_PERM, | ||
7728 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
7729 | NL80211_FLAG_NEED_RTNL, | ||
7730 | }, | ||
7731 | { | ||
7732 | .cmd = NL80211_CMD_UNEXPECTED_FRAME, | ||
7733 | .doit = nl80211_register_unexpected_frame, | ||
7734 | .policy = nl80211_policy, | ||
7735 | .flags = GENL_ADMIN_PERM, | ||
7736 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | ||
7737 | NL80211_FLAG_NEED_RTNL, | ||
7738 | }, | ||
7739 | { | ||
7740 | .cmd = NL80211_CMD_PROBE_CLIENT, | ||
7741 | .doit = nl80211_probe_client, | ||
7742 | .policy = nl80211_policy, | ||
7743 | .flags = GENL_ADMIN_PERM, | ||
7744 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
7745 | NL80211_FLAG_NEED_RTNL, | ||
7746 | }, | ||
7747 | { | ||
7748 | .cmd = NL80211_CMD_REGISTER_BEACONS, | ||
7749 | .doit = nl80211_register_beacons, | ||
7750 | .policy = nl80211_policy, | ||
7751 | .flags = GENL_ADMIN_PERM, | ||
7752 | .internal_flags = NL80211_FLAG_NEED_WIPHY | | ||
7753 | NL80211_FLAG_NEED_RTNL, | ||
7754 | }, | ||
7755 | { | ||
7756 | .cmd = NL80211_CMD_SET_NOACK_MAP, | ||
7757 | .doit = nl80211_set_noack_map, | ||
7758 | .policy = nl80211_policy, | ||
7759 | .flags = GENL_ADMIN_PERM, | ||
7760 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | ||
7761 | NL80211_FLAG_NEED_RTNL, | ||
7762 | }, | ||
7763 | { | ||
7764 | .cmd = NL80211_CMD_START_P2P_DEVICE, | ||
7765 | .doit = nl80211_start_p2p_device, | ||
7766 | .policy = nl80211_policy, | ||
7767 | .flags = GENL_ADMIN_PERM, | ||
7768 | .internal_flags = NL80211_FLAG_NEED_WDEV | | ||
7769 | NL80211_FLAG_NEED_RTNL, | ||
7770 | }, | ||
7771 | { | ||
7772 | .cmd = NL80211_CMD_STOP_P2P_DEVICE, | ||
7773 | .doit = nl80211_stop_p2p_device, | ||
7774 | .policy = nl80211_policy, | ||
7775 | .flags = GENL_ADMIN_PERM, | ||
7776 | .internal_flags = NL80211_FLAG_NEED_WDEV_UP | | ||
7777 | NL80211_FLAG_NEED_RTNL, | ||
7778 | }, | ||
7779 | { | ||
7780 | .cmd = NL80211_CMD_SET_MCAST_RATE, | ||
7781 | .doit = nl80211_set_mcast_rate, | ||
7782 | .policy = nl80211_policy, | ||
7783 | .flags = GENL_ADMIN_PERM, | ||
7784 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | ||
7785 | NL80211_FLAG_NEED_RTNL, | ||
7786 | }, | ||
7787 | }; | 6096 | }; |
7788 | 6097 | ||
7789 | static struct genl_multicast_group nl80211_mlme_mcgrp = { | 6098 | static struct genl_multicast_group nl80211_mlme_mcgrp = { |
@@ -7835,27 +6144,19 @@ static int nl80211_add_scan_req(struct sk_buff *msg, | |||
7835 | nest = nla_nest_start(msg, NL80211_ATTR_SCAN_SSIDS); | 6144 | nest = nla_nest_start(msg, NL80211_ATTR_SCAN_SSIDS); |
7836 | if (!nest) | 6145 | if (!nest) |
7837 | goto nla_put_failure; | 6146 | goto nla_put_failure; |
7838 | for (i = 0; i < req->n_ssids; i++) { | 6147 | for (i = 0; i < req->n_ssids; i++) |
7839 | if (nla_put(msg, i, req->ssids[i].ssid_len, req->ssids[i].ssid)) | 6148 | NLA_PUT(msg, i, req->ssids[i].ssid_len, req->ssids[i].ssid); |
7840 | goto nla_put_failure; | ||
7841 | } | ||
7842 | nla_nest_end(msg, nest); | 6149 | nla_nest_end(msg, nest); |
7843 | 6150 | ||
7844 | nest = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES); | 6151 | nest = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES); |
7845 | if (!nest) | 6152 | if (!nest) |
7846 | goto nla_put_failure; | 6153 | goto nla_put_failure; |
7847 | for (i = 0; i < req->n_channels; i++) { | 6154 | for (i = 0; i < req->n_channels; i++) |
7848 | if (nla_put_u32(msg, i, req->channels[i]->center_freq)) | 6155 | NLA_PUT_U32(msg, i, req->channels[i]->center_freq); |
7849 | goto nla_put_failure; | ||
7850 | } | ||
7851 | nla_nest_end(msg, nest); | 6156 | nla_nest_end(msg, nest); |
7852 | 6157 | ||
7853 | if (req->ie && | 6158 | if (req->ie) |
7854 | nla_put(msg, NL80211_ATTR_IE, req->ie_len, req->ie)) | 6159 | NLA_PUT(msg, NL80211_ATTR_IE, req->ie_len, req->ie); |
7855 | goto nla_put_failure; | ||
7856 | |||
7857 | if (req->flags) | ||
7858 | nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags); | ||
7859 | 6160 | ||
7860 | return 0; | 6161 | return 0; |
7861 | nla_put_failure: | 6162 | nla_put_failure: |
@@ -7864,21 +6165,18 @@ static int nl80211_add_scan_req(struct sk_buff *msg, | |||
7864 | 6165 | ||
7865 | static int nl80211_send_scan_msg(struct sk_buff *msg, | 6166 | static int nl80211_send_scan_msg(struct sk_buff *msg, |
7866 | struct cfg80211_registered_device *rdev, | 6167 | struct cfg80211_registered_device *rdev, |
7867 | struct wireless_dev *wdev, | 6168 | struct net_device *netdev, |
7868 | u32 portid, u32 seq, int flags, | 6169 | u32 pid, u32 seq, int flags, |
7869 | u32 cmd) | 6170 | u32 cmd) |
7870 | { | 6171 | { |
7871 | void *hdr; | 6172 | void *hdr; |
7872 | 6173 | ||
7873 | hdr = nl80211hdr_put(msg, portid, seq, flags, cmd); | 6174 | hdr = nl80211hdr_put(msg, pid, seq, flags, cmd); |
7874 | if (!hdr) | 6175 | if (!hdr) |
7875 | return -1; | 6176 | return -1; |
7876 | 6177 | ||
7877 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 6178 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); |
7878 | (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX, | 6179 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); |
7879 | wdev->netdev->ifindex)) || | ||
7880 | nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev))) | ||
7881 | goto nla_put_failure; | ||
7882 | 6180 | ||
7883 | /* ignore errors and send incomplete event anyway */ | 6181 | /* ignore errors and send incomplete event anyway */ |
7884 | nl80211_add_scan_req(msg, rdev); | 6182 | nl80211_add_scan_req(msg, rdev); |
@@ -7894,17 +6192,16 @@ static int | |||
7894 | nl80211_send_sched_scan_msg(struct sk_buff *msg, | 6192 | nl80211_send_sched_scan_msg(struct sk_buff *msg, |
7895 | struct cfg80211_registered_device *rdev, | 6193 | struct cfg80211_registered_device *rdev, |
7896 | struct net_device *netdev, | 6194 | struct net_device *netdev, |
7897 | u32 portid, u32 seq, int flags, u32 cmd) | 6195 | u32 pid, u32 seq, int flags, u32 cmd) |
7898 | { | 6196 | { |
7899 | void *hdr; | 6197 | void *hdr; |
7900 | 6198 | ||
7901 | hdr = nl80211hdr_put(msg, portid, seq, flags, cmd); | 6199 | hdr = nl80211hdr_put(msg, pid, seq, flags, cmd); |
7902 | if (!hdr) | 6200 | if (!hdr) |
7903 | return -1; | 6201 | return -1; |
7904 | 6202 | ||
7905 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 6203 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); |
7906 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex)) | 6204 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); |
7907 | goto nla_put_failure; | ||
7908 | 6205 | ||
7909 | return genlmsg_end(msg, hdr); | 6206 | return genlmsg_end(msg, hdr); |
7910 | 6207 | ||
@@ -7914,15 +6211,15 @@ nl80211_send_sched_scan_msg(struct sk_buff *msg, | |||
7914 | } | 6211 | } |
7915 | 6212 | ||
7916 | void nl80211_send_scan_start(struct cfg80211_registered_device *rdev, | 6213 | void nl80211_send_scan_start(struct cfg80211_registered_device *rdev, |
7917 | struct wireless_dev *wdev) | 6214 | struct net_device *netdev) |
7918 | { | 6215 | { |
7919 | struct sk_buff *msg; | 6216 | struct sk_buff *msg; |
7920 | 6217 | ||
7921 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 6218 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); |
7922 | if (!msg) | 6219 | if (!msg) |
7923 | return; | 6220 | return; |
7924 | 6221 | ||
7925 | if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0, | 6222 | if (nl80211_send_scan_msg(msg, rdev, netdev, 0, 0, 0, |
7926 | NL80211_CMD_TRIGGER_SCAN) < 0) { | 6223 | NL80211_CMD_TRIGGER_SCAN) < 0) { |
7927 | nlmsg_free(msg); | 6224 | nlmsg_free(msg); |
7928 | return; | 6225 | return; |
@@ -7933,7 +6230,7 @@ void nl80211_send_scan_start(struct cfg80211_registered_device *rdev, | |||
7933 | } | 6230 | } |
7934 | 6231 | ||
7935 | void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, | 6232 | void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, |
7936 | struct wireless_dev *wdev) | 6233 | struct net_device *netdev) |
7937 | { | 6234 | { |
7938 | struct sk_buff *msg; | 6235 | struct sk_buff *msg; |
7939 | 6236 | ||
@@ -7941,7 +6238,7 @@ void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, | |||
7941 | if (!msg) | 6238 | if (!msg) |
7942 | return; | 6239 | return; |
7943 | 6240 | ||
7944 | if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0, | 6241 | if (nl80211_send_scan_msg(msg, rdev, netdev, 0, 0, 0, |
7945 | NL80211_CMD_NEW_SCAN_RESULTS) < 0) { | 6242 | NL80211_CMD_NEW_SCAN_RESULTS) < 0) { |
7946 | nlmsg_free(msg); | 6243 | nlmsg_free(msg); |
7947 | return; | 6244 | return; |
@@ -7952,7 +6249,7 @@ void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, | |||
7952 | } | 6249 | } |
7953 | 6250 | ||
7954 | void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, | 6251 | void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, |
7955 | struct wireless_dev *wdev) | 6252 | struct net_device *netdev) |
7956 | { | 6253 | { |
7957 | struct sk_buff *msg; | 6254 | struct sk_buff *msg; |
7958 | 6255 | ||
@@ -7960,7 +6257,7 @@ void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, | |||
7960 | if (!msg) | 6257 | if (!msg) |
7961 | return; | 6258 | return; |
7962 | 6259 | ||
7963 | if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0, | 6260 | if (nl80211_send_scan_msg(msg, rdev, netdev, 0, 0, 0, |
7964 | NL80211_CMD_SCAN_ABORTED) < 0) { | 6261 | NL80211_CMD_SCAN_ABORTED) < 0) { |
7965 | nlmsg_free(msg); | 6262 | nlmsg_free(msg); |
7966 | return; | 6263 | return; |
@@ -7994,7 +6291,7 @@ void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev, | |||
7994 | { | 6291 | { |
7995 | struct sk_buff *msg; | 6292 | struct sk_buff *msg; |
7996 | 6293 | ||
7997 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 6294 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); |
7998 | if (!msg) | 6295 | if (!msg) |
7999 | return; | 6296 | return; |
8000 | 6297 | ||
@@ -8027,36 +6324,32 @@ void nl80211_send_reg_change_event(struct regulatory_request *request) | |||
8027 | } | 6324 | } |
8028 | 6325 | ||
8029 | /* Userspace can always count this one always being set */ | 6326 | /* Userspace can always count this one always being set */ |
8030 | if (nla_put_u8(msg, NL80211_ATTR_REG_INITIATOR, request->initiator)) | 6327 | NLA_PUT_U8(msg, NL80211_ATTR_REG_INITIATOR, request->initiator); |
8031 | goto nla_put_failure; | 6328 | |
8032 | 6329 | if (request->alpha2[0] == '0' && request->alpha2[1] == '0') | |
8033 | if (request->alpha2[0] == '0' && request->alpha2[1] == '0') { | 6330 | NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE, |
8034 | if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE, | 6331 | NL80211_REGDOM_TYPE_WORLD); |
8035 | NL80211_REGDOM_TYPE_WORLD)) | 6332 | else if (request->alpha2[0] == '9' && request->alpha2[1] == '9') |
8036 | goto nla_put_failure; | 6333 | NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE, |
8037 | } else if (request->alpha2[0] == '9' && request->alpha2[1] == '9') { | 6334 | NL80211_REGDOM_TYPE_CUSTOM_WORLD); |
8038 | if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE, | 6335 | else if ((request->alpha2[0] == '9' && request->alpha2[1] == '8') || |
8039 | NL80211_REGDOM_TYPE_CUSTOM_WORLD)) | 6336 | request->intersect) |
8040 | goto nla_put_failure; | 6337 | NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE, |
8041 | } else if ((request->alpha2[0] == '9' && request->alpha2[1] == '8') || | 6338 | NL80211_REGDOM_TYPE_INTERSECTION); |
8042 | request->intersect) { | 6339 | else { |
8043 | if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE, | 6340 | NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE, |
8044 | NL80211_REGDOM_TYPE_INTERSECTION)) | 6341 | NL80211_REGDOM_TYPE_COUNTRY); |
8045 | goto nla_put_failure; | 6342 | NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, request->alpha2); |
8046 | } else { | 6343 | } |
8047 | if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE, | 6344 | |
8048 | NL80211_REGDOM_TYPE_COUNTRY) || | 6345 | if (wiphy_idx_valid(request->wiphy_idx)) |
8049 | nla_put_string(msg, NL80211_ATTR_REG_ALPHA2, | 6346 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx); |
8050 | request->alpha2)) | 6347 | |
8051 | goto nla_put_failure; | 6348 | if (genlmsg_end(msg, hdr) < 0) { |
6349 | nlmsg_free(msg); | ||
6350 | return; | ||
8052 | } | 6351 | } |
8053 | 6352 | ||
8054 | if (wiphy_idx_valid(request->wiphy_idx) && | ||
8055 | nla_put_u32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx)) | ||
8056 | goto nla_put_failure; | ||
8057 | |||
8058 | genlmsg_end(msg, hdr); | ||
8059 | |||
8060 | rcu_read_lock(); | 6353 | rcu_read_lock(); |
8061 | genlmsg_multicast_allns(msg, 0, nl80211_regulatory_mcgrp.id, | 6354 | genlmsg_multicast_allns(msg, 0, nl80211_regulatory_mcgrp.id, |
8062 | GFP_ATOMIC); | 6355 | GFP_ATOMIC); |
@@ -8087,12 +6380,14 @@ static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev, | |||
8087 | return; | 6380 | return; |
8088 | } | 6381 | } |
8089 | 6382 | ||
8090 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 6383 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); |
8091 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || | 6384 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); |
8092 | nla_put(msg, NL80211_ATTR_FRAME, len, buf)) | 6385 | NLA_PUT(msg, NL80211_ATTR_FRAME, len, buf); |
8093 | goto nla_put_failure; | ||
8094 | 6386 | ||
8095 | genlmsg_end(msg, hdr); | 6387 | if (genlmsg_end(msg, hdr) < 0) { |
6388 | nlmsg_free(msg); | ||
6389 | return; | ||
6390 | } | ||
8096 | 6391 | ||
8097 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | 6392 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
8098 | nl80211_mlme_mcgrp.id, gfp); | 6393 | nl80211_mlme_mcgrp.id, gfp); |
@@ -8168,13 +6463,15 @@ static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev, | |||
8168 | return; | 6463 | return; |
8169 | } | 6464 | } |
8170 | 6465 | ||
8171 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 6466 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); |
8172 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || | 6467 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); |
8173 | nla_put_flag(msg, NL80211_ATTR_TIMED_OUT) || | 6468 | NLA_PUT_FLAG(msg, NL80211_ATTR_TIMED_OUT); |
8174 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) | 6469 | NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); |
8175 | goto nla_put_failure; | ||
8176 | 6470 | ||
8177 | genlmsg_end(msg, hdr); | 6471 | if (genlmsg_end(msg, hdr) < 0) { |
6472 | nlmsg_free(msg); | ||
6473 | return; | ||
6474 | } | ||
8178 | 6475 | ||
8179 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | 6476 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
8180 | nl80211_mlme_mcgrp.id, gfp); | 6477 | nl80211_mlme_mcgrp.id, gfp); |
@@ -8210,7 +6507,7 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev, | |||
8210 | struct sk_buff *msg; | 6507 | struct sk_buff *msg; |
8211 | void *hdr; | 6508 | void *hdr; |
8212 | 6509 | ||
8213 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | 6510 | msg = nlmsg_new(NLMSG_GOODSIZE, gfp); |
8214 | if (!msg) | 6511 | if (!msg) |
8215 | return; | 6512 | return; |
8216 | 6513 | ||
@@ -8220,17 +6517,20 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev, | |||
8220 | return; | 6517 | return; |
8221 | } | 6518 | } |
8222 | 6519 | ||
8223 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 6520 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); |
8224 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || | 6521 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); |
8225 | (bssid && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid)) || | 6522 | if (bssid) |
8226 | nla_put_u16(msg, NL80211_ATTR_STATUS_CODE, status) || | 6523 | NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid); |
8227 | (req_ie && | 6524 | NLA_PUT_U16(msg, NL80211_ATTR_STATUS_CODE, status); |
8228 | nla_put(msg, NL80211_ATTR_REQ_IE, req_ie_len, req_ie)) || | 6525 | if (req_ie) |
8229 | (resp_ie && | 6526 | NLA_PUT(msg, NL80211_ATTR_REQ_IE, req_ie_len, req_ie); |
8230 | nla_put(msg, NL80211_ATTR_RESP_IE, resp_ie_len, resp_ie))) | 6527 | if (resp_ie) |
8231 | goto nla_put_failure; | 6528 | NLA_PUT(msg, NL80211_ATTR_RESP_IE, resp_ie_len, resp_ie); |
8232 | 6529 | ||
8233 | genlmsg_end(msg, hdr); | 6530 | if (genlmsg_end(msg, hdr) < 0) { |
6531 | nlmsg_free(msg); | ||
6532 | return; | ||
6533 | } | ||
8234 | 6534 | ||
8235 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | 6535 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
8236 | nl80211_mlme_mcgrp.id, gfp); | 6536 | nl80211_mlme_mcgrp.id, gfp); |
@@ -8250,7 +6550,7 @@ void nl80211_send_roamed(struct cfg80211_registered_device *rdev, | |||
8250 | struct sk_buff *msg; | 6550 | struct sk_buff *msg; |
8251 | void *hdr; | 6551 | void *hdr; |
8252 | 6552 | ||
8253 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | 6553 | msg = nlmsg_new(NLMSG_GOODSIZE, gfp); |
8254 | if (!msg) | 6554 | if (!msg) |
8255 | return; | 6555 | return; |
8256 | 6556 | ||
@@ -8260,16 +6560,18 @@ void nl80211_send_roamed(struct cfg80211_registered_device *rdev, | |||
8260 | return; | 6560 | return; |
8261 | } | 6561 | } |
8262 | 6562 | ||
8263 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 6563 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); |
8264 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || | 6564 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); |
8265 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid) || | 6565 | NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid); |
8266 | (req_ie && | 6566 | if (req_ie) |
8267 | nla_put(msg, NL80211_ATTR_REQ_IE, req_ie_len, req_ie)) || | 6567 | NLA_PUT(msg, NL80211_ATTR_REQ_IE, req_ie_len, req_ie); |
8268 | (resp_ie && | 6568 | if (resp_ie) |
8269 | nla_put(msg, NL80211_ATTR_RESP_IE, resp_ie_len, resp_ie))) | 6569 | NLA_PUT(msg, NL80211_ATTR_RESP_IE, resp_ie_len, resp_ie); |
8270 | goto nla_put_failure; | ||
8271 | 6570 | ||
8272 | genlmsg_end(msg, hdr); | 6571 | if (genlmsg_end(msg, hdr) < 0) { |
6572 | nlmsg_free(msg); | ||
6573 | return; | ||
6574 | } | ||
8273 | 6575 | ||
8274 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | 6576 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
8275 | nl80211_mlme_mcgrp.id, gfp); | 6577 | nl80211_mlme_mcgrp.id, gfp); |
@@ -8288,7 +6590,7 @@ void nl80211_send_disconnected(struct cfg80211_registered_device *rdev, | |||
8288 | struct sk_buff *msg; | 6590 | struct sk_buff *msg; |
8289 | void *hdr; | 6591 | void *hdr; |
8290 | 6592 | ||
8291 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 6593 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); |
8292 | if (!msg) | 6594 | if (!msg) |
8293 | return; | 6595 | return; |
8294 | 6596 | ||
@@ -8298,16 +6600,19 @@ void nl80211_send_disconnected(struct cfg80211_registered_device *rdev, | |||
8298 | return; | 6600 | return; |
8299 | } | 6601 | } |
8300 | 6602 | ||
8301 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 6603 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); |
8302 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || | 6604 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); |
8303 | (from_ap && reason && | 6605 | if (from_ap && reason) |
8304 | nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason)) || | 6606 | NLA_PUT_U16(msg, NL80211_ATTR_REASON_CODE, reason); |
8305 | (from_ap && | 6607 | if (from_ap) |
8306 | nla_put_flag(msg, NL80211_ATTR_DISCONNECTED_BY_AP)) || | 6608 | NLA_PUT_FLAG(msg, NL80211_ATTR_DISCONNECTED_BY_AP); |
8307 | (ie && nla_put(msg, NL80211_ATTR_IE, ie_len, ie))) | 6609 | if (ie) |
8308 | goto nla_put_failure; | 6610 | NLA_PUT(msg, NL80211_ATTR_IE, ie_len, ie); |
8309 | 6611 | ||
8310 | genlmsg_end(msg, hdr); | 6612 | if (genlmsg_end(msg, hdr) < 0) { |
6613 | nlmsg_free(msg); | ||
6614 | return; | ||
6615 | } | ||
8311 | 6616 | ||
8312 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | 6617 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
8313 | nl80211_mlme_mcgrp.id, GFP_KERNEL); | 6618 | nl80211_mlme_mcgrp.id, GFP_KERNEL); |
@@ -8336,12 +6641,14 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev, | |||
8336 | return; | 6641 | return; |
8337 | } | 6642 | } |
8338 | 6643 | ||
8339 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 6644 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); |
8340 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || | 6645 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); |
8341 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid)) | 6646 | NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid); |
8342 | goto nla_put_failure; | ||
8343 | 6647 | ||
8344 | genlmsg_end(msg, hdr); | 6648 | if (genlmsg_end(msg, hdr) < 0) { |
6649 | nlmsg_free(msg); | ||
6650 | return; | ||
6651 | } | ||
8345 | 6652 | ||
8346 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | 6653 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
8347 | nl80211_mlme_mcgrp.id, gfp); | 6654 | nl80211_mlme_mcgrp.id, gfp); |
@@ -8370,14 +6677,16 @@ void nl80211_send_new_peer_candidate(struct cfg80211_registered_device *rdev, | |||
8370 | return; | 6677 | return; |
8371 | } | 6678 | } |
8372 | 6679 | ||
8373 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 6680 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); |
8374 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || | 6681 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); |
8375 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, macaddr) || | 6682 | NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, macaddr); |
8376 | (ie_len && ie && | 6683 | if (ie_len && ie) |
8377 | nla_put(msg, NL80211_ATTR_IE, ie_len , ie))) | 6684 | NLA_PUT(msg, NL80211_ATTR_IE, ie_len , ie); |
8378 | goto nla_put_failure; | ||
8379 | 6685 | ||
8380 | genlmsg_end(msg, hdr); | 6686 | if (genlmsg_end(msg, hdr) < 0) { |
6687 | nlmsg_free(msg); | ||
6688 | return; | ||
6689 | } | ||
8381 | 6690 | ||
8382 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | 6691 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
8383 | nl80211_mlme_mcgrp.id, gfp); | 6692 | nl80211_mlme_mcgrp.id, gfp); |
@@ -8406,16 +6715,20 @@ void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, | |||
8406 | return; | 6715 | return; |
8407 | } | 6716 | } |
8408 | 6717 | ||
8409 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 6718 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); |
8410 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || | 6719 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); |
8411 | (addr && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) || | 6720 | if (addr) |
8412 | nla_put_u32(msg, NL80211_ATTR_KEY_TYPE, key_type) || | 6721 | NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); |
8413 | (key_id != -1 && | 6722 | NLA_PUT_U32(msg, NL80211_ATTR_KEY_TYPE, key_type); |
8414 | nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_id)) || | 6723 | if (key_id != -1) |
8415 | (tsc && nla_put(msg, NL80211_ATTR_KEY_SEQ, 6, tsc))) | 6724 | NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_id); |
8416 | goto nla_put_failure; | 6725 | if (tsc) |
6726 | NLA_PUT(msg, NL80211_ATTR_KEY_SEQ, 6, tsc); | ||
8417 | 6727 | ||
8418 | genlmsg_end(msg, hdr); | 6728 | if (genlmsg_end(msg, hdr) < 0) { |
6729 | nlmsg_free(msg); | ||
6730 | return; | ||
6731 | } | ||
8419 | 6732 | ||
8420 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | 6733 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
8421 | nl80211_mlme_mcgrp.id, gfp); | 6734 | nl80211_mlme_mcgrp.id, gfp); |
@@ -8448,8 +6761,7 @@ void nl80211_send_beacon_hint_event(struct wiphy *wiphy, | |||
8448 | * Since we are applying the beacon hint to a wiphy we know its | 6761 | * Since we are applying the beacon hint to a wiphy we know its |
8449 | * wiphy_idx is valid | 6762 | * wiphy_idx is valid |
8450 | */ | 6763 | */ |
8451 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy))) | 6764 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)); |
8452 | goto nla_put_failure; | ||
8453 | 6765 | ||
8454 | /* Before */ | 6766 | /* Before */ |
8455 | nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_BEFORE); | 6767 | nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_BEFORE); |
@@ -8467,7 +6779,10 @@ void nl80211_send_beacon_hint_event(struct wiphy *wiphy, | |||
8467 | goto nla_put_failure; | 6779 | goto nla_put_failure; |
8468 | nla_nest_end(msg, nl_freq); | 6780 | nla_nest_end(msg, nl_freq); |
8469 | 6781 | ||
8470 | genlmsg_end(msg, hdr); | 6782 | if (genlmsg_end(msg, hdr) < 0) { |
6783 | nlmsg_free(msg); | ||
6784 | return; | ||
6785 | } | ||
8471 | 6786 | ||
8472 | rcu_read_lock(); | 6787 | rcu_read_lock(); |
8473 | genlmsg_multicast_allns(msg, 0, nl80211_regulatory_mcgrp.id, | 6788 | genlmsg_multicast_allns(msg, 0, nl80211_regulatory_mcgrp.id, |
@@ -8483,8 +6798,9 @@ nla_put_failure: | |||
8483 | 6798 | ||
8484 | static void nl80211_send_remain_on_chan_event( | 6799 | static void nl80211_send_remain_on_chan_event( |
8485 | int cmd, struct cfg80211_registered_device *rdev, | 6800 | int cmd, struct cfg80211_registered_device *rdev, |
8486 | struct wireless_dev *wdev, u64 cookie, | 6801 | struct net_device *netdev, u64 cookie, |
8487 | struct ieee80211_channel *chan, | 6802 | struct ieee80211_channel *chan, |
6803 | enum nl80211_channel_type channel_type, | ||
8488 | unsigned int duration, gfp_t gfp) | 6804 | unsigned int duration, gfp_t gfp) |
8489 | { | 6805 | { |
8490 | struct sk_buff *msg; | 6806 | struct sk_buff *msg; |
@@ -8500,21 +6816,19 @@ static void nl80211_send_remain_on_chan_event( | |||
8500 | return; | 6816 | return; |
8501 | } | 6817 | } |
8502 | 6818 | ||
8503 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 6819 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); |
8504 | (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX, | 6820 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); |
8505 | wdev->netdev->ifindex)) || | 6821 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, chan->center_freq); |
8506 | nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) || | 6822 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, channel_type); |
8507 | nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, chan->center_freq) || | 6823 | NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie); |
8508 | nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, | ||
8509 | NL80211_CHAN_NO_HT) || | ||
8510 | nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie)) | ||
8511 | goto nla_put_failure; | ||
8512 | 6824 | ||
8513 | if (cmd == NL80211_CMD_REMAIN_ON_CHANNEL && | 6825 | if (cmd == NL80211_CMD_REMAIN_ON_CHANNEL) |
8514 | nla_put_u32(msg, NL80211_ATTR_DURATION, duration)) | 6826 | NLA_PUT_U32(msg, NL80211_ATTR_DURATION, duration); |
8515 | goto nla_put_failure; | ||
8516 | 6827 | ||
8517 | genlmsg_end(msg, hdr); | 6828 | if (genlmsg_end(msg, hdr) < 0) { |
6829 | nlmsg_free(msg); | ||
6830 | return; | ||
6831 | } | ||
8518 | 6832 | ||
8519 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | 6833 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
8520 | nl80211_mlme_mcgrp.id, gfp); | 6834 | nl80211_mlme_mcgrp.id, gfp); |
@@ -8526,22 +6840,24 @@ static void nl80211_send_remain_on_chan_event( | |||
8526 | } | 6840 | } |
8527 | 6841 | ||
8528 | void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev, | 6842 | void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev, |
8529 | struct wireless_dev *wdev, u64 cookie, | 6843 | struct net_device *netdev, u64 cookie, |
8530 | struct ieee80211_channel *chan, | 6844 | struct ieee80211_channel *chan, |
6845 | enum nl80211_channel_type channel_type, | ||
8531 | unsigned int duration, gfp_t gfp) | 6846 | unsigned int duration, gfp_t gfp) |
8532 | { | 6847 | { |
8533 | nl80211_send_remain_on_chan_event(NL80211_CMD_REMAIN_ON_CHANNEL, | 6848 | nl80211_send_remain_on_chan_event(NL80211_CMD_REMAIN_ON_CHANNEL, |
8534 | rdev, wdev, cookie, chan, | 6849 | rdev, netdev, cookie, chan, |
8535 | duration, gfp); | 6850 | channel_type, duration, gfp); |
8536 | } | 6851 | } |
8537 | 6852 | ||
8538 | void nl80211_send_remain_on_channel_cancel( | 6853 | void nl80211_send_remain_on_channel_cancel( |
8539 | struct cfg80211_registered_device *rdev, | 6854 | struct cfg80211_registered_device *rdev, struct net_device *netdev, |
8540 | struct wireless_dev *wdev, | 6855 | u64 cookie, struct ieee80211_channel *chan, |
8541 | u64 cookie, struct ieee80211_channel *chan, gfp_t gfp) | 6856 | enum nl80211_channel_type channel_type, gfp_t gfp) |
8542 | { | 6857 | { |
8543 | nl80211_send_remain_on_chan_event(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, | 6858 | nl80211_send_remain_on_chan_event(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, |
8544 | rdev, wdev, cookie, chan, 0, gfp); | 6859 | rdev, netdev, cookie, chan, |
6860 | channel_type, 0, gfp); | ||
8545 | } | 6861 | } |
8546 | 6862 | ||
8547 | void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, | 6863 | void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, |
@@ -8550,12 +6866,11 @@ void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, | |||
8550 | { | 6866 | { |
8551 | struct sk_buff *msg; | 6867 | struct sk_buff *msg; |
8552 | 6868 | ||
8553 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | 6869 | msg = nlmsg_new(NLMSG_GOODSIZE, gfp); |
8554 | if (!msg) | 6870 | if (!msg) |
8555 | return; | 6871 | return; |
8556 | 6872 | ||
8557 | if (nl80211_send_station(msg, 0, 0, 0, | 6873 | if (nl80211_send_station(msg, 0, 0, 0, dev, mac_addr, sinfo) < 0) { |
8558 | rdev, dev, mac_addr, sinfo) < 0) { | ||
8559 | nlmsg_free(msg); | 6874 | nlmsg_free(msg); |
8560 | return; | 6875 | return; |
8561 | } | 6876 | } |
@@ -8571,7 +6886,7 @@ void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev, | |||
8571 | struct sk_buff *msg; | 6886 | struct sk_buff *msg; |
8572 | void *hdr; | 6887 | void *hdr; |
8573 | 6888 | ||
8574 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | 6889 | msg = nlmsg_new(NLMSG_GOODSIZE, gfp); |
8575 | if (!msg) | 6890 | if (!msg) |
8576 | return; | 6891 | return; |
8577 | 6892 | ||
@@ -8581,46 +6896,14 @@ void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev, | |||
8581 | return; | 6896 | return; |
8582 | } | 6897 | } |
8583 | 6898 | ||
8584 | if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || | 6899 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); |
8585 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr)) | 6900 | NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); |
8586 | goto nla_put_failure; | ||
8587 | |||
8588 | genlmsg_end(msg, hdr); | ||
8589 | |||
8590 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | ||
8591 | nl80211_mlme_mcgrp.id, gfp); | ||
8592 | return; | ||
8593 | |||
8594 | nla_put_failure: | ||
8595 | genlmsg_cancel(msg, hdr); | ||
8596 | nlmsg_free(msg); | ||
8597 | } | ||
8598 | |||
8599 | void nl80211_send_conn_failed_event(struct cfg80211_registered_device *rdev, | ||
8600 | struct net_device *dev, const u8 *mac_addr, | ||
8601 | enum nl80211_connect_failed_reason reason, | ||
8602 | gfp_t gfp) | ||
8603 | { | ||
8604 | struct sk_buff *msg; | ||
8605 | void *hdr; | ||
8606 | |||
8607 | msg = nlmsg_new(NLMSG_GOODSIZE, gfp); | ||
8608 | if (!msg) | ||
8609 | return; | ||
8610 | 6901 | ||
8611 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONN_FAILED); | 6902 | if (genlmsg_end(msg, hdr) < 0) { |
8612 | if (!hdr) { | ||
8613 | nlmsg_free(msg); | 6903 | nlmsg_free(msg); |
8614 | return; | 6904 | return; |
8615 | } | 6905 | } |
8616 | 6906 | ||
8617 | if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || | ||
8618 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr) || | ||
8619 | nla_put_u32(msg, NL80211_ATTR_CONN_FAILED_REASON, reason)) | ||
8620 | goto nla_put_failure; | ||
8621 | |||
8622 | genlmsg_end(msg, hdr); | ||
8623 | |||
8624 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | 6907 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
8625 | nl80211_mlme_mcgrp.id, gfp); | 6908 | nl80211_mlme_mcgrp.id, gfp); |
8626 | return; | 6909 | return; |
@@ -8630,71 +6913,13 @@ void nl80211_send_conn_failed_event(struct cfg80211_registered_device *rdev, | |||
8630 | nlmsg_free(msg); | 6913 | nlmsg_free(msg); |
8631 | } | 6914 | } |
8632 | 6915 | ||
8633 | static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd, | ||
8634 | const u8 *addr, gfp_t gfp) | ||
8635 | { | ||
8636 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
8637 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | ||
8638 | struct sk_buff *msg; | ||
8639 | void *hdr; | ||
8640 | int err; | ||
8641 | u32 nlportid = ACCESS_ONCE(wdev->ap_unexpected_nlportid); | ||
8642 | |||
8643 | if (!nlportid) | ||
8644 | return false; | ||
8645 | |||
8646 | msg = nlmsg_new(100, gfp); | ||
8647 | if (!msg) | ||
8648 | return true; | ||
8649 | |||
8650 | hdr = nl80211hdr_put(msg, 0, 0, 0, cmd); | ||
8651 | if (!hdr) { | ||
8652 | nlmsg_free(msg); | ||
8653 | return true; | ||
8654 | } | ||
8655 | |||
8656 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | ||
8657 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || | ||
8658 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) | ||
8659 | goto nla_put_failure; | ||
8660 | |||
8661 | err = genlmsg_end(msg, hdr); | ||
8662 | if (err < 0) { | ||
8663 | nlmsg_free(msg); | ||
8664 | return true; | ||
8665 | } | ||
8666 | |||
8667 | genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid); | ||
8668 | return true; | ||
8669 | |||
8670 | nla_put_failure: | ||
8671 | genlmsg_cancel(msg, hdr); | ||
8672 | nlmsg_free(msg); | ||
8673 | return true; | ||
8674 | } | ||
8675 | |||
8676 | bool nl80211_unexpected_frame(struct net_device *dev, const u8 *addr, gfp_t gfp) | ||
8677 | { | ||
8678 | return __nl80211_unexpected_frame(dev, NL80211_CMD_UNEXPECTED_FRAME, | ||
8679 | addr, gfp); | ||
8680 | } | ||
8681 | |||
8682 | bool nl80211_unexpected_4addr_frame(struct net_device *dev, | ||
8683 | const u8 *addr, gfp_t gfp) | ||
8684 | { | ||
8685 | return __nl80211_unexpected_frame(dev, | ||
8686 | NL80211_CMD_UNEXPECTED_4ADDR_FRAME, | ||
8687 | addr, gfp); | ||
8688 | } | ||
8689 | |||
8690 | int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, | 6916 | int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, |
8691 | struct wireless_dev *wdev, u32 nlportid, | 6917 | struct net_device *netdev, u32 nlpid, |
8692 | int freq, int sig_dbm, | 6918 | int freq, const u8 *buf, size_t len, gfp_t gfp) |
8693 | const u8 *buf, size_t len, gfp_t gfp) | ||
8694 | { | 6919 | { |
8695 | struct net_device *netdev = wdev->netdev; | ||
8696 | struct sk_buff *msg; | 6920 | struct sk_buff *msg; |
8697 | void *hdr; | 6921 | void *hdr; |
6922 | int err; | ||
8698 | 6923 | ||
8699 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | 6924 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); |
8700 | if (!msg) | 6925 | if (!msg) |
@@ -8706,18 +6931,21 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, | |||
8706 | return -ENOMEM; | 6931 | return -ENOMEM; |
8707 | } | 6932 | } |
8708 | 6933 | ||
8709 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 6934 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); |
8710 | (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX, | 6935 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); |
8711 | netdev->ifindex)) || | 6936 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq); |
8712 | nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) || | 6937 | NLA_PUT(msg, NL80211_ATTR_FRAME, len, buf); |
8713 | (sig_dbm && | ||
8714 | nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) || | ||
8715 | nla_put(msg, NL80211_ATTR_FRAME, len, buf)) | ||
8716 | goto nla_put_failure; | ||
8717 | 6938 | ||
8718 | genlmsg_end(msg, hdr); | 6939 | err = genlmsg_end(msg, hdr); |
6940 | if (err < 0) { | ||
6941 | nlmsg_free(msg); | ||
6942 | return err; | ||
6943 | } | ||
8719 | 6944 | ||
8720 | return genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid); | 6945 | err = genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlpid); |
6946 | if (err < 0) | ||
6947 | return err; | ||
6948 | return 0; | ||
8721 | 6949 | ||
8722 | nla_put_failure: | 6950 | nla_put_failure: |
8723 | genlmsg_cancel(msg, hdr); | 6951 | genlmsg_cancel(msg, hdr); |
@@ -8726,11 +6954,10 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, | |||
8726 | } | 6954 | } |
8727 | 6955 | ||
8728 | void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev, | 6956 | void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev, |
8729 | struct wireless_dev *wdev, u64 cookie, | 6957 | struct net_device *netdev, u64 cookie, |
8730 | const u8 *buf, size_t len, bool ack, | 6958 | const u8 *buf, size_t len, bool ack, |
8731 | gfp_t gfp) | 6959 | gfp_t gfp) |
8732 | { | 6960 | { |
8733 | struct net_device *netdev = wdev->netdev; | ||
8734 | struct sk_buff *msg; | 6961 | struct sk_buff *msg; |
8735 | void *hdr; | 6962 | void *hdr; |
8736 | 6963 | ||
@@ -8744,15 +6971,17 @@ void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev, | |||
8744 | return; | 6971 | return; |
8745 | } | 6972 | } |
8746 | 6973 | ||
8747 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 6974 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); |
8748 | (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX, | 6975 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); |
8749 | netdev->ifindex)) || | 6976 | NLA_PUT(msg, NL80211_ATTR_FRAME, len, buf); |
8750 | nla_put(msg, NL80211_ATTR_FRAME, len, buf) || | 6977 | NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie); |
8751 | nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie) || | 6978 | if (ack) |
8752 | (ack && nla_put_flag(msg, NL80211_ATTR_ACK))) | 6979 | NLA_PUT_FLAG(msg, NL80211_ATTR_ACK); |
8753 | goto nla_put_failure; | ||
8754 | 6980 | ||
8755 | genlmsg_end(msg, hdr); | 6981 | if (genlmsg_end(msg, hdr) < 0) { |
6982 | nlmsg_free(msg); | ||
6983 | return; | ||
6984 | } | ||
8756 | 6985 | ||
8757 | genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp); | 6986 | genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp); |
8758 | return; | 6987 | return; |
@@ -8772,7 +7001,7 @@ nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev, | |||
8772 | struct nlattr *pinfoattr; | 7001 | struct nlattr *pinfoattr; |
8773 | void *hdr; | 7002 | void *hdr; |
8774 | 7003 | ||
8775 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | 7004 | msg = nlmsg_new(NLMSG_GOODSIZE, gfp); |
8776 | if (!msg) | 7005 | if (!msg) |
8777 | return; | 7006 | return; |
8778 | 7007 | ||
@@ -8782,21 +7011,22 @@ nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev, | |||
8782 | return; | 7011 | return; |
8783 | } | 7012 | } |
8784 | 7013 | ||
8785 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 7014 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); |
8786 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex)) | 7015 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); |
8787 | goto nla_put_failure; | ||
8788 | 7016 | ||
8789 | pinfoattr = nla_nest_start(msg, NL80211_ATTR_CQM); | 7017 | pinfoattr = nla_nest_start(msg, NL80211_ATTR_CQM); |
8790 | if (!pinfoattr) | 7018 | if (!pinfoattr) |
8791 | goto nla_put_failure; | 7019 | goto nla_put_failure; |
8792 | 7020 | ||
8793 | if (nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT, | 7021 | NLA_PUT_U32(msg, NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT, |
8794 | rssi_event)) | 7022 | rssi_event); |
8795 | goto nla_put_failure; | ||
8796 | 7023 | ||
8797 | nla_nest_end(msg, pinfoattr); | 7024 | nla_nest_end(msg, pinfoattr); |
8798 | 7025 | ||
8799 | genlmsg_end(msg, hdr); | 7026 | if (genlmsg_end(msg, hdr) < 0) { |
7027 | nlmsg_free(msg); | ||
7028 | return; | ||
7029 | } | ||
8800 | 7030 | ||
8801 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | 7031 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
8802 | nl80211_mlme_mcgrp.id, gfp); | 7032 | nl80211_mlme_mcgrp.id, gfp); |
@@ -8815,7 +7045,7 @@ void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev, | |||
8815 | struct nlattr *rekey_attr; | 7045 | struct nlattr *rekey_attr; |
8816 | void *hdr; | 7046 | void *hdr; |
8817 | 7047 | ||
8818 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | 7048 | msg = nlmsg_new(NLMSG_GOODSIZE, gfp); |
8819 | if (!msg) | 7049 | if (!msg) |
8820 | return; | 7050 | return; |
8821 | 7051 | ||
@@ -8825,152 +7055,24 @@ void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev, | |||
8825 | return; | 7055 | return; |
8826 | } | 7056 | } |
8827 | 7057 | ||
8828 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 7058 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); |
8829 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || | 7059 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); |
8830 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid)) | 7060 | NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid); |
8831 | goto nla_put_failure; | ||
8832 | 7061 | ||
8833 | rekey_attr = nla_nest_start(msg, NL80211_ATTR_REKEY_DATA); | 7062 | rekey_attr = nla_nest_start(msg, NL80211_ATTR_REKEY_DATA); |
8834 | if (!rekey_attr) | 7063 | if (!rekey_attr) |
8835 | goto nla_put_failure; | 7064 | goto nla_put_failure; |
8836 | 7065 | ||
8837 | if (nla_put(msg, NL80211_REKEY_DATA_REPLAY_CTR, | 7066 | NLA_PUT(msg, NL80211_REKEY_DATA_REPLAY_CTR, |
8838 | NL80211_REPLAY_CTR_LEN, replay_ctr)) | 7067 | NL80211_REPLAY_CTR_LEN, replay_ctr); |
8839 | goto nla_put_failure; | ||
8840 | 7068 | ||
8841 | nla_nest_end(msg, rekey_attr); | 7069 | nla_nest_end(msg, rekey_attr); |
8842 | 7070 | ||
8843 | genlmsg_end(msg, hdr); | 7071 | if (genlmsg_end(msg, hdr) < 0) { |
8844 | |||
8845 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | ||
8846 | nl80211_mlme_mcgrp.id, gfp); | ||
8847 | return; | ||
8848 | |||
8849 | nla_put_failure: | ||
8850 | genlmsg_cancel(msg, hdr); | ||
8851 | nlmsg_free(msg); | ||
8852 | } | ||
8853 | |||
8854 | void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev, | ||
8855 | struct net_device *netdev, int index, | ||
8856 | const u8 *bssid, bool preauth, gfp_t gfp) | ||
8857 | { | ||
8858 | struct sk_buff *msg; | ||
8859 | struct nlattr *attr; | ||
8860 | void *hdr; | ||
8861 | |||
8862 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | ||
8863 | if (!msg) | ||
8864 | return; | ||
8865 | |||
8866 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PMKSA_CANDIDATE); | ||
8867 | if (!hdr) { | ||
8868 | nlmsg_free(msg); | 7072 | nlmsg_free(msg); |
8869 | return; | 7073 | return; |
8870 | } | 7074 | } |
8871 | 7075 | ||
8872 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | ||
8873 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex)) | ||
8874 | goto nla_put_failure; | ||
8875 | |||
8876 | attr = nla_nest_start(msg, NL80211_ATTR_PMKSA_CANDIDATE); | ||
8877 | if (!attr) | ||
8878 | goto nla_put_failure; | ||
8879 | |||
8880 | if (nla_put_u32(msg, NL80211_PMKSA_CANDIDATE_INDEX, index) || | ||
8881 | nla_put(msg, NL80211_PMKSA_CANDIDATE_BSSID, ETH_ALEN, bssid) || | ||
8882 | (preauth && | ||
8883 | nla_put_flag(msg, NL80211_PMKSA_CANDIDATE_PREAUTH))) | ||
8884 | goto nla_put_failure; | ||
8885 | |||
8886 | nla_nest_end(msg, attr); | ||
8887 | |||
8888 | genlmsg_end(msg, hdr); | ||
8889 | |||
8890 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | ||
8891 | nl80211_mlme_mcgrp.id, gfp); | ||
8892 | return; | ||
8893 | |||
8894 | nla_put_failure: | ||
8895 | genlmsg_cancel(msg, hdr); | ||
8896 | nlmsg_free(msg); | ||
8897 | } | ||
8898 | |||
8899 | void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, | ||
8900 | struct net_device *netdev, | ||
8901 | struct cfg80211_chan_def *chandef, gfp_t gfp) | ||
8902 | { | ||
8903 | struct sk_buff *msg; | ||
8904 | void *hdr; | ||
8905 | |||
8906 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | ||
8907 | if (!msg) | ||
8908 | return; | ||
8909 | |||
8910 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CH_SWITCH_NOTIFY); | ||
8911 | if (!hdr) { | ||
8912 | nlmsg_free(msg); | ||
8913 | return; | ||
8914 | } | ||
8915 | |||
8916 | if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex)) | ||
8917 | goto nla_put_failure; | ||
8918 | |||
8919 | if (nl80211_send_chandef(msg, chandef)) | ||
8920 | goto nla_put_failure; | ||
8921 | |||
8922 | genlmsg_end(msg, hdr); | ||
8923 | |||
8924 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | ||
8925 | nl80211_mlme_mcgrp.id, gfp); | ||
8926 | return; | ||
8927 | |||
8928 | nla_put_failure: | ||
8929 | genlmsg_cancel(msg, hdr); | ||
8930 | nlmsg_free(msg); | ||
8931 | } | ||
8932 | |||
8933 | void | ||
8934 | nl80211_send_cqm_txe_notify(struct cfg80211_registered_device *rdev, | ||
8935 | struct net_device *netdev, const u8 *peer, | ||
8936 | u32 num_packets, u32 rate, u32 intvl, gfp_t gfp) | ||
8937 | { | ||
8938 | struct sk_buff *msg; | ||
8939 | struct nlattr *pinfoattr; | ||
8940 | void *hdr; | ||
8941 | |||
8942 | msg = nlmsg_new(NLMSG_GOODSIZE, gfp); | ||
8943 | if (!msg) | ||
8944 | return; | ||
8945 | |||
8946 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NOTIFY_CQM); | ||
8947 | if (!hdr) { | ||
8948 | nlmsg_free(msg); | ||
8949 | return; | ||
8950 | } | ||
8951 | |||
8952 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | ||
8953 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || | ||
8954 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer)) | ||
8955 | goto nla_put_failure; | ||
8956 | |||
8957 | pinfoattr = nla_nest_start(msg, NL80211_ATTR_CQM); | ||
8958 | if (!pinfoattr) | ||
8959 | goto nla_put_failure; | ||
8960 | |||
8961 | if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_PKTS, num_packets)) | ||
8962 | goto nla_put_failure; | ||
8963 | |||
8964 | if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_RATE, rate)) | ||
8965 | goto nla_put_failure; | ||
8966 | |||
8967 | if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_INTVL, intvl)) | ||
8968 | goto nla_put_failure; | ||
8969 | |||
8970 | nla_nest_end(msg, pinfoattr); | ||
8971 | |||
8972 | genlmsg_end(msg, hdr); | ||
8973 | |||
8974 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | 7076 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
8975 | nl80211_mlme_mcgrp.id, gfp); | 7077 | nl80211_mlme_mcgrp.id, gfp); |
8976 | return; | 7078 | return; |
@@ -8989,7 +7091,7 @@ nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, | |||
8989 | struct nlattr *pinfoattr; | 7091 | struct nlattr *pinfoattr; |
8990 | void *hdr; | 7092 | void *hdr; |
8991 | 7093 | ||
8992 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | 7094 | msg = nlmsg_new(NLMSG_GOODSIZE, gfp); |
8993 | if (!msg) | 7095 | if (!msg) |
8994 | return; | 7096 | return; |
8995 | 7097 | ||
@@ -8999,62 +7101,19 @@ nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, | |||
8999 | return; | 7101 | return; |
9000 | } | 7102 | } |
9001 | 7103 | ||
9002 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 7104 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); |
9003 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || | 7105 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); |
9004 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer)) | 7106 | NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, peer); |
9005 | goto nla_put_failure; | ||
9006 | 7107 | ||
9007 | pinfoattr = nla_nest_start(msg, NL80211_ATTR_CQM); | 7108 | pinfoattr = nla_nest_start(msg, NL80211_ATTR_CQM); |
9008 | if (!pinfoattr) | 7109 | if (!pinfoattr) |
9009 | goto nla_put_failure; | 7110 | goto nla_put_failure; |
9010 | 7111 | ||
9011 | if (nla_put_u32(msg, NL80211_ATTR_CQM_PKT_LOSS_EVENT, num_packets)) | 7112 | NLA_PUT_U32(msg, NL80211_ATTR_CQM_PKT_LOSS_EVENT, num_packets); |
9012 | goto nla_put_failure; | ||
9013 | 7113 | ||
9014 | nla_nest_end(msg, pinfoattr); | 7114 | nla_nest_end(msg, pinfoattr); |
9015 | 7115 | ||
9016 | genlmsg_end(msg, hdr); | 7116 | if (genlmsg_end(msg, hdr) < 0) { |
9017 | |||
9018 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | ||
9019 | nl80211_mlme_mcgrp.id, gfp); | ||
9020 | return; | ||
9021 | |||
9022 | nla_put_failure: | ||
9023 | genlmsg_cancel(msg, hdr); | ||
9024 | nlmsg_free(msg); | ||
9025 | } | ||
9026 | |||
9027 | void cfg80211_probe_status(struct net_device *dev, const u8 *addr, | ||
9028 | u64 cookie, bool acked, gfp_t gfp) | ||
9029 | { | ||
9030 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
9031 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | ||
9032 | struct sk_buff *msg; | ||
9033 | void *hdr; | ||
9034 | int err; | ||
9035 | |||
9036 | trace_cfg80211_probe_status(dev, addr, cookie, acked); | ||
9037 | |||
9038 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | ||
9039 | |||
9040 | if (!msg) | ||
9041 | return; | ||
9042 | |||
9043 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PROBE_CLIENT); | ||
9044 | if (!hdr) { | ||
9045 | nlmsg_free(msg); | ||
9046 | return; | ||
9047 | } | ||
9048 | |||
9049 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | ||
9050 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || | ||
9051 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) || | ||
9052 | nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie) || | ||
9053 | (acked && nla_put_flag(msg, NL80211_ATTR_ACK))) | ||
9054 | goto nla_put_failure; | ||
9055 | |||
9056 | err = genlmsg_end(msg, hdr); | ||
9057 | if (err < 0) { | ||
9058 | nlmsg_free(msg); | 7117 | nlmsg_free(msg); |
9059 | return; | 7118 | return; |
9060 | } | 7119 | } |
@@ -9067,100 +7126,6 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr, | |||
9067 | genlmsg_cancel(msg, hdr); | 7126 | genlmsg_cancel(msg, hdr); |
9068 | nlmsg_free(msg); | 7127 | nlmsg_free(msg); |
9069 | } | 7128 | } |
9070 | EXPORT_SYMBOL(cfg80211_probe_status); | ||
9071 | |||
9072 | void cfg80211_report_obss_beacon(struct wiphy *wiphy, | ||
9073 | const u8 *frame, size_t len, | ||
9074 | int freq, int sig_dbm) | ||
9075 | { | ||
9076 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
9077 | struct sk_buff *msg; | ||
9078 | void *hdr; | ||
9079 | struct cfg80211_beacon_registration *reg; | ||
9080 | |||
9081 | trace_cfg80211_report_obss_beacon(wiphy, frame, len, freq, sig_dbm); | ||
9082 | |||
9083 | spin_lock_bh(&rdev->beacon_registrations_lock); | ||
9084 | list_for_each_entry(reg, &rdev->beacon_registrations, list) { | ||
9085 | msg = nlmsg_new(len + 100, GFP_ATOMIC); | ||
9086 | if (!msg) { | ||
9087 | spin_unlock_bh(&rdev->beacon_registrations_lock); | ||
9088 | return; | ||
9089 | } | ||
9090 | |||
9091 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME); | ||
9092 | if (!hdr) | ||
9093 | goto nla_put_failure; | ||
9094 | |||
9095 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | ||
9096 | (freq && | ||
9097 | nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq)) || | ||
9098 | (sig_dbm && | ||
9099 | nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) || | ||
9100 | nla_put(msg, NL80211_ATTR_FRAME, len, frame)) | ||
9101 | goto nla_put_failure; | ||
9102 | |||
9103 | genlmsg_end(msg, hdr); | ||
9104 | |||
9105 | genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, reg->nlportid); | ||
9106 | } | ||
9107 | spin_unlock_bh(&rdev->beacon_registrations_lock); | ||
9108 | return; | ||
9109 | |||
9110 | nla_put_failure: | ||
9111 | spin_unlock_bh(&rdev->beacon_registrations_lock); | ||
9112 | if (hdr) | ||
9113 | genlmsg_cancel(msg, hdr); | ||
9114 | nlmsg_free(msg); | ||
9115 | } | ||
9116 | EXPORT_SYMBOL(cfg80211_report_obss_beacon); | ||
9117 | |||
9118 | void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer, | ||
9119 | enum nl80211_tdls_operation oper, | ||
9120 | u16 reason_code, gfp_t gfp) | ||
9121 | { | ||
9122 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
9123 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | ||
9124 | struct sk_buff *msg; | ||
9125 | void *hdr; | ||
9126 | int err; | ||
9127 | |||
9128 | trace_cfg80211_tdls_oper_request(wdev->wiphy, dev, peer, oper, | ||
9129 | reason_code); | ||
9130 | |||
9131 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | ||
9132 | if (!msg) | ||
9133 | return; | ||
9134 | |||
9135 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_TDLS_OPER); | ||
9136 | if (!hdr) { | ||
9137 | nlmsg_free(msg); | ||
9138 | return; | ||
9139 | } | ||
9140 | |||
9141 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | ||
9142 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || | ||
9143 | nla_put_u8(msg, NL80211_ATTR_TDLS_OPERATION, oper) || | ||
9144 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer) || | ||
9145 | (reason_code > 0 && | ||
9146 | nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code))) | ||
9147 | goto nla_put_failure; | ||
9148 | |||
9149 | err = genlmsg_end(msg, hdr); | ||
9150 | if (err < 0) { | ||
9151 | nlmsg_free(msg); | ||
9152 | return; | ||
9153 | } | ||
9154 | |||
9155 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | ||
9156 | nl80211_mlme_mcgrp.id, gfp); | ||
9157 | return; | ||
9158 | |||
9159 | nla_put_failure: | ||
9160 | genlmsg_cancel(msg, hdr); | ||
9161 | nlmsg_free(msg); | ||
9162 | } | ||
9163 | EXPORT_SYMBOL(cfg80211_tdls_oper_request); | ||
9164 | 7129 | ||
9165 | static int nl80211_netlink_notify(struct notifier_block * nb, | 7130 | static int nl80211_netlink_notify(struct notifier_block * nb, |
9166 | unsigned long state, | 7131 | unsigned long state, |
@@ -9169,28 +7134,15 @@ static int nl80211_netlink_notify(struct notifier_block * nb, | |||
9169 | struct netlink_notify *notify = _notify; | 7134 | struct netlink_notify *notify = _notify; |
9170 | struct cfg80211_registered_device *rdev; | 7135 | struct cfg80211_registered_device *rdev; |
9171 | struct wireless_dev *wdev; | 7136 | struct wireless_dev *wdev; |
9172 | struct cfg80211_beacon_registration *reg, *tmp; | ||
9173 | 7137 | ||
9174 | if (state != NETLINK_URELEASE) | 7138 | if (state != NETLINK_URELEASE) |
9175 | return NOTIFY_DONE; | 7139 | return NOTIFY_DONE; |
9176 | 7140 | ||
9177 | rcu_read_lock(); | 7141 | rcu_read_lock(); |
9178 | 7142 | ||
9179 | list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) { | 7143 | list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) |
9180 | list_for_each_entry_rcu(wdev, &rdev->wdev_list, list) | 7144 | list_for_each_entry_rcu(wdev, &rdev->netdev_list, list) |
9181 | cfg80211_mlme_unregister_socket(wdev, notify->portid); | 7145 | cfg80211_mlme_unregister_socket(wdev, notify->pid); |
9182 | |||
9183 | spin_lock_bh(&rdev->beacon_registrations_lock); | ||
9184 | list_for_each_entry_safe(reg, tmp, &rdev->beacon_registrations, | ||
9185 | list) { | ||
9186 | if (reg->nlportid == notify->portid) { | ||
9187 | list_del(®->list); | ||
9188 | kfree(reg); | ||
9189 | break; | ||
9190 | } | ||
9191 | } | ||
9192 | spin_unlock_bh(&rdev->beacon_registrations_lock); | ||
9193 | } | ||
9194 | 7146 | ||
9195 | rcu_read_unlock(); | 7147 | rcu_read_unlock(); |
9196 | 7148 | ||