mesh_plink.c 25.3 KB
Newer Older
1
/*
R
Rui Paulo 已提交
2
 * Copyright (c) 2008, 2009 open80211s Ltd.
3 4 5 6 7 8
 * Author:     Luis Carlos Cobo <luisca@cozybit.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
9
#include <linux/gfp.h>
J
Johannes Berg 已提交
10 11
#include <linux/kernel.h>
#include <linux/random.h>
12
#include "ieee80211_i.h"
J
Johannes Berg 已提交
13
#include "rate.h"
14 15 16 17 18 19 20 21
#include "mesh.h"

#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
#define mpl_dbg(fmt, args...)	printk(KERN_DEBUG fmt, ##args)
#else
#define mpl_dbg(fmt, args...)	do { (void)(0); } while (0)
#endif

22 23
#define PLINK_GET_LLID(p) (p + 2)
#define PLINK_GET_PLID(p) (p + 4)
24 25 26 27

#define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \
				jiffies + HZ * t / 1000))

28 29 30 31 32
#define dot11MeshMaxRetries(s) (s->u.mesh.mshcfg.dot11MeshMaxRetries)
#define dot11MeshRetryTimeout(s) (s->u.mesh.mshcfg.dot11MeshRetryTimeout)
#define dot11MeshConfirmTimeout(s) (s->u.mesh.mshcfg.dot11MeshConfirmTimeout)
#define dot11MeshHoldingTimeout(s) (s->u.mesh.mshcfg.dot11MeshHoldingTimeout)
#define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks)
33

34 35
/* We only need a valid sta if user configured a minimum rssi_threshold. */
#define rssi_threshold_check(sta, sdata) \
36
		(sdata->u.mesh.mshcfg.rssi_threshold == 0 ||\
37 38
		(sta && (s8) -ewma_read(&sta->avg_signal) > \
		sdata->u.mesh.mshcfg.rssi_threshold))
39

40 41 42 43 44 45 46 47 48 49 50 51
enum plink_event {
	PLINK_UNDEFINED,
	OPN_ACPT,
	OPN_RJCT,
	OPN_IGNR,
	CNF_ACPT,
	CNF_RJCT,
	CNF_IGNR,
	CLS_ACPT,
	CLS_IGNR
};

52 53 54 55
static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
		enum ieee80211_self_protected_actioncode action,
		u8 *da, __le16 llid, __le16 plid, __le16 reason);

56 57 58
static inline
void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata)
{
59
	atomic_inc(&sdata->u.mesh.mshstats.estab_plinks);
60
	mesh_accept_plinks_update(sdata);
61 62 63 64 65
}

static inline
void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata)
{
66
	atomic_dec(&sdata->u.mesh.mshstats.estab_plinks);
67
	mesh_accept_plinks_update(sdata);
68 69 70 71 72
}

/**
 * mesh_plink_fsm_restart - restart a mesh peer link finite state machine
 *
R
Rui Paulo 已提交
73
 * @sta: mesh peer link to restart
74
 *
75
 * Locking: this function must be called holding sta->lock
76 77 78
 */
static inline void mesh_plink_fsm_restart(struct sta_info *sta)
{
79
	sta->plink_state = NL80211_PLINK_LISTEN;
80 81
	sta->llid = sta->plid = sta->reason = 0;
	sta->plink_retries = 0;
82 83
}

84
/*
85
 * Allocate mesh sta entry and insert into station table
86
 */
87
static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
88
					 u8 *hw_addr)
89 90 91
{
	struct sta_info *sta;

92
	if (sdata->local->num_sta >= MESH_MAX_PLINKS)
J
Johannes Berg 已提交
93
		return NULL;
94

95
	sta = sta_info_alloc(sdata, hw_addr, GFP_KERNEL);
J
Johannes Berg 已提交
96 97
	if (!sta)
		return NULL;
98

99 100 101
	sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
	sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
	sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED);
102

J
Johannes Berg 已提交
103
	set_sta_flag(sta, WLAN_STA_WME);
104

105 106 107
	return sta;
}

108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
/** mesh_set_ht_prot_mode - set correct HT protection mode
 *
 * Section 9.23.3.5 of IEEE 80211s standard describes the protection rules for
 * HT mesh STA in a MBSS. Three HT protection modes are supported for now,
 * non-HT mixed mode, 20MHz-protection and no-protection mode. non-HT mixed
 * mode is selected if any non-HT peers are present in our MBSS.
 * 20MHz-protection mode is selected if all peers in our 20/40MHz MBSS support
 * HT and atleast one HT20 peer is present. Otherwise no-protection mode is
 * selected.
 */
static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_local *local = sdata->local;
	struct sta_info *sta;
	u32 changed = 0;
	u16 ht_opmode;
	bool non_ht_sta = false, ht20_sta = false;

	if (local->_oper_channel_type == NL80211_CHAN_NO_HT)
		return 0;

	rcu_read_lock();
	list_for_each_entry_rcu(sta, &local->sta_list, list) {
		if (sdata == sta->sdata &&
		    sta->plink_state == NL80211_PLINK_ESTAB) {
			switch (sta->ch_type) {
			case NL80211_CHAN_NO_HT:
				mpl_dbg("mesh_plink %pM: nonHT sta (%pM) is present",
					sdata->vif.addr, sta->sta.addr);
				non_ht_sta = true;
				goto out;
			case NL80211_CHAN_HT20:
				mpl_dbg("mesh_plink %pM: HT20 sta (%pM) is present",
					sdata->vif.addr, sta->sta.addr);
				ht20_sta = true;
			default:
				break;
			}
		}
	}
out:
	rcu_read_unlock();

	if (non_ht_sta)
		ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED;
	else if (ht20_sta && local->_oper_channel_type > NL80211_CHAN_HT20)
		ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_20MHZ;
	else
		ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONE;

	if (sdata->vif.bss_conf.ht_operation_mode != ht_opmode) {
		sdata->vif.bss_conf.ht_operation_mode = ht_opmode;
		changed = BSS_CHANGED_HT;
		mpl_dbg("mesh_plink %pM: protection mode changed to %d",
			sdata->vif.addr, ht_opmode);
	}

	return changed;
}

168
/**
169
 * __mesh_plink_deactivate - deactivate mesh peer link
170 171 172 173 174
 *
 * @sta: mesh peer link to deactivate
 *
 * All mesh paths with this peer as next hop will be flushed
 *
175
 * Locking: the caller must hold sta->lock
176
 */
177
static bool __mesh_plink_deactivate(struct sta_info *sta)
178
{
179
	struct ieee80211_sub_if_data *sdata = sta->sdata;
180
	bool deactivated = false;
181

182
	if (sta->plink_state == NL80211_PLINK_ESTAB) {
183
		mesh_plink_dec_estab_count(sdata);
184 185
		deactivated = true;
	}
186
	sta->plink_state = NL80211_PLINK_BLOCKED;
187
	mesh_path_flush_by_nexthop(sta);
188 189

	return deactivated;
190 191
}

J
Johannes Berg 已提交
192
/**
193
 * mesh_plink_deactivate - deactivate mesh peer link
J
Johannes Berg 已提交
194 195 196 197 198 199 200
 *
 * @sta: mesh peer link to deactivate
 *
 * All mesh paths with this peer as next hop will be flushed
 */
void mesh_plink_deactivate(struct sta_info *sta)
{
201 202 203
	struct ieee80211_sub_if_data *sdata = sta->sdata;
	bool deactivated;

204
	spin_lock_bh(&sta->lock);
205
	deactivated = __mesh_plink_deactivate(sta);
206 207 208 209
	sta->reason = cpu_to_le16(WLAN_REASON_MESH_PEER_CANCELED);
	mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
			    sta->sta.addr, sta->llid, sta->plid,
			    sta->reason);
210
	spin_unlock_bh(&sta->lock);
211 212 213

	if (deactivated)
		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
J
Johannes Berg 已提交
214 215
}

216
static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
217 218
		enum ieee80211_self_protected_actioncode action,
		u8 *da, __le16 llid, __le16 plid, __le16 reason) {
219
	struct ieee80211_local *local = sdata->local;
220
	struct sk_buff *skb;
221 222
	struct ieee80211_mgmt *mgmt;
	bool include_plid = false;
223
	u16 peering_proto = 0;
224 225 226 227
	u8 *pos, ie_len = 4;
	int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.self_prot) +
		      sizeof(mgmt->u.action.u.self_prot);

228
	skb = dev_alloc_skb(local->tx_headroom +
229 230 231 232 233 234 235
			    hdr_len +
			    2 + /* capability info */
			    2 + /* AID */
			    2 + 8 + /* supported rates */
			    2 + (IEEE80211_MAX_SUPP_RATES - 8) +
			    2 + sdata->u.mesh.mesh_id_len +
			    2 + sizeof(struct ieee80211_meshconf_ie) +
236
			    2 + sizeof(struct ieee80211_ht_cap) +
237
			    2 + sizeof(struct ieee80211_ht_operation) +
238 239
			    2 + 8 + /* peering IE */
			    sdata->u.mesh.ie_len);
240 241
	if (!skb)
		return -1;
242
	skb_reserve(skb, local->tx_headroom);
243 244
	mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
	memset(mgmt, 0, hdr_len);
245 246
	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
					  IEEE80211_STYPE_ACTION);
247
	memcpy(mgmt->da, da, ETH_ALEN);
248
	memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
249
	memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
250 251
	mgmt->u.action.category = WLAN_CATEGORY_SELF_PROTECTED;
	mgmt->u.action.u.self_prot.action_code = action;
252

253 254 255 256
	if (action != WLAN_SP_MESH_PEERING_CLOSE) {
		/* capability info */
		pos = skb_put(skb, 2);
		memset(pos, 0, 2);
257
		if (action == WLAN_SP_MESH_PEERING_CONFIRM) {
258 259
			/* AID */
			pos = skb_put(skb, 2);
260
			memcpy(pos + 2, &plid, 2);
261
		}
262 263
		if (ieee80211_add_srates_ie(&sdata->vif, skb, true) ||
		    ieee80211_add_ext_srates_ie(&sdata->vif, skb, true) ||
264 265 266 267
		    mesh_add_rsn_ie(skb, sdata) ||
		    mesh_add_meshid_ie(skb, sdata) ||
		    mesh_add_meshconf_ie(skb, sdata))
			return -1;
268 269 270
	} else {	/* WLAN_SP_MESH_PEERING_CLOSE */
		if (mesh_add_meshid_ie(skb, sdata))
			return -1;
271 272
	}

273
	/* Add Mesh Peering Management element */
274
	switch (action) {
275
	case WLAN_SP_MESH_PEERING_OPEN:
276
		break;
277
	case WLAN_SP_MESH_PEERING_CONFIRM:
278
		ie_len += 2;
279 280
		include_plid = true;
		break;
281
	case WLAN_SP_MESH_PEERING_CLOSE:
282 283
		if (plid) {
			ie_len += 2;
284 285
			include_plid = true;
		}
286
		ie_len += 2;	/* reason code */
287
		break;
288 289
	default:
		return -EINVAL;
290 291
	}

292 293 294
	if (WARN_ON(skb_tailroom(skb) < 2 + ie_len))
		return -ENOMEM;

295
	pos = skb_put(skb, 2 + ie_len);
296
	*pos++ = WLAN_EID_PEER_MGMT;
297
	*pos++ = ie_len;
298 299
	memcpy(pos, &peering_proto, 2);
	pos += 2;
300
	memcpy(pos, &llid, 2);
301
	pos += 2;
302 303
	if (include_plid) {
		memcpy(pos, &plid, 2);
304
		pos += 2;
305
	}
306
	if (action == WLAN_SP_MESH_PEERING_CLOSE) {
307
		memcpy(pos, &reason, 2);
308
		pos += 2;
309
	}
310 311 312

	if (action != WLAN_SP_MESH_PEERING_CLOSE) {
		if (mesh_add_ht_cap_ie(skb, sdata) ||
313
		    mesh_add_ht_oper_ie(skb, sdata))
314 315 316
			return -1;
	}

317 318
	if (mesh_add_vendor_ies(skb, sdata))
		return -1;
319

320
	ieee80211_tx_skb(sdata, skb);
321 322 323
	return 0;
}

324 325 326 327 328 329 330 331 332
/* mesh_peer_init - initialize new mesh peer and return resulting sta_info
 *
 * @sdata: local meshif
 * @addr: peer's address
 * @elems: IEs from beacon or mesh peering frame
 *
 * call under RCU
 */
static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata,
333
				       u8 *addr,
334
				       struct ieee802_11_elems *elems)
335
{
336
	struct ieee80211_local *local = sdata->local;
337
	enum ieee80211_band band = local->oper_channel->band;
338
	struct ieee80211_supported_band *sband;
339
	u32 rates, basic_rates = 0;
340
	struct sta_info *sta;
341
	bool insert = false;
342

343 344
	sband = local->hw.wiphy->bands[band];
	rates = ieee80211_sta_get_rates(local, elems, band, &basic_rates);
345

346
	sta = sta_info_get(sdata, addr);
347
	if (!sta) {
348
		sta = mesh_plink_alloc(sdata, addr);
349
		if (!sta)
350
			return NULL;
351
		insert = true;
352 353
	}

354
	spin_lock_bh(&sta->lock);
355
	sta->last_rx = jiffies;
356
	sta->sta.supp_rates[band] = rates;
357 358
	if (elems->ht_cap_elem &&
	    sdata->local->_oper_channel_type != NL80211_CHAN_NO_HT)
359 360 361 362 363 364
		ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
						  elems->ht_cap_elem,
						  &sta->sta.ht_cap);
	else
		memset(&sta->sta.ht_cap, 0, sizeof(sta->sta.ht_cap));

365
	if (elems->ht_operation) {
366 367 368 369
		if (!(elems->ht_operation->ht_param &
		      IEEE80211_HT_PARAM_CHAN_WIDTH_ANY))
			sta->sta.ht_cap.cap &=
					    ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
370 371 372
		sta->ch_type =
			ieee80211_ht_oper_to_channel_type(elems->ht_operation);
	}
373

374 375 376
	rate_control_rate_init(sta);
	spin_unlock_bh(&sta->lock);

377 378 379
	if (insert && sta_info_insert(sta))
		return NULL;

380 381 382
	return sta;
}

383 384
void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata,
			   u8 *hw_addr,
385 386 387 388 389 390 391 392 393 394 395 396 397 398
			   struct ieee802_11_elems *elems)
{
	struct sta_info *sta;

	/* Userspace handles peer allocation when security is enabled */
	if (sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED) {
		cfg80211_notify_new_peer_candidate(sdata->dev, hw_addr,
						   elems->ie_start,
						   elems->total_len,
						   GFP_KERNEL);
		return;
	}

	rcu_read_lock();
399
	sta = mesh_peer_init(sdata, hw_addr, elems);
400 401 402
	if (!sta)
		goto out;

403
	if (mesh_peer_accepts_plinks(elems) &&
404 405 406 407
	    sta->plink_state == NL80211_PLINK_LISTEN &&
	    sdata->u.mesh.accepting_plinks &&
	    sdata->u.mesh.mshcfg.auto_open_plinks &&
	    rssi_threshold_check(sta, sdata))
408 409
		mesh_plink_open(sta);

410
out:
411
	rcu_read_unlock();
412 413 414 415 416 417 418 419
}

static void mesh_plink_timer(unsigned long data)
{
	struct sta_info *sta;
	__le16 llid, plid, reason;
	struct ieee80211_sub_if_data *sdata;

420 421 422 423 424
	/*
	 * This STA is valid because sta_info_destroy() will
	 * del_timer_sync() this timer after having made sure
	 * it cannot be readded (by deleting the plink.)
	 */
425 426
	sta = (struct sta_info *) data;

427 428 429 430 431
	if (sta->sdata->local->quiescing) {
		sta->plink_timer_was_running = true;
		return;
	}

432
	spin_lock_bh(&sta->lock);
433 434
	if (sta->ignore_plink_timer) {
		sta->ignore_plink_timer = false;
435
		spin_unlock_bh(&sta->lock);
436 437
		return;
	}
438 439
	mpl_dbg("Mesh plink timer for %pM fired on state %d\n",
		sta->sta.addr, sta->plink_state);
440 441 442
	reason = 0;
	llid = sta->llid;
	plid = sta->plid;
443
	sdata = sta->sdata;
444 445

	switch (sta->plink_state) {
446 447
	case NL80211_PLINK_OPN_RCVD:
	case NL80211_PLINK_OPN_SNT:
448 449 450
		/* retry timer */
		if (sta->plink_retries < dot11MeshMaxRetries(sdata)) {
			u32 rand;
451 452 453
			mpl_dbg("Mesh plink for %pM (retry, timeout): %d %d\n",
				sta->sta.addr, sta->plink_retries,
				sta->plink_timeout);
454 455 456 457
			get_random_bytes(&rand, sizeof(u32));
			sta->plink_timeout = sta->plink_timeout +
					     rand % sta->plink_timeout;
			++sta->plink_retries;
458
			mod_plink_timer(sta, sta->plink_timeout);
459
			spin_unlock_bh(&sta->lock);
460 461
			mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN,
					    sta->sta.addr, llid, 0, 0);
462 463
			break;
		}
464
		reason = cpu_to_le16(WLAN_REASON_MESH_MAX_RETRIES);
465
		/* fall through on else */
466
	case NL80211_PLINK_CNF_RCVD:
467 468
		/* confirm timer */
		if (!reason)
469
			reason = cpu_to_le16(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
470
		sta->plink_state = NL80211_PLINK_HOLDING;
471
		mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
472
		spin_unlock_bh(&sta->lock);
473 474
		mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
				    sta->sta.addr, llid, plid, reason);
475
		break;
476
	case NL80211_PLINK_HOLDING:
477
		/* holding timer */
478
		del_timer(&sta->plink_timer);
479
		mesh_plink_fsm_restart(sta);
480
		spin_unlock_bh(&sta->lock);
481 482
		break;
	default:
483
		spin_unlock_bh(&sta->lock);
484 485 486 487
		break;
	}
}

488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503
#ifdef CONFIG_PM
void mesh_plink_quiesce(struct sta_info *sta)
{
	if (del_timer_sync(&sta->plink_timer))
		sta->plink_timer_was_running = true;
}

void mesh_plink_restart(struct sta_info *sta)
{
	if (sta->plink_timer_was_running) {
		add_timer(&sta->plink_timer);
		sta->plink_timer_was_running = false;
	}
}
#endif

504 505 506 507 508 509 510 511 512 513 514 515
static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout)
{
	sta->plink_timer.expires = jiffies + (HZ * timeout / 1000);
	sta->plink_timer.data = (unsigned long) sta;
	sta->plink_timer.function = mesh_plink_timer;
	sta->plink_timeout = timeout;
	add_timer(&sta->plink_timer);
}

int mesh_plink_open(struct sta_info *sta)
{
	__le16 llid;
516
	struct ieee80211_sub_if_data *sdata = sta->sdata;
517

J
Johannes Berg 已提交
518
	if (!test_sta_flag(sta, WLAN_STA_AUTH))
519 520
		return -EPERM;

521
	spin_lock_bh(&sta->lock);
522 523
	get_random_bytes(&llid, 2);
	sta->llid = llid;
524
	if (sta->plink_state != NL80211_PLINK_LISTEN) {
525
		spin_unlock_bh(&sta->lock);
526 527
		return -EBUSY;
	}
528
	sta->plink_state = NL80211_PLINK_OPN_SNT;
529
	mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));
530
	spin_unlock_bh(&sta->lock);
531 532
	mpl_dbg("Mesh plink: starting establishment with %pM\n",
		sta->sta.addr);
533

534
	return mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN,
535
				   sta->sta.addr, llid, 0, 0);
536 537 538 539
}

void mesh_plink_block(struct sta_info *sta)
{
540 541 542
	struct ieee80211_sub_if_data *sdata = sta->sdata;
	bool deactivated;

543
	spin_lock_bh(&sta->lock);
544
	deactivated = __mesh_plink_deactivate(sta);
545
	sta->plink_state = NL80211_PLINK_BLOCKED;
546
	spin_unlock_bh(&sta->lock);
547 548 549

	if (deactivated)
		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
550 551 552
}


553
void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt,
554 555 556 557 558
			 size_t len, struct ieee80211_rx_status *rx_status)
{
	struct ieee802_11_elems elems;
	struct sta_info *sta;
	enum plink_event event;
559
	enum ieee80211_self_protected_actioncode ftype;
560
	size_t baselen;
561
	bool matches_local = true;
562 563
	u8 ie_len;
	u8 *baseaddr;
564
	u32 changed = 0;
565
	__le16 plid, llid, reason;
566 567
#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
	static const char *mplstates[] = {
568 569 570 571 572 573 574
		[NL80211_PLINK_LISTEN] = "LISTEN",
		[NL80211_PLINK_OPN_SNT] = "OPN-SNT",
		[NL80211_PLINK_OPN_RCVD] = "OPN-RCVD",
		[NL80211_PLINK_CNF_RCVD] = "CNF_RCVD",
		[NL80211_PLINK_ESTAB] = "ESTAB",
		[NL80211_PLINK_HOLDING] = "HOLDING",
		[NL80211_PLINK_BLOCKED] = "BLOCKED"
575 576
	};
#endif
577

578 579 580 581
	/* need action_code, aux */
	if (len < IEEE80211_MIN_ACTION_SIZE + 3)
		return;

582 583 584 585 586
	if (is_multicast_ether_addr(mgmt->da)) {
		mpl_dbg("Mesh plink: ignore frame from multicast address");
		return;
	}

587 588 589
	baseaddr = mgmt->u.action.u.self_prot.variable;
	baselen = (u8 *) mgmt->u.action.u.self_prot.variable - (u8 *) mgmt;
	if (mgmt->u.action.u.self_prot.action_code ==
590
						WLAN_SP_MESH_PEERING_CONFIRM) {
591
		baseaddr += 4;
592
		baselen += 4;
593 594
	}
	ieee802_11_parse_elems(baseaddr, len - baselen, &elems);
595
	if (!elems.peering) {
596 597 598
		mpl_dbg("Mesh plink: missing necessary peer link ie\n");
		return;
	}
599 600
	if (elems.rsn_len &&
			sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) {
601 602 603
		mpl_dbg("Mesh plink: can't establish link with secure peer\n");
		return;
	}
604

605 606 607 608 609 610
	ftype = mgmt->u.action.u.self_prot.action_code;
	ie_len = elems.peering_len;
	if ((ftype == WLAN_SP_MESH_PEERING_OPEN && ie_len != 4) ||
	    (ftype == WLAN_SP_MESH_PEERING_CONFIRM && ie_len != 6) ||
	    (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len != 6
							&& ie_len != 8)) {
611 612
		mpl_dbg("Mesh plink: incorrect plink ie length %d %d\n",
		    ftype, ie_len);
613 614 615
		return;
	}

616 617
	if (ftype != WLAN_SP_MESH_PEERING_CLOSE &&
				(!elems.mesh_id || !elems.mesh_config)) {
618 619 620 621 622 623
		mpl_dbg("Mesh plink: missing necessary ie\n");
		return;
	}
	/* Note the lines below are correct, the llid in the frame is the plid
	 * from the point of view of this host.
	 */
624
	memcpy(&plid, PLINK_GET_LLID(elems.peering), 2);
625
	if (ftype == WLAN_SP_MESH_PEERING_CONFIRM ||
626 627
	    (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len == 8))
		memcpy(&llid, PLINK_GET_PLID(elems.peering), 2);
628

629 630
	rcu_read_lock();

631
	sta = sta_info_get(sdata, mgmt->sa);
632
	if (!sta && ftype != WLAN_SP_MESH_PEERING_OPEN) {
633
		mpl_dbg("Mesh plink: cls or cnf from unknown peer\n");
634
		rcu_read_unlock();
635 636 637
		return;
	}

638
	if (ftype == WLAN_SP_MESH_PEERING_OPEN &&
639
	    !rssi_threshold_check(sta, sdata)) {
640
		mpl_dbg("Mesh plink: %pM does not meet rssi threshold\n",
641
			mgmt->sa);
642 643 644 645
		rcu_read_unlock();
		return;
	}

J
Johannes Berg 已提交
646
	if (sta && !test_sta_flag(sta, WLAN_STA_AUTH)) {
647 648 649 650 651
		mpl_dbg("Mesh plink: Action frame from non-authed peer\n");
		rcu_read_unlock();
		return;
	}

652
	if (sta && sta->plink_state == NL80211_PLINK_BLOCKED) {
653
		rcu_read_unlock();
654 655 656 657 658
		return;
	}

	/* Now we will figure out the appropriate event... */
	event = PLINK_UNDEFINED;
659
	if (ftype != WLAN_SP_MESH_PEERING_CLOSE &&
660
	    !mesh_matches_local(sdata, &elems)) {
661
		matches_local = false;
662
		switch (ftype) {
663
		case WLAN_SP_MESH_PEERING_OPEN:
664 665
			event = OPN_RJCT;
			break;
666
		case WLAN_SP_MESH_PEERING_CONFIRM:
667 668
			event = CNF_RJCT;
			break;
669
		default:
670 671
			break;
		}
672 673 674 675
	}

	if (!sta && !matches_local) {
		rcu_read_unlock();
676
		reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
677
		llid = 0;
678 679
		mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
				    mgmt->sa, llid, plid, reason);
680
		return;
681
	} else if (!sta) {
682
		/* ftype == WLAN_SP_MESH_PEERING_OPEN */
683 684
		if (!mesh_plink_free_count(sdata)) {
			mpl_dbg("Mesh plink error: no more free plinks\n");
J
Johannes Berg 已提交
685 686 687
			rcu_read_unlock();
			return;
		}
688
		event = OPN_ACPT;
689
	} else if (matches_local) {
690
		switch (ftype) {
691
		case WLAN_SP_MESH_PEERING_OPEN:
692
			if (!mesh_plink_free_count(sdata) ||
693
			    (sta->plid && sta->plid != plid))
694 695 696 697
				event = OPN_IGNR;
			else
				event = OPN_ACPT;
			break;
698
		case WLAN_SP_MESH_PEERING_CONFIRM:
699
			if (!mesh_plink_free_count(sdata) ||
700
			    (sta->llid != llid || sta->plid != plid))
701 702 703 704
				event = CNF_IGNR;
			else
				event = CNF_ACPT;
			break;
705
		case WLAN_SP_MESH_PEERING_CLOSE:
706
			if (sta->plink_state == NL80211_PLINK_ESTAB)
707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725
				/* Do not check for llid or plid. This does not
				 * follow the standard but since multiple plinks
				 * per sta are not supported, it is necessary in
				 * order to avoid a livelock when MP A sees an
				 * establish peer link to MP B but MP B does not
				 * see it. This can be caused by a timeout in
				 * B's peer link establishment or B beign
				 * restarted.
				 */
				event = CLS_ACPT;
			else if (sta->plid != plid)
				event = CLS_IGNR;
			else if (ie_len == 7 && sta->llid != llid)
				event = CLS_IGNR;
			else
				event = CLS_ACPT;
			break;
		default:
			mpl_dbg("Mesh plink: unknown frame subtype\n");
726
			rcu_read_unlock();
727 728
			return;
		}
729 730 731 732
	}

	if (event == OPN_ACPT) {
		/* allocate sta entry if necessary and update info */
733
		sta = mesh_peer_init(sdata, mgmt->sa, &elems);
734 735 736 737 738
		if (!sta) {
			mpl_dbg("Mesh plink: failed to init peer!\n");
			rcu_read_unlock();
			return;
		}
739 740
	}

741 742
	mpl_dbg("Mesh plink (peer, state, llid, plid, event): %pM %s %d %d %d\n",
		mgmt->sa, mplstates[sta->plink_state],
743 744
		le16_to_cpu(sta->llid), le16_to_cpu(sta->plid),
		event);
745
	reason = 0;
746
	spin_lock_bh(&sta->lock);
747 748
	switch (sta->plink_state) {
		/* spin_unlock as soon as state is updated at each case */
749
	case NL80211_PLINK_LISTEN:
750 751 752
		switch (event) {
		case CLS_ACPT:
			mesh_plink_fsm_restart(sta);
753
			spin_unlock_bh(&sta->lock);
754 755
			break;
		case OPN_ACPT:
756
			sta->plink_state = NL80211_PLINK_OPN_RCVD;
757 758 759 760
			sta->plid = plid;
			get_random_bytes(&llid, 2);
			sta->llid = llid;
			mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));
761
			spin_unlock_bh(&sta->lock);
762 763 764 765 766 767
			mesh_plink_frame_tx(sdata,
					    WLAN_SP_MESH_PEERING_OPEN,
					    sta->sta.addr, llid, 0, 0);
			mesh_plink_frame_tx(sdata,
					    WLAN_SP_MESH_PEERING_CONFIRM,
					    sta->sta.addr, llid, plid, 0);
768 769
			break;
		default:
770
			spin_unlock_bh(&sta->lock);
771 772 773 774
			break;
		}
		break;

775
	case NL80211_PLINK_OPN_SNT:
776 777 778
		switch (event) {
		case OPN_RJCT:
		case CNF_RJCT:
779
			reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
780 781
		case CLS_ACPT:
			if (!reason)
782
				reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
783
			sta->reason = reason;
784
			sta->plink_state = NL80211_PLINK_HOLDING;
785 786 787 788 789
			if (!mod_plink_timer(sta,
					     dot11MeshHoldingTimeout(sdata)))
				sta->ignore_plink_timer = true;

			llid = sta->llid;
790
			spin_unlock_bh(&sta->lock);
791 792 793
			mesh_plink_frame_tx(sdata,
					    WLAN_SP_MESH_PEERING_CLOSE,
					    sta->sta.addr, llid, plid, reason);
794 795 796
			break;
		case OPN_ACPT:
			/* retry timer is left untouched */
797
			sta->plink_state = NL80211_PLINK_OPN_RCVD;
798 799
			sta->plid = plid;
			llid = sta->llid;
800
			spin_unlock_bh(&sta->lock);
801 802 803
			mesh_plink_frame_tx(sdata,
					    WLAN_SP_MESH_PEERING_CONFIRM,
					    sta->sta.addr, llid, plid, 0);
804 805
			break;
		case CNF_ACPT:
806
			sta->plink_state = NL80211_PLINK_CNF_RCVD;
807 808 809 810
			if (!mod_plink_timer(sta,
					     dot11MeshConfirmTimeout(sdata)))
				sta->ignore_plink_timer = true;

811
			spin_unlock_bh(&sta->lock);
812 813
			break;
		default:
814
			spin_unlock_bh(&sta->lock);
815 816 817 818
			break;
		}
		break;

819
	case NL80211_PLINK_OPN_RCVD:
820 821 822
		switch (event) {
		case OPN_RJCT:
		case CNF_RJCT:
823
			reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
824 825
		case CLS_ACPT:
			if (!reason)
826
				reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
827
			sta->reason = reason;
828
			sta->plink_state = NL80211_PLINK_HOLDING;
829 830 831 832 833
			if (!mod_plink_timer(sta,
					     dot11MeshHoldingTimeout(sdata)))
				sta->ignore_plink_timer = true;

			llid = sta->llid;
834
			spin_unlock_bh(&sta->lock);
835 836
			mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
					    sta->sta.addr, llid, plid, reason);
837 838 839
			break;
		case OPN_ACPT:
			llid = sta->llid;
840
			spin_unlock_bh(&sta->lock);
841 842 843
			mesh_plink_frame_tx(sdata,
					    WLAN_SP_MESH_PEERING_CONFIRM,
					    sta->sta.addr, llid, plid, 0);
844 845
			break;
		case CNF_ACPT:
846
			del_timer(&sta->plink_timer);
847
			sta->plink_state = NL80211_PLINK_ESTAB;
848
			spin_unlock_bh(&sta->lock);
849
			mesh_plink_inc_estab_count(sdata);
850 851
			changed |= mesh_set_ht_prot_mode(sdata);
			changed |= BSS_CHANGED_BEACON;
852 853
			mpl_dbg("Mesh plink with %pM ESTABLISHED\n",
				sta->sta.addr);
854 855
			break;
		default:
856
			spin_unlock_bh(&sta->lock);
857 858 859 860
			break;
		}
		break;

861
	case NL80211_PLINK_CNF_RCVD:
862 863 864
		switch (event) {
		case OPN_RJCT:
		case CNF_RJCT:
865
			reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
866 867
		case CLS_ACPT:
			if (!reason)
868
				reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
869
			sta->reason = reason;
870
			sta->plink_state = NL80211_PLINK_HOLDING;
871 872 873 874 875
			if (!mod_plink_timer(sta,
					     dot11MeshHoldingTimeout(sdata)))
				sta->ignore_plink_timer = true;

			llid = sta->llid;
876
			spin_unlock_bh(&sta->lock);
877 878 879
			mesh_plink_frame_tx(sdata,
					    WLAN_SP_MESH_PEERING_CLOSE,
					    sta->sta.addr, llid, plid, reason);
880
			break;
881
		case OPN_ACPT:
882
			del_timer(&sta->plink_timer);
883
			sta->plink_state = NL80211_PLINK_ESTAB;
884
			spin_unlock_bh(&sta->lock);
885
			mesh_plink_inc_estab_count(sdata);
886 887
			changed |= mesh_set_ht_prot_mode(sdata);
			changed |= BSS_CHANGED_BEACON;
888 889
			mpl_dbg("Mesh plink with %pM ESTABLISHED\n",
				sta->sta.addr);
890 891 892
			mesh_plink_frame_tx(sdata,
					    WLAN_SP_MESH_PEERING_CONFIRM,
					    sta->sta.addr, llid, plid, 0);
893 894
			break;
		default:
895
			spin_unlock_bh(&sta->lock);
896 897 898 899
			break;
		}
		break;

900
	case NL80211_PLINK_ESTAB:
901 902
		switch (event) {
		case CLS_ACPT:
903
			reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
904
			sta->reason = reason;
905
			__mesh_plink_deactivate(sta);
906
			sta->plink_state = NL80211_PLINK_HOLDING;
907
			llid = sta->llid;
908
			mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
909
			spin_unlock_bh(&sta->lock);
910 911
			changed |= mesh_set_ht_prot_mode(sdata);
			changed |= BSS_CHANGED_BEACON;
912 913
			mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
					    sta->sta.addr, llid, plid, reason);
914 915 916
			break;
		case OPN_ACPT:
			llid = sta->llid;
917
			spin_unlock_bh(&sta->lock);
918 919 920
			mesh_plink_frame_tx(sdata,
					    WLAN_SP_MESH_PEERING_CONFIRM,
					    sta->sta.addr, llid, plid, 0);
921 922
			break;
		default:
923
			spin_unlock_bh(&sta->lock);
924 925 926
			break;
		}
		break;
927
	case NL80211_PLINK_HOLDING:
928 929
		switch (event) {
		case CLS_ACPT:
930
			if (del_timer(&sta->plink_timer))
931 932
				sta->ignore_plink_timer = 1;
			mesh_plink_fsm_restart(sta);
933
			spin_unlock_bh(&sta->lock);
934 935 936 937 938 939 940
			break;
		case OPN_ACPT:
		case CNF_ACPT:
		case OPN_RJCT:
		case CNF_RJCT:
			llid = sta->llid;
			reason = sta->reason;
941
			spin_unlock_bh(&sta->lock);
942 943
			mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
					    sta->sta.addr, llid, plid, reason);
944 945
			break;
		default:
946
			spin_unlock_bh(&sta->lock);
947 948 949
		}
		break;
	default:
950
		/* should not get here, PLINK_BLOCKED is dealt with at the
D
Daniel Mack 已提交
951
		 * beginning of the function
952
		 */
953
		spin_unlock_bh(&sta->lock);
954 955
		break;
	}
956 957

	rcu_read_unlock();
958 959 960

	if (changed)
		ieee80211_bss_info_change_notify(sdata, changed);
961
}