]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - net/mac80211/cfg.c
mac80211: fix sta-info pinning
[mirror_ubuntu-bionic-kernel.git] / net / mac80211 / cfg.c
CommitLineData
f0706e82
JB
1/*
2 * mac80211 configuration hooks for cfg80211
3 *
62da92fb 4 * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net>
f0706e82
JB
5 *
6 * This file is GPLv2 as found in COPYING.
7 */
8
e8cbb4cb 9#include <linux/ieee80211.h>
f0706e82
JB
10#include <linux/nl80211.h>
11#include <linux/rtnetlink.h>
881d966b 12#include <net/net_namespace.h>
5dfdaf58 13#include <linux/rcupdate.h>
f0706e82
JB
14#include <net/cfg80211.h>
15#include "ieee80211_i.h"
e0eb6859 16#include "cfg.h"
4fd6931e 17#include "ieee80211_rate.h"
c5dd9c2b 18#include "mesh.h"
c5dd9c2b 19
42613db7
JB
20static enum ieee80211_if_types
21nl80211_type_to_mac80211_type(enum nl80211_iftype type)
22{
23 switch (type) {
24 case NL80211_IFTYPE_UNSPECIFIED:
25 return IEEE80211_IF_TYPE_STA;
26 case NL80211_IFTYPE_ADHOC:
27 return IEEE80211_IF_TYPE_IBSS;
28 case NL80211_IFTYPE_STATION:
29 return IEEE80211_IF_TYPE_STA;
30 case NL80211_IFTYPE_MONITOR:
31 return IEEE80211_IF_TYPE_MNTR;
c5dd9c2b
LCC
32#ifdef CONFIG_MAC80211_MESH
33 case NL80211_IFTYPE_MESH_POINT:
34 return IEEE80211_IF_TYPE_MESH_POINT;
35#endif
42613db7
JB
36 default:
37 return IEEE80211_IF_TYPE_INVALID;
38 }
39}
40
f0706e82 41static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
2ec600d6
LCC
42 enum nl80211_iftype type, u32 *flags,
43 struct vif_params *params)
f0706e82
JB
44{
45 struct ieee80211_local *local = wiphy_priv(wiphy);
42613db7 46 enum ieee80211_if_types itype;
8cc9a739
MW
47 struct net_device *dev;
48 struct ieee80211_sub_if_data *sdata;
49 int err;
f0706e82
JB
50
51 if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
52 return -ENODEV;
53
42613db7
JB
54 itype = nl80211_type_to_mac80211_type(type);
55 if (itype == IEEE80211_IF_TYPE_INVALID)
f0706e82 56 return -EINVAL;
f0706e82 57
ee385855 58 err = ieee80211_if_add(local->mdev, name, &dev, itype, params);
8cc9a739
MW
59 if (err || itype != IEEE80211_IF_TYPE_MNTR || !flags)
60 return err;
61
62 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
63 sdata->u.mntr_flags = *flags;
64 return 0;
f0706e82
JB
65}
66
67static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex)
68{
69 struct ieee80211_local *local = wiphy_priv(wiphy);
70 struct net_device *dev;
71 char *name;
72
73 if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
74 return -ENODEV;
75
42613db7
JB
76 /* we're under RTNL */
77 dev = __dev_get_by_index(&init_net, ifindex);
f0706e82
JB
78 if (!dev)
79 return 0;
80
81 name = dev->name;
f0706e82
JB
82
83 return ieee80211_if_remove(local->mdev, name, -1);
84}
85
42613db7 86static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
2ec600d6
LCC
87 enum nl80211_iftype type, u32 *flags,
88 struct vif_params *params)
42613db7
JB
89{
90 struct ieee80211_local *local = wiphy_priv(wiphy);
91 struct net_device *dev;
92 enum ieee80211_if_types itype;
93 struct ieee80211_sub_if_data *sdata;
94
95 if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
96 return -ENODEV;
97
98 /* we're under RTNL */
99 dev = __dev_get_by_index(&init_net, ifindex);
100 if (!dev)
101 return -ENODEV;
102
103 if (netif_running(dev))
104 return -EBUSY;
105
106 itype = nl80211_type_to_mac80211_type(type);
107 if (itype == IEEE80211_IF_TYPE_INVALID)
108 return -EINVAL;
109
110 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
111
51fb61e7 112 if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
42613db7
JB
113 return -EOPNOTSUPP;
114
115 ieee80211_if_reinit(dev);
116 ieee80211_if_set_type(dev, itype);
117
902acc78
JB
118 if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len)
119 ieee80211_if_sta_set_mesh_id(&sdata->u.sta,
120 params->mesh_id_len,
121 params->mesh_id);
c5dd9c2b 122
8cc9a739
MW
123 if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR || !flags)
124 return 0;
125
126 sdata->u.mntr_flags = *flags;
42613db7
JB
127 return 0;
128}
129
e8cbb4cb
JB
130static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
131 u8 key_idx, u8 *mac_addr,
132 struct key_params *params)
133{
134 struct ieee80211_sub_if_data *sdata;
135 struct sta_info *sta = NULL;
136 enum ieee80211_key_alg alg;
db4d1169 137 struct ieee80211_key *key;
e8cbb4cb
JB
138
139 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
140
141 switch (params->cipher) {
142 case WLAN_CIPHER_SUITE_WEP40:
143 case WLAN_CIPHER_SUITE_WEP104:
144 alg = ALG_WEP;
145 break;
146 case WLAN_CIPHER_SUITE_TKIP:
147 alg = ALG_TKIP;
148 break;
149 case WLAN_CIPHER_SUITE_CCMP:
150 alg = ALG_CCMP;
151 break;
152 default:
153 return -EINVAL;
154 }
155
db4d1169
JB
156 key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key);
157 if (!key)
158 return -ENOMEM;
159
e8cbb4cb
JB
160 if (mac_addr) {
161 sta = sta_info_get(sdata->local, mac_addr);
db4d1169
JB
162 if (!sta) {
163 ieee80211_key_free(key);
e8cbb4cb 164 return -ENOENT;
db4d1169 165 }
e8cbb4cb
JB
166 }
167
db4d1169
JB
168 ieee80211_key_link(key, sdata, sta);
169
d0709a65 170 return 0;
e8cbb4cb
JB
171}
172
173static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
174 u8 key_idx, u8 *mac_addr)
175{
176 struct ieee80211_sub_if_data *sdata;
177 struct sta_info *sta;
178 int ret;
179
180 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
181
182 if (mac_addr) {
183 sta = sta_info_get(sdata->local, mac_addr);
184 if (!sta)
185 return -ENOENT;
186
187 ret = 0;
db4d1169 188 if (sta->key) {
d0709a65 189 ieee80211_key_free(sta->key);
db4d1169
JB
190 WARN_ON(sta->key);
191 } else
e8cbb4cb
JB
192 ret = -ENOENT;
193
e8cbb4cb
JB
194 return ret;
195 }
196
197 if (!sdata->keys[key_idx])
198 return -ENOENT;
199
d0709a65 200 ieee80211_key_free(sdata->keys[key_idx]);
db4d1169 201 WARN_ON(sdata->keys[key_idx]);
e8cbb4cb
JB
202
203 return 0;
204}
205
62da92fb
JB
206static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
207 u8 key_idx, u8 *mac_addr, void *cookie,
208 void (*callback)(void *cookie,
209 struct key_params *params))
210{
211 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
212 struct sta_info *sta = NULL;
213 u8 seq[6] = {0};
214 struct key_params params;
215 struct ieee80211_key *key;
216 u32 iv32;
217 u16 iv16;
218 int err = -ENOENT;
219
220 if (mac_addr) {
221 sta = sta_info_get(sdata->local, mac_addr);
222 if (!sta)
223 goto out;
224
225 key = sta->key;
226 } else
227 key = sdata->keys[key_idx];
228
229 if (!key)
230 goto out;
231
232 memset(&params, 0, sizeof(params));
233
234 switch (key->conf.alg) {
235 case ALG_TKIP:
236 params.cipher = WLAN_CIPHER_SUITE_TKIP;
237
238 iv32 = key->u.tkip.iv32;
239 iv16 = key->u.tkip.iv16;
240
241 if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE &&
242 sdata->local->ops->get_tkip_seq)
243 sdata->local->ops->get_tkip_seq(
244 local_to_hw(sdata->local),
245 key->conf.hw_key_idx,
246 &iv32, &iv16);
247
248 seq[0] = iv16 & 0xff;
249 seq[1] = (iv16 >> 8) & 0xff;
250 seq[2] = iv32 & 0xff;
251 seq[3] = (iv32 >> 8) & 0xff;
252 seq[4] = (iv32 >> 16) & 0xff;
253 seq[5] = (iv32 >> 24) & 0xff;
254 params.seq = seq;
255 params.seq_len = 6;
256 break;
257 case ALG_CCMP:
258 params.cipher = WLAN_CIPHER_SUITE_CCMP;
259 seq[0] = key->u.ccmp.tx_pn[5];
260 seq[1] = key->u.ccmp.tx_pn[4];
261 seq[2] = key->u.ccmp.tx_pn[3];
262 seq[3] = key->u.ccmp.tx_pn[2];
263 seq[4] = key->u.ccmp.tx_pn[1];
264 seq[5] = key->u.ccmp.tx_pn[0];
265 params.seq = seq;
266 params.seq_len = 6;
267 break;
268 case ALG_WEP:
269 if (key->conf.keylen == 5)
270 params.cipher = WLAN_CIPHER_SUITE_WEP40;
271 else
272 params.cipher = WLAN_CIPHER_SUITE_WEP104;
273 break;
274 }
275
276 params.key = key->conf.key;
277 params.key_len = key->conf.keylen;
278
279 callback(cookie, &params);
280 err = 0;
281
282 out:
62da92fb
JB
283 return err;
284}
285
e8cbb4cb
JB
286static int ieee80211_config_default_key(struct wiphy *wiphy,
287 struct net_device *dev,
288 u8 key_idx)
289{
290 struct ieee80211_sub_if_data *sdata;
291
292 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
293 ieee80211_set_default_key(sdata, key_idx);
294
295 return 0;
296}
297
c5dd9c2b
LCC
298static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
299{
d0709a65 300 struct ieee80211_sub_if_data *sdata = sta->sdata;
c5dd9c2b
LCC
301
302 sinfo->filled = STATION_INFO_INACTIVE_TIME |
303 STATION_INFO_RX_BYTES |
304 STATION_INFO_TX_BYTES;
305
306 sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
307 sinfo->rx_bytes = sta->rx_bytes;
308 sinfo->tx_bytes = sta->tx_bytes;
309
902acc78 310 if (ieee80211_vif_is_mesh(&sdata->vif)) {
c5dd9c2b 311#ifdef CONFIG_MAC80211_MESH
c5dd9c2b
LCC
312 sinfo->filled |= STATION_INFO_LLID |
313 STATION_INFO_PLID |
314 STATION_INFO_PLINK_STATE;
315
316 sinfo->llid = le16_to_cpu(sta->llid);
317 sinfo->plid = le16_to_cpu(sta->plid);
318 sinfo->plink_state = sta->plink_state;
c5dd9c2b 319#endif
902acc78 320 }
c5dd9c2b
LCC
321}
322
323
324static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
325 int idx, u8 *mac, struct station_info *sinfo)
326{
327 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
328 struct sta_info *sta;
d0709a65
JB
329 int ret = -ENOENT;
330
331 rcu_read_lock();
c5dd9c2b
LCC
332
333 sta = sta_info_get_by_idx(local, idx, dev);
d0709a65
JB
334 if (sta) {
335 ret = 0;
336 memcpy(mac, sta->addr, ETH_ALEN);
337 sta_set_sinfo(sta, sinfo);
338 }
c5dd9c2b 339
d0709a65 340 rcu_read_unlock();
c5dd9c2b 341
d0709a65 342 return ret;
c5dd9c2b
LCC
343}
344
7bbdd2d9 345static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
2ec600d6 346 u8 *mac, struct station_info *sinfo)
7bbdd2d9
JB
347{
348 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
349 struct sta_info *sta;
d0709a65 350 int ret = -ENOENT;
7bbdd2d9 351
d0709a65 352 rcu_read_lock();
7bbdd2d9
JB
353
354 /* XXX: verify sta->dev == dev */
7bbdd2d9 355
d0709a65
JB
356 sta = sta_info_get(local, mac);
357 if (sta) {
358 ret = 0;
359 sta_set_sinfo(sta, sinfo);
360 }
361
362 rcu_read_unlock();
363
364 return ret;
7bbdd2d9
JB
365}
366
5dfdaf58
JB
367/*
368 * This handles both adding a beacon and setting new beacon info
369 */
370static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata,
371 struct beacon_parameters *params)
372{
373 struct beacon_data *new, *old;
374 int new_head_len, new_tail_len;
375 int size;
376 int err = -EINVAL;
377
378 old = sdata->u.ap.beacon;
379
380 /* head must not be zero-length */
381 if (params->head && !params->head_len)
382 return -EINVAL;
383
384 /*
385 * This is a kludge. beacon interval should really be part
386 * of the beacon information.
387 */
388 if (params->interval) {
389 sdata->local->hw.conf.beacon_int = params->interval;
390 if (ieee80211_hw_config(sdata->local))
391 return -EINVAL;
392 /*
393 * We updated some parameter so if below bails out
394 * it's not an error.
395 */
396 err = 0;
397 }
398
399 /* Need to have a beacon head if we don't have one yet */
400 if (!params->head && !old)
401 return err;
402
403 /* sorry, no way to start beaconing without dtim period */
404 if (!params->dtim_period && !old)
405 return err;
406
407 /* new or old head? */
408 if (params->head)
409 new_head_len = params->head_len;
410 else
411 new_head_len = old->head_len;
412
413 /* new or old tail? */
414 if (params->tail || !old)
415 /* params->tail_len will be zero for !params->tail */
416 new_tail_len = params->tail_len;
417 else
418 new_tail_len = old->tail_len;
419
420 size = sizeof(*new) + new_head_len + new_tail_len;
421
422 new = kzalloc(size, GFP_KERNEL);
423 if (!new)
424 return -ENOMEM;
425
426 /* start filling the new info now */
427
428 /* new or old dtim period? */
429 if (params->dtim_period)
430 new->dtim_period = params->dtim_period;
431 else
432 new->dtim_period = old->dtim_period;
433
434 /*
435 * pointers go into the block we allocated,
436 * memory is | beacon_data | head | tail |
437 */
438 new->head = ((u8 *) new) + sizeof(*new);
439 new->tail = new->head + new_head_len;
440 new->head_len = new_head_len;
441 new->tail_len = new_tail_len;
442
443 /* copy in head */
444 if (params->head)
445 memcpy(new->head, params->head, new_head_len);
446 else
447 memcpy(new->head, old->head, new_head_len);
448
449 /* copy in optional tail */
450 if (params->tail)
451 memcpy(new->tail, params->tail, new_tail_len);
452 else
453 if (old)
454 memcpy(new->tail, old->tail, new_tail_len);
455
456 rcu_assign_pointer(sdata->u.ap.beacon, new);
457
458 synchronize_rcu();
459
460 kfree(old);
461
462 return ieee80211_if_config_beacon(sdata->dev);
463}
464
465static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev,
466 struct beacon_parameters *params)
467{
468 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
469 struct beacon_data *old;
470
471 if (sdata->vif.type != IEEE80211_IF_TYPE_AP)
472 return -EINVAL;
473
474 old = sdata->u.ap.beacon;
475
476 if (old)
477 return -EALREADY;
478
479 return ieee80211_config_beacon(sdata, params);
480}
481
482static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
483 struct beacon_parameters *params)
484{
485 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
486 struct beacon_data *old;
487
488 if (sdata->vif.type != IEEE80211_IF_TYPE_AP)
489 return -EINVAL;
490
491 old = sdata->u.ap.beacon;
492
493 if (!old)
494 return -ENOENT;
495
496 return ieee80211_config_beacon(sdata, params);
497}
498
499static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)
500{
501 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
502 struct beacon_data *old;
503
504 if (sdata->vif.type != IEEE80211_IF_TYPE_AP)
505 return -EINVAL;
506
507 old = sdata->u.ap.beacon;
508
509 if (!old)
510 return -ENOENT;
511
512 rcu_assign_pointer(sdata->u.ap.beacon, NULL);
513 synchronize_rcu();
514 kfree(old);
515
516 return ieee80211_if_config_beacon(dev);
517}
518
4fd6931e
JB
519/* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */
520struct iapp_layer2_update {
521 u8 da[ETH_ALEN]; /* broadcast */
522 u8 sa[ETH_ALEN]; /* STA addr */
523 __be16 len; /* 6 */
524 u8 dsap; /* 0 */
525 u8 ssap; /* 0 */
526 u8 control;
527 u8 xid_info[3];
528} __attribute__ ((packed));
529
530static void ieee80211_send_layer2_update(struct sta_info *sta)
531{
532 struct iapp_layer2_update *msg;
533 struct sk_buff *skb;
534
535 /* Send Level 2 Update Frame to update forwarding tables in layer 2
536 * bridge devices */
537
538 skb = dev_alloc_skb(sizeof(*msg));
539 if (!skb)
540 return;
541 msg = (struct iapp_layer2_update *)skb_put(skb, sizeof(*msg));
542
543 /* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID)
544 * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */
545
546 memset(msg->da, 0xff, ETH_ALEN);
547 memcpy(msg->sa, sta->addr, ETH_ALEN);
548 msg->len = htons(6);
549 msg->dsap = 0;
550 msg->ssap = 0x01; /* NULL LSAP, CR Bit: Response */
551 msg->control = 0xaf; /* XID response lsb.1111F101.
552 * F=0 (no poll command; unsolicited frame) */
553 msg->xid_info[0] = 0x81; /* XID format identifier */
554 msg->xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */
555 msg->xid_info[2] = 0; /* XID sender's receive window size (RW) */
556
d0709a65
JB
557 skb->dev = sta->sdata->dev;
558 skb->protocol = eth_type_trans(skb, sta->sdata->dev);
4fd6931e
JB
559 memset(skb->cb, 0, sizeof(skb->cb));
560 netif_rx(skb);
561}
562
563static void sta_apply_parameters(struct ieee80211_local *local,
564 struct sta_info *sta,
565 struct station_parameters *params)
566{
567 u32 rates;
568 int i, j;
8318d78a 569 struct ieee80211_supported_band *sband;
d0709a65 570 struct ieee80211_sub_if_data *sdata = sta->sdata;
4fd6931e 571
73651ee6
JB
572 /*
573 * FIXME: updating the flags is racy when this function is
574 * called from ieee80211_change_station(), this will
575 * be resolved in a future patch.
576 */
577
4fd6931e
JB
578 if (params->station_flags & STATION_FLAG_CHANGED) {
579 sta->flags &= ~WLAN_STA_AUTHORIZED;
580 if (params->station_flags & STATION_FLAG_AUTHORIZED)
581 sta->flags |= WLAN_STA_AUTHORIZED;
582
583 sta->flags &= ~WLAN_STA_SHORT_PREAMBLE;
584 if (params->station_flags & STATION_FLAG_SHORT_PREAMBLE)
585 sta->flags |= WLAN_STA_SHORT_PREAMBLE;
586
587 sta->flags &= ~WLAN_STA_WME;
588 if (params->station_flags & STATION_FLAG_WME)
589 sta->flags |= WLAN_STA_WME;
590 }
591
73651ee6
JB
592 /*
593 * FIXME: updating the following information is racy when this
594 * function is called from ieee80211_change_station().
595 * However, all this information should be static so
596 * maybe we should just reject attemps to change it.
597 */
598
4fd6931e
JB
599 if (params->aid) {
600 sta->aid = params->aid;
601 if (sta->aid > IEEE80211_MAX_AID)
602 sta->aid = 0; /* XXX: should this be an error? */
603 }
604
605 if (params->listen_interval >= 0)
606 sta->listen_interval = params->listen_interval;
607
608 if (params->supported_rates) {
609 rates = 0;
8318d78a
JB
610 sband = local->hw.wiphy->bands[local->oper_channel->band];
611
4fd6931e
JB
612 for (i = 0; i < params->supported_rates_len; i++) {
613 int rate = (params->supported_rates[i] & 0x7f) * 5;
8318d78a
JB
614 for (j = 0; j < sband->n_bitrates; j++) {
615 if (sband->bitrates[j].bitrate == rate)
4fd6931e
JB
616 rates |= BIT(j);
617 }
618 }
8318d78a 619 sta->supp_rates[local->oper_channel->band] = rates;
4fd6931e 620 }
c5dd9c2b 621
902acc78 622 if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) {
c5dd9c2b
LCC
623 switch (params->plink_action) {
624 case PLINK_ACTION_OPEN:
625 mesh_plink_open(sta);
626 break;
627 case PLINK_ACTION_BLOCK:
628 mesh_plink_block(sta);
629 break;
630 }
902acc78 631 }
4fd6931e
JB
632}
633
634static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
635 u8 *mac, struct station_parameters *params)
636{
637 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
638 struct sta_info *sta;
639 struct ieee80211_sub_if_data *sdata;
73651ee6 640 int err;
4fd6931e
JB
641
642 /* Prevent a race with changing the rate control algorithm */
643 if (!netif_running(dev))
644 return -ENETDOWN;
645
4fd6931e
JB
646 if (params->vlan) {
647 sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
648
649 if (sdata->vif.type != IEEE80211_IF_TYPE_VLAN ||
650 sdata->vif.type != IEEE80211_IF_TYPE_AP)
651 return -EINVAL;
652 } else
653 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
654
03e4497e
JB
655 if (compare_ether_addr(mac, dev->dev_addr) == 0)
656 return -EINVAL;
657
658 if (is_multicast_ether_addr(mac))
659 return -EINVAL;
660
661 sta = sta_info_alloc(sdata, mac, GFP_KERNEL);
73651ee6
JB
662 if (!sta)
663 return -ENOMEM;
4fd6931e
JB
664
665 sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC;
666
667 sta_apply_parameters(local, sta, params);
668
669 rate_control_rate_init(sta, local);
670
73651ee6
JB
671 rcu_read_lock();
672
673 err = sta_info_insert(sta);
674 if (err) {
93e5deb1 675 /* STA has been freed */
73651ee6
JB
676 rcu_read_unlock();
677 return err;
678 }
679
680 if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN ||
681 sdata->vif.type == IEEE80211_IF_TYPE_AP)
682 ieee80211_send_layer2_update(sta);
683
684 rcu_read_unlock();
685
4fd6931e
JB
686 return 0;
687}
688
689static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev,
690 u8 *mac)
691{
d0709a65
JB
692 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
693 struct ieee80211_local *local = sdata->local;
4fd6931e
JB
694 struct sta_info *sta;
695
696 if (mac) {
697 /* XXX: get sta belonging to dev */
698 sta = sta_info_get(local, mac);
699 if (!sta)
700 return -ENOENT;
701
d0709a65 702 sta_info_unlink(&sta);
4f6fab47 703 sta_info_destroy(sta);
4fd6931e 704 } else
d0709a65 705 sta_info_flush(local, sdata);
4fd6931e
JB
706
707 return 0;
708}
709
710static int ieee80211_change_station(struct wiphy *wiphy,
711 struct net_device *dev,
712 u8 *mac,
713 struct station_parameters *params)
714{
715 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
716 struct sta_info *sta;
717 struct ieee80211_sub_if_data *vlansdata;
718
719 /* XXX: get sta belonging to dev */
720 sta = sta_info_get(local, mac);
721 if (!sta)
722 return -ENOENT;
723
d0709a65 724 if (params->vlan && params->vlan != sta->sdata->dev) {
4fd6931e
JB
725 vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
726
727 if (vlansdata->vif.type != IEEE80211_IF_TYPE_VLAN ||
728 vlansdata->vif.type != IEEE80211_IF_TYPE_AP)
729 return -EINVAL;
730
d0709a65 731 sta->sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
4fd6931e
JB
732 ieee80211_send_layer2_update(sta);
733 }
734
735 sta_apply_parameters(local, sta, params);
736
4fd6931e
JB
737 return 0;
738}
739
c5dd9c2b
LCC
740#ifdef CONFIG_MAC80211_MESH
741static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
742 u8 *dst, u8 *next_hop)
743{
744 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
745 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
746 struct mesh_path *mpath;
747 struct sta_info *sta;
748 int err;
749
750 if (!netif_running(dev))
751 return -ENETDOWN;
752
753 if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
754 return -ENOTSUPP;
755
d0709a65 756 rcu_read_lock();
c5dd9c2b 757 sta = sta_info_get(local, next_hop);
d0709a65
JB
758 if (!sta) {
759 rcu_read_unlock();
c5dd9c2b 760 return -ENOENT;
d0709a65 761 }
c5dd9c2b
LCC
762
763 err = mesh_path_add(dst, dev);
d0709a65
JB
764 if (err) {
765 rcu_read_unlock();
c5dd9c2b 766 return err;
d0709a65 767 }
c5dd9c2b 768
c5dd9c2b
LCC
769 mpath = mesh_path_lookup(dst, dev);
770 if (!mpath) {
771 rcu_read_unlock();
c5dd9c2b
LCC
772 return -ENXIO;
773 }
774 mesh_path_fix_nexthop(mpath, sta);
d0709a65 775
c5dd9c2b
LCC
776 rcu_read_unlock();
777 return 0;
778}
779
780static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev,
781 u8 *dst)
782{
783 if (dst)
cfa22c71 784 return mesh_path_del(dst, dev);
c5dd9c2b
LCC
785
786 mesh_path_flush(dev);
787 return 0;
788}
789
790static int ieee80211_change_mpath(struct wiphy *wiphy,
791 struct net_device *dev,
792 u8 *dst, u8 *next_hop)
793{
794 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
795 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
796 struct mesh_path *mpath;
797 struct sta_info *sta;
798
799 if (!netif_running(dev))
800 return -ENETDOWN;
801
802 if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
803 return -ENOTSUPP;
804
d0709a65
JB
805 rcu_read_lock();
806
c5dd9c2b 807 sta = sta_info_get(local, next_hop);
d0709a65
JB
808 if (!sta) {
809 rcu_read_unlock();
c5dd9c2b 810 return -ENOENT;
d0709a65 811 }
c5dd9c2b 812
c5dd9c2b
LCC
813 mpath = mesh_path_lookup(dst, dev);
814 if (!mpath) {
815 rcu_read_unlock();
c5dd9c2b
LCC
816 return -ENOENT;
817 }
818
819 mesh_path_fix_nexthop(mpath, sta);
d0709a65 820
c5dd9c2b
LCC
821 rcu_read_unlock();
822 return 0;
823}
824
825static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
826 struct mpath_info *pinfo)
827{
828 if (mpath->next_hop)
829 memcpy(next_hop, mpath->next_hop->addr, ETH_ALEN);
830 else
831 memset(next_hop, 0, ETH_ALEN);
832
833 pinfo->filled = MPATH_INFO_FRAME_QLEN |
834 MPATH_INFO_DSN |
835 MPATH_INFO_METRIC |
836 MPATH_INFO_EXPTIME |
837 MPATH_INFO_DISCOVERY_TIMEOUT |
838 MPATH_INFO_DISCOVERY_RETRIES |
839 MPATH_INFO_FLAGS;
840
841 pinfo->frame_qlen = mpath->frame_queue.qlen;
842 pinfo->dsn = mpath->dsn;
843 pinfo->metric = mpath->metric;
844 if (time_before(jiffies, mpath->exp_time))
845 pinfo->exptime = jiffies_to_msecs(mpath->exp_time - jiffies);
846 pinfo->discovery_timeout =
847 jiffies_to_msecs(mpath->discovery_timeout);
848 pinfo->discovery_retries = mpath->discovery_retries;
849 pinfo->flags = 0;
850 if (mpath->flags & MESH_PATH_ACTIVE)
851 pinfo->flags |= NL80211_MPATH_FLAG_ACTIVE;
852 if (mpath->flags & MESH_PATH_RESOLVING)
853 pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING;
854 if (mpath->flags & MESH_PATH_DSN_VALID)
855 pinfo->flags |= NL80211_MPATH_FLAG_DSN_VALID;
856 if (mpath->flags & MESH_PATH_FIXED)
857 pinfo->flags |= NL80211_MPATH_FLAG_FIXED;
858 if (mpath->flags & MESH_PATH_RESOLVING)
859 pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING;
860
861 pinfo->flags = mpath->flags;
862}
863
864static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev,
865 u8 *dst, u8 *next_hop, struct mpath_info *pinfo)
866
867{
868 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
869 struct mesh_path *mpath;
870
871 if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
872 return -ENOTSUPP;
873
874 rcu_read_lock();
875 mpath = mesh_path_lookup(dst, dev);
876 if (!mpath) {
877 rcu_read_unlock();
878 return -ENOENT;
879 }
880 memcpy(dst, mpath->dst, ETH_ALEN);
881 mpath_set_pinfo(mpath, next_hop, pinfo);
882 rcu_read_unlock();
883 return 0;
884}
885
886static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev,
887 int idx, u8 *dst, u8 *next_hop,
888 struct mpath_info *pinfo)
889{
890 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
891 struct mesh_path *mpath;
892
893 if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
894 return -ENOTSUPP;
895
896 rcu_read_lock();
897 mpath = mesh_path_lookup_by_idx(idx, dev);
898 if (!mpath) {
899 rcu_read_unlock();
900 return -ENOENT;
901 }
902 memcpy(dst, mpath->dst, ETH_ALEN);
903 mpath_set_pinfo(mpath, next_hop, pinfo);
904 rcu_read_unlock();
905 return 0;
906}
907#endif
908
f0706e82
JB
909struct cfg80211_ops mac80211_config_ops = {
910 .add_virtual_intf = ieee80211_add_iface,
911 .del_virtual_intf = ieee80211_del_iface,
42613db7 912 .change_virtual_intf = ieee80211_change_iface,
e8cbb4cb
JB
913 .add_key = ieee80211_add_key,
914 .del_key = ieee80211_del_key,
62da92fb 915 .get_key = ieee80211_get_key,
e8cbb4cb 916 .set_default_key = ieee80211_config_default_key,
5dfdaf58
JB
917 .add_beacon = ieee80211_add_beacon,
918 .set_beacon = ieee80211_set_beacon,
919 .del_beacon = ieee80211_del_beacon,
4fd6931e
JB
920 .add_station = ieee80211_add_station,
921 .del_station = ieee80211_del_station,
922 .change_station = ieee80211_change_station,
7bbdd2d9 923 .get_station = ieee80211_get_station,
c5dd9c2b
LCC
924 .dump_station = ieee80211_dump_station,
925#ifdef CONFIG_MAC80211_MESH
926 .add_mpath = ieee80211_add_mpath,
927 .del_mpath = ieee80211_del_mpath,
928 .change_mpath = ieee80211_change_mpath,
929 .get_mpath = ieee80211_get_mpath,
930 .dump_mpath = ieee80211_dump_mpath,
931#endif
f0706e82 932};