cfg.c 23.9 KB
Newer Older
1
2
3
/*
 * mac80211 configuration hooks for cfg80211
 *
4
 * Copyright 2006, 2007	Johannes Berg <johannes@sipsolutions.net>
5
6
7
8
 *
 * This file is GPLv2 as found in COPYING.
 */

9
#include <linux/ieee80211.h>
10
11
#include <linux/nl80211.h>
#include <linux/rtnetlink.h>
12
#include <net/net_namespace.h>
13
#include <linux/rcupdate.h>
14
15
#include <net/cfg80211.h>
#include "ieee80211_i.h"
16
#include "cfg.h"
Johannes Berg's avatar
Johannes Berg committed
17
#include "rate.h"
18
19
#include "mesh.h"

20
21
22
23
24
25
26
struct ieee80211_hw *wiphy_to_hw(struct wiphy *wiphy)
{
	struct ieee80211_local *local = wiphy_priv(wiphy);
	return &local->hw;
}
EXPORT_SYMBOL(wiphy_to_hw);

27
static bool nl80211_type_check(enum nl80211_iftype type)
28
29
30
31
32
{
	switch (type) {
	case NL80211_IFTYPE_ADHOC:
	case NL80211_IFTYPE_STATION:
	case NL80211_IFTYPE_MONITOR:
33
34
35
#ifdef CONFIG_MAC80211_MESH
	case NL80211_IFTYPE_MESH_POINT:
#endif
Johannes Berg's avatar
Johannes Berg committed
36
	case NL80211_IFTYPE_WDS:
37
		return true;
38
	default:
39
		return false;
40
41
42
	}
}

43
static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
44
45
			       enum nl80211_iftype type, u32 *flags,
			       struct vif_params *params)
46
47
{
	struct ieee80211_local *local = wiphy_priv(wiphy);
48
49
50
	struct net_device *dev;
	struct ieee80211_sub_if_data *sdata;
	int err;
51

52
	if (!nl80211_type_check(type))
53
54
		return -EINVAL;

55
56
	err = ieee80211_if_add(local, name, &dev, type, params);
	if (err || type != NL80211_IFTYPE_MONITOR || !flags)
57
58
59
60
61
		return err;

	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	sdata->u.mntr_flags = *flags;
	return 0;
62
63
64
65
66
}

static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex)
{
	struct net_device *dev;
67
	struct ieee80211_sub_if_data *sdata;
68

69
70
	/* we're under RTNL */
	dev = __dev_get_by_index(&init_net, ifindex);
71
	if (!dev)
72
		return -ENODEV;
73

74
75
76
	sdata = IEEE80211_DEV_TO_SUB_IF(dev);

	ieee80211_if_remove(sdata);
77

78
	return 0;
79
80
}

81
static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
82
83
				  enum nl80211_iftype type, u32 *flags,
				  struct vif_params *params)
84
{
85
	struct ieee80211_local *local = wiphy_priv(wiphy);
86
87
	struct net_device *dev;
	struct ieee80211_sub_if_data *sdata;
88
	int ret;
89
90
91
92
93
94

	/* we're under RTNL */
	dev = __dev_get_by_index(&init_net, ifindex);
	if (!dev)
		return -ENODEV;

95
	if (!nl80211_type_check(type))
96
97
		return -EINVAL;

98
99
100
	if (dev == local->mdev)
		return -EOPNOTSUPP;

101
102
	sdata = IEEE80211_DEV_TO_SUB_IF(dev);

103
	ret = ieee80211_if_change_type(sdata, type);
104
105
	if (ret)
		return ret;
106

Johannes Berg's avatar
Johannes Berg committed
107
	if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len)
108
109
110
		ieee80211_sdata_set_mesh_id(sdata,
					    params->mesh_id_len,
					    params->mesh_id);
111

112
	if (sdata->vif.type != NL80211_IFTYPE_MONITOR || !flags)
113
114
115
		return 0;

	sdata->u.mntr_flags = *flags;
116
117
118
	return 0;
}

119
120
121
122
static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
			     u8 key_idx, u8 *mac_addr,
			     struct key_params *params)
{
123
	struct ieee80211_local *local = wiphy_priv(wiphy);
124
125
126
	struct ieee80211_sub_if_data *sdata;
	struct sta_info *sta = NULL;
	enum ieee80211_key_alg alg;
127
	struct ieee80211_key *key;
128
	int err;
129

130
131
132
	if (dev == local->mdev)
		return -EOPNOTSUPP;

133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
	sdata = IEEE80211_DEV_TO_SUB_IF(dev);

	switch (params->cipher) {
	case WLAN_CIPHER_SUITE_WEP40:
	case WLAN_CIPHER_SUITE_WEP104:
		alg = ALG_WEP;
		break;
	case WLAN_CIPHER_SUITE_TKIP:
		alg = ALG_TKIP;
		break;
	case WLAN_CIPHER_SUITE_CCMP:
		alg = ALG_CCMP;
		break;
	default:
		return -EINVAL;
	}

150
151
152
153
	key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key);
	if (!key)
		return -ENOMEM;

154
155
	rcu_read_lock();

156
157
	if (mac_addr) {
		sta = sta_info_get(sdata->local, mac_addr);
158
159
		if (!sta) {
			ieee80211_key_free(key);
160
161
			err = -ENOENT;
			goto out_unlock;
162
		}
163
164
	}

165
166
	ieee80211_key_link(key, sdata, sta);

167
168
169
170
171
	err = 0;
 out_unlock:
	rcu_read_unlock();

	return err;
172
173
174
175
176
}

static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
			     u8 key_idx, u8 *mac_addr)
{
177
	struct ieee80211_local *local = wiphy_priv(wiphy);
178
179
180
181
	struct ieee80211_sub_if_data *sdata;
	struct sta_info *sta;
	int ret;

182
183
184
	if (dev == local->mdev)
		return -EOPNOTSUPP;

185
186
	sdata = IEEE80211_DEV_TO_SUB_IF(dev);

187
188
	rcu_read_lock();

189
	if (mac_addr) {
190
191
		ret = -ENOENT;

192
193
		sta = sta_info_get(sdata->local, mac_addr);
		if (!sta)
194
			goto out_unlock;
195

196
		if (sta->key) {
197
			ieee80211_key_free(sta->key);
198
			WARN_ON(sta->key);
199
200
			ret = 0;
		}
201

202
		goto out_unlock;
203
204
	}

205
206
207
208
	if (!sdata->keys[key_idx]) {
		ret = -ENOENT;
		goto out_unlock;
	}
209

210
	ieee80211_key_free(sdata->keys[key_idx]);
211
	WARN_ON(sdata->keys[key_idx]);
212

213
214
215
216
217
	ret = 0;
 out_unlock:
	rcu_read_unlock();

	return ret;
218
219
}

220
221
222
223
224
static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
			     u8 key_idx, u8 *mac_addr, void *cookie,
			     void (*callback)(void *cookie,
					      struct key_params *params))
{
225
226
	struct ieee80211_local *local = wiphy_priv(wiphy);
	struct ieee80211_sub_if_data *sdata;
227
228
229
230
231
232
233
234
	struct sta_info *sta = NULL;
	u8 seq[6] = {0};
	struct key_params params;
	struct ieee80211_key *key;
	u32 iv32;
	u16 iv16;
	int err = -ENOENT;

235
236
237
238
239
	if (dev == local->mdev)
		return -EOPNOTSUPP;

	sdata = IEEE80211_DEV_TO_SUB_IF(dev);

240
241
	rcu_read_lock();

242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
	if (mac_addr) {
		sta = sta_info_get(sdata->local, mac_addr);
		if (!sta)
			goto out;

		key = sta->key;
	} else
		key = sdata->keys[key_idx];

	if (!key)
		goto out;

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

	switch (key->conf.alg) {
	case ALG_TKIP:
		params.cipher = WLAN_CIPHER_SUITE_TKIP;

260
261
		iv32 = key->u.tkip.tx.iv32;
		iv16 = key->u.tkip.tx.iv16;
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304

		if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE &&
		    sdata->local->ops->get_tkip_seq)
			sdata->local->ops->get_tkip_seq(
				local_to_hw(sdata->local),
				key->conf.hw_key_idx,
				&iv32, &iv16);

		seq[0] = iv16 & 0xff;
		seq[1] = (iv16 >> 8) & 0xff;
		seq[2] = iv32 & 0xff;
		seq[3] = (iv32 >> 8) & 0xff;
		seq[4] = (iv32 >> 16) & 0xff;
		seq[5] = (iv32 >> 24) & 0xff;
		params.seq = seq;
		params.seq_len = 6;
		break;
	case ALG_CCMP:
		params.cipher = WLAN_CIPHER_SUITE_CCMP;
		seq[0] = key->u.ccmp.tx_pn[5];
		seq[1] = key->u.ccmp.tx_pn[4];
		seq[2] = key->u.ccmp.tx_pn[3];
		seq[3] = key->u.ccmp.tx_pn[2];
		seq[4] = key->u.ccmp.tx_pn[1];
		seq[5] = key->u.ccmp.tx_pn[0];
		params.seq = seq;
		params.seq_len = 6;
		break;
	case ALG_WEP:
		if (key->conf.keylen == 5)
			params.cipher = WLAN_CIPHER_SUITE_WEP40;
		else
			params.cipher = WLAN_CIPHER_SUITE_WEP104;
		break;
	}

	params.key = key->conf.key;
	params.key_len = key->conf.keylen;

	callback(cookie, &params);
	err = 0;

 out:
305
	rcu_read_unlock();
306
307
308
	return err;
}

309
310
311
312
static int ieee80211_config_default_key(struct wiphy *wiphy,
					struct net_device *dev,
					u8 key_idx)
{
313
	struct ieee80211_local *local = wiphy_priv(wiphy);
314
315
	struct ieee80211_sub_if_data *sdata;

316
317
318
	if (dev == local->mdev)
		return -EOPNOTSUPP;

319
320
	rcu_read_lock();

321
322
323
	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	ieee80211_set_default_key(sdata, key_idx);

324
325
	rcu_read_unlock();

326
327
328
	return 0;
}

329
330
static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
{
331
	struct ieee80211_sub_if_data *sdata = sta->sdata;
332
333
334
335
336
337
338
339
340

	sinfo->filled = STATION_INFO_INACTIVE_TIME |
			STATION_INFO_RX_BYTES |
			STATION_INFO_TX_BYTES;

	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
	sinfo->rx_bytes = sta->rx_bytes;
	sinfo->tx_bytes = sta->tx_bytes;

Johannes Berg's avatar
Johannes Berg committed
341
	if (ieee80211_vif_is_mesh(&sdata->vif)) {
342
343
344
345
346
347
348
349
350
#ifdef CONFIG_MAC80211_MESH
		sinfo->filled |= STATION_INFO_LLID |
				 STATION_INFO_PLID |
				 STATION_INFO_PLINK_STATE;

		sinfo->llid = le16_to_cpu(sta->llid);
		sinfo->plid = le16_to_cpu(sta->plid);
		sinfo->plink_state = sta->plink_state;
#endif
Johannes Berg's avatar
Johannes Berg committed
351
	}
352
353
354
355
356
357
358
359
}


static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
				 int idx, u8 *mac, struct station_info *sinfo)
{
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
	struct sta_info *sta;
360
361
362
	int ret = -ENOENT;

	rcu_read_lock();
363
364

	sta = sta_info_get_by_idx(local, idx, dev);
365
366
	if (sta) {
		ret = 0;
367
		memcpy(mac, sta->sta.addr, ETH_ALEN);
368
369
		sta_set_sinfo(sta, sinfo);
	}
370

371
	rcu_read_unlock();
372

373
	return ret;
374
375
}

376
static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
377
				 u8 *mac, struct station_info *sinfo)
378
379
380
{
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
	struct sta_info *sta;
381
	int ret = -ENOENT;
382

383
	rcu_read_lock();
384
385
386

	/* XXX: verify sta->dev == dev */

387
388
389
390
391
392
393
394
395
	sta = sta_info_get(local, mac);
	if (sta) {
		ret = 0;
		sta_set_sinfo(sta, sinfo);
	}

	rcu_read_unlock();

	return ret;
396
397
}

398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
/*
 * This handles both adding a beacon and setting new beacon info
 */
static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata,
				   struct beacon_parameters *params)
{
	struct beacon_data *new, *old;
	int new_head_len, new_tail_len;
	int size;
	int err = -EINVAL;

	old = sdata->u.ap.beacon;

	/* head must not be zero-length */
	if (params->head && !params->head_len)
		return -EINVAL;

	/*
	 * This is a kludge. beacon interval should really be part
	 * of the beacon information.
	 */
	if (params->interval) {
		sdata->local->hw.conf.beacon_int = params->interval;
		if (ieee80211_hw_config(sdata->local))
			return -EINVAL;
		/*
		 * We updated some parameter so if below bails out
		 * it's not an error.
		 */
		err = 0;
	}

	/* Need to have a beacon head if we don't have one yet */
	if (!params->head && !old)
		return err;

	/* sorry, no way to start beaconing without dtim period */
	if (!params->dtim_period && !old)
		return err;

	/* new or old head? */
	if (params->head)
		new_head_len = params->head_len;
	else
		new_head_len = old->head_len;

	/* new or old tail? */
	if (params->tail || !old)
		/* params->tail_len will be zero for !params->tail */
		new_tail_len = params->tail_len;
	else
		new_tail_len = old->tail_len;

	size = sizeof(*new) + new_head_len + new_tail_len;

	new = kzalloc(size, GFP_KERNEL);
	if (!new)
		return -ENOMEM;

	/* start filling the new info now */

	/* new or old dtim period? */
	if (params->dtim_period)
		new->dtim_period = params->dtim_period;
	else
		new->dtim_period = old->dtim_period;

	/*
	 * pointers go into the block we allocated,
	 * memory is | beacon_data | head | tail |
	 */
	new->head = ((u8 *) new) + sizeof(*new);
	new->tail = new->head + new_head_len;
	new->head_len = new_head_len;
	new->tail_len = new_tail_len;

	/* copy in head */
	if (params->head)
		memcpy(new->head, params->head, new_head_len);
	else
		memcpy(new->head, old->head, new_head_len);

	/* copy in optional tail */
	if (params->tail)
		memcpy(new->tail, params->tail, new_tail_len);
	else
		if (old)
			memcpy(new->tail, old->tail, new_tail_len);

	rcu_assign_pointer(sdata->u.ap.beacon, new);

	synchronize_rcu();

	kfree(old);

493
	return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON);
494
495
496
497
498
}

static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev,
				struct beacon_parameters *params)
{
499
500
	struct ieee80211_local *local = wiphy_priv(wiphy);
	struct ieee80211_sub_if_data *sdata;
501
502
	struct beacon_data *old;

503
504
505
506
507
	if (dev == local->mdev)
		return -EOPNOTSUPP;

	sdata = IEEE80211_DEV_TO_SUB_IF(dev);

508
	if (sdata->vif.type != NL80211_IFTYPE_AP)
509
510
511
512
513
514
515
516
517
518
519
520
521
		return -EINVAL;

	old = sdata->u.ap.beacon;

	if (old)
		return -EALREADY;

	return ieee80211_config_beacon(sdata, params);
}

static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
				struct beacon_parameters *params)
{
522
523
	struct ieee80211_local *local = wiphy_priv(wiphy);
	struct ieee80211_sub_if_data *sdata;
524
525
	struct beacon_data *old;

526
527
528
529
530
	if (dev == local->mdev)
		return -EOPNOTSUPP;

	sdata = IEEE80211_DEV_TO_SUB_IF(dev);

531
	if (sdata->vif.type != NL80211_IFTYPE_AP)
532
533
534
535
536
537
538
539
540
541
542
543
		return -EINVAL;

	old = sdata->u.ap.beacon;

	if (!old)
		return -ENOENT;

	return ieee80211_config_beacon(sdata, params);
}

static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)
{
544
545
	struct ieee80211_local *local = wiphy_priv(wiphy);
	struct ieee80211_sub_if_data *sdata;
546
547
	struct beacon_data *old;

548
549
550
551
552
	if (dev == local->mdev)
		return -EOPNOTSUPP;

	sdata = IEEE80211_DEV_TO_SUB_IF(dev);

553
	if (sdata->vif.type != NL80211_IFTYPE_AP)
554
555
556
557
558
559
560
561
562
563
564
		return -EINVAL;

	old = sdata->u.ap.beacon;

	if (!old)
		return -ENOENT;

	rcu_assign_pointer(sdata->u.ap.beacon, NULL);
	synchronize_rcu();
	kfree(old);

565
	return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON);
566
567
}

568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
/* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */
struct iapp_layer2_update {
	u8 da[ETH_ALEN];	/* broadcast */
	u8 sa[ETH_ALEN];	/* STA addr */
	__be16 len;		/* 6 */
	u8 dsap;		/* 0 */
	u8 ssap;		/* 0 */
	u8 control;
	u8 xid_info[3];
} __attribute__ ((packed));

static void ieee80211_send_layer2_update(struct sta_info *sta)
{
	struct iapp_layer2_update *msg;
	struct sk_buff *skb;

	/* Send Level 2 Update Frame to update forwarding tables in layer 2
	 * bridge devices */

	skb = dev_alloc_skb(sizeof(*msg));
	if (!skb)
		return;
	msg = (struct iapp_layer2_update *)skb_put(skb, sizeof(*msg));

	/* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID)
	 * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */

	memset(msg->da, 0xff, ETH_ALEN);
596
	memcpy(msg->sa, sta->sta.addr, ETH_ALEN);
597
598
599
600
601
602
603
604
605
	msg->len = htons(6);
	msg->dsap = 0;
	msg->ssap = 0x01;	/* NULL LSAP, CR Bit: Response */
	msg->control = 0xaf;	/* XID response lsb.1111F101.
				 * F=0 (no poll command; unsolicited frame) */
	msg->xid_info[0] = 0x81;	/* XID format identifier */
	msg->xid_info[1] = 1;	/* LLC types/classes: Type 1 LLC */
	msg->xid_info[2] = 0;	/* XID sender's receive window size (RW) */

606
607
	skb->dev = sta->sdata->dev;
	skb->protocol = eth_type_trans(skb, sta->sdata->dev);
608
609
610
611
612
613
614
615
616
617
	memset(skb->cb, 0, sizeof(skb->cb));
	netif_rx(skb);
}

static void sta_apply_parameters(struct ieee80211_local *local,
				 struct sta_info *sta,
				 struct station_parameters *params)
{
	u32 rates;
	int i, j;
618
	struct ieee80211_supported_band *sband;
619
	struct ieee80211_sub_if_data *sdata = sta->sdata;
620

Johannes Berg's avatar
Johannes Berg committed
621
622
623
624
625
626
	/*
	 * FIXME: updating the flags is racy when this function is
	 *	  called from ieee80211_change_station(), this will
	 *	  be resolved in a future patch.
	 */

627
	if (params->station_flags & STATION_FLAG_CHANGED) {
628
		spin_lock_bh(&sta->lock);
629
630
631
632
633
634
635
636
637
638
639
		sta->flags &= ~WLAN_STA_AUTHORIZED;
		if (params->station_flags & STATION_FLAG_AUTHORIZED)
			sta->flags |= WLAN_STA_AUTHORIZED;

		sta->flags &= ~WLAN_STA_SHORT_PREAMBLE;
		if (params->station_flags & STATION_FLAG_SHORT_PREAMBLE)
			sta->flags |= WLAN_STA_SHORT_PREAMBLE;

		sta->flags &= ~WLAN_STA_WME;
		if (params->station_flags & STATION_FLAG_WME)
			sta->flags |= WLAN_STA_WME;
640
		spin_unlock_bh(&sta->lock);
641
642
	}

Johannes Berg's avatar
Johannes Berg committed
643
644
645
646
647
648
649
	/*
	 * FIXME: updating the following information is racy when this
	 *	  function is called from ieee80211_change_station().
	 *	  However, all this information should be static so
	 *	  maybe we should just reject attemps to change it.
	 */

650
	if (params->aid) {
651
652
653
		sta->sta.aid = params->aid;
		if (sta->sta.aid > IEEE80211_MAX_AID)
			sta->sta.aid = 0; /* XXX: should this be an error? */
654
655
656
657
658
659
660
	}

	if (params->listen_interval >= 0)
		sta->listen_interval = params->listen_interval;

	if (params->supported_rates) {
		rates = 0;
661
662
		sband = local->hw.wiphy->bands[local->oper_channel->band];

663
664
		for (i = 0; i < params->supported_rates_len; i++) {
			int rate = (params->supported_rates[i] & 0x7f) * 5;
665
666
			for (j = 0; j < sband->n_bitrates; j++) {
				if (sband->bitrates[j].bitrate == rate)
667
668
669
					rates |= BIT(j);
			}
		}
670
		sta->supp_rates[local->oper_channel->band] = rates;
671
	}
672

673
674
675
676
677
	if (params->ht_capa) {
		ieee80211_ht_cap_ie_to_ht_info(params->ht_capa,
					       &sta->ht_info);
	}

Johannes Berg's avatar
Johannes Berg committed
678
	if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) {
679
680
681
682
683
684
685
686
		switch (params->plink_action) {
		case PLINK_ACTION_OPEN:
			mesh_plink_open(sta);
			break;
		case PLINK_ACTION_BLOCK:
			mesh_plink_block(sta);
			break;
		}
Johannes Berg's avatar
Johannes Berg committed
687
	}
688
689
690
691
692
}

static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
				 u8 *mac, struct station_parameters *params)
{
693
	struct ieee80211_local *local = wiphy_priv(wiphy);
694
695
	struct sta_info *sta;
	struct ieee80211_sub_if_data *sdata;
Johannes Berg's avatar
Johannes Berg committed
696
	int err;
697

698
699
700
	if (dev == local->mdev || params->vlan == local->mdev)
		return -EOPNOTSUPP;

701
702
703
704
705
706
707
	/* Prevent a race with changing the rate control algorithm */
	if (!netif_running(dev))
		return -ENETDOWN;

	if (params->vlan) {
		sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);

708
709
		if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
		    sdata->vif.type != NL80211_IFTYPE_AP)
710
711
712
713
			return -EINVAL;
	} else
		sdata = IEEE80211_DEV_TO_SUB_IF(dev);

714
715
716
717
718
719
720
	if (compare_ether_addr(mac, dev->dev_addr) == 0)
		return -EINVAL;

	if (is_multicast_ether_addr(mac))
		return -EINVAL;

	sta = sta_info_alloc(sdata, mac, GFP_KERNEL);
Johannes Berg's avatar
Johannes Berg committed
721
722
	if (!sta)
		return -ENOMEM;
723
724
725
726
727
728
729

	sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC;

	sta_apply_parameters(local, sta, params);

	rate_control_rate_init(sta, local);

Johannes Berg's avatar
Johannes Berg committed
730
731
732
733
	rcu_read_lock();

	err = sta_info_insert(sta);
	if (err) {
734
		/* STA has been freed */
Johannes Berg's avatar
Johannes Berg committed
735
736
737
738
		rcu_read_unlock();
		return err;
	}

739
740
	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
	    sdata->vif.type == NL80211_IFTYPE_AP)
Johannes Berg's avatar
Johannes Berg committed
741
742
743
744
		ieee80211_send_layer2_update(sta);

	rcu_read_unlock();

745
746
747
748
749
750
	return 0;
}

static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev,
				 u8 *mac)
{
751
752
	struct ieee80211_local *local = wiphy_priv(wiphy);
	struct ieee80211_sub_if_data *sdata;
753
754
	struct sta_info *sta;

755
756
757
758
759
	if (dev == local->mdev)
		return -EOPNOTSUPP;

	sdata = IEEE80211_DEV_TO_SUB_IF(dev);

760
	if (mac) {
Johannes Berg's avatar
Johannes Berg committed
761
762
		rcu_read_lock();

763
764
		/* XXX: get sta belonging to dev */
		sta = sta_info_get(local, mac);
Johannes Berg's avatar
Johannes Berg committed
765
766
		if (!sta) {
			rcu_read_unlock();
767
			return -ENOENT;
Johannes Berg's avatar
Johannes Berg committed
768
		}
769

770
		sta_info_unlink(&sta);
Johannes Berg's avatar
Johannes Berg committed
771
772
		rcu_read_unlock();

773
		sta_info_destroy(sta);
774
	} else
775
		sta_info_flush(local, sdata);
776
777
778
779
780
781
782
783
784

	return 0;
}

static int ieee80211_change_station(struct wiphy *wiphy,
				    struct net_device *dev,
				    u8 *mac,
				    struct station_parameters *params)
{
785
	struct ieee80211_local *local = wiphy_priv(wiphy);
786
787
788
	struct sta_info *sta;
	struct ieee80211_sub_if_data *vlansdata;

789
790
791
	if (dev == local->mdev || params->vlan == local->mdev)
		return -EOPNOTSUPP;

Johannes Berg's avatar
Johannes Berg committed
792
793
	rcu_read_lock();

794
795
	/* XXX: get sta belonging to dev */
	sta = sta_info_get(local, mac);
Johannes Berg's avatar
Johannes Berg committed
796
797
	if (!sta) {
		rcu_read_unlock();
798
		return -ENOENT;
Johannes Berg's avatar
Johannes Berg committed
799
	}
800

801
	if (params->vlan && params->vlan != sta->sdata->dev) {
802
803
		vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);

804
805
		if (vlansdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
		    vlansdata->vif.type != NL80211_IFTYPE_AP) {
Johannes Berg's avatar
Johannes Berg committed
806
			rcu_read_unlock();
807
			return -EINVAL;
Johannes Berg's avatar
Johannes Berg committed
808
		}
809

810
		sta->sdata = vlansdata;
811
812
813
814
815
		ieee80211_send_layer2_update(sta);
	}

	sta_apply_parameters(local, sta, params);

Johannes Berg's avatar
Johannes Berg committed
816
817
	rcu_read_unlock();

818
819
820
	return 0;
}

821
822
823
824
#ifdef CONFIG_MAC80211_MESH
static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
				 u8 *dst, u8 *next_hop)
{
825
826
	struct ieee80211_local *local = wiphy_priv(wiphy);
	struct ieee80211_sub_if_data *sdata;
827
828
829
830
	struct mesh_path *mpath;
	struct sta_info *sta;
	int err;

831
832
833
	if (dev == local->mdev)
		return -EOPNOTSUPP;

834
835
836
	if (!netif_running(dev))
		return -ENETDOWN;

837
838
	sdata = IEEE80211_DEV_TO_SUB_IF(dev);

839
	if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
840
841
		return -ENOTSUPP;

842
	rcu_read_lock();
843
	sta = sta_info_get(local, next_hop);
844
845
	if (!sta) {
		rcu_read_unlock();
846
		return -ENOENT;
847
	}
848

849
	err = mesh_path_add(dst, sdata);
850
851
	if (err) {
		rcu_read_unlock();
852
		return err;
853
	}
854

855
	mpath = mesh_path_lookup(dst, sdata);
856
857
858
859
860
	if (!mpath) {
		rcu_read_unlock();
		return -ENXIO;
	}
	mesh_path_fix_nexthop(mpath, sta);
861

862
863
864
865
866
867
868
	rcu_read_unlock();
	return 0;
}

static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev,
				 u8 *dst)
{
869
870
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);

871
	if (dst)
872
		return mesh_path_del(dst, sdata);
873

874
	mesh_path_flush(sdata);
875
876
877
878
879
880
881
	return 0;
}

static int ieee80211_change_mpath(struct wiphy *wiphy,
				    struct net_device *dev,
				    u8 *dst, u8 *next_hop)
{
882
883
	struct ieee80211_local *local = wiphy_priv(wiphy);
	struct ieee80211_sub_if_data *sdata;
884
885
886
	struct mesh_path *mpath;
	struct sta_info *sta;

887
888
889
	if (dev == local->mdev)
		return -EOPNOTSUPP;

890
891
892
	if (!netif_running(dev))
		return -ENETDOWN;

893
894
	sdata = IEEE80211_DEV_TO_SUB_IF(dev);

895
	if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
896
897
		return -ENOTSUPP;

898
899
	rcu_read_lock();

900
	sta = sta_info_get(local, next_hop);
901
902
	if (!sta) {
		rcu_read_unlock();
903
		return -ENOENT;
904
	}
905

906
	mpath = mesh_path_lookup(dst, sdata);
907
908
909
910
911
912
	if (!mpath) {
		rcu_read_unlock();
		return -ENOENT;
	}

	mesh_path_fix_nexthop(mpath, sta);
913

914
915
916
917
918
919
920
921
	rcu_read_unlock();
	return 0;
}

static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
			    struct mpath_info *pinfo)
{
	if (mpath->next_hop)
922
		memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN);
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
	else
		memset(next_hop, 0, ETH_ALEN);

	pinfo->filled = MPATH_INFO_FRAME_QLEN |
			MPATH_INFO_DSN |
			MPATH_INFO_METRIC |
			MPATH_INFO_EXPTIME |
			MPATH_INFO_DISCOVERY_TIMEOUT |
			MPATH_INFO_DISCOVERY_RETRIES |
			MPATH_INFO_FLAGS;

	pinfo->frame_qlen = mpath->frame_queue.qlen;
	pinfo->dsn = mpath->dsn;
	pinfo->metric = mpath->metric;
	if (time_before(jiffies, mpath->exp_time))
		pinfo->exptime = jiffies_to_msecs(mpath->exp_time - jiffies);
	pinfo->discovery_timeout =
			jiffies_to_msecs(mpath->discovery_timeout);
	pinfo->discovery_retries = mpath->discovery_retries;
	pinfo->flags = 0;
	if (mpath->flags & MESH_PATH_ACTIVE)
		pinfo->flags |= NL80211_MPATH_FLAG_ACTIVE;
	if (mpath->flags & MESH_PATH_RESOLVING)
		pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING;
	if (mpath->flags & MESH_PATH_DSN_VALID)
		pinfo->flags |= NL80211_MPATH_FLAG_DSN_VALID;
	if (mpath->flags & MESH_PATH_FIXED)
		pinfo->flags |= NL80211_MPATH_FLAG_FIXED;
	if (mpath->flags & MESH_PATH_RESOLVING)
		pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING;

	pinfo->flags = mpath->flags;
}

static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev,
			       u8 *dst, u8 *next_hop, struct mpath_info *pinfo)

{
961
962
	struct ieee80211_local *local = wiphy_priv(wiphy);
	struct ieee80211_sub_if_data *sdata;
963
964
	struct mesh_path *mpath;

965
966
967
968
969
	if (dev == local->mdev)
		return -EOPNOTSUPP;

	sdata = IEEE80211_DEV_TO_SUB_IF(dev);

970
	if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
971
972
973
		return -ENOTSUPP;

	rcu_read_lock();
974
	mpath = mesh_path_lookup(dst, sdata);
975
976
977
978
979
980
981
982
983
984
985
986
987
988
	if (!mpath) {
		rcu_read_unlock();
		return -ENOENT;
	}
	memcpy(dst, mpath->dst, ETH_ALEN);
	mpath_set_pinfo(mpath, next_hop, pinfo);
	rcu_read_unlock();
	return 0;
}

static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev,
				 int idx, u8 *dst, u8 *next_hop,
				 struct mpath_info *pinfo)
{
989
990
	struct ieee80211_local *local = wiphy_priv(wiphy);
	struct ieee80211_sub_if_data *sdata;
991
992
	struct mesh_path *mpath;

993
994
995
996
997
	if (dev == local->mdev)
		return -EOPNOTSUPP;

	sdata = IEEE80211_DEV_TO_SUB_IF(dev);

998
	if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
999
1000
		return -ENOTSUPP;

For faster browsing, not all history is shown. View entire blame