ieee80211_mesh.c revision 246508
160894Smsmith/*-
260894Smsmith * Copyright (c) 2009 The FreeBSD Foundation
3123103Sps * All rights reserved.
4123103Sps *
560894Smsmith * This software was developed by Rui Paulo under sponsorship from the
660894Smsmith * FreeBSD Foundation.
760894Smsmith *
860894Smsmith * Redistribution and use in source and binary forms, with or without
960894Smsmith * modification, are permitted provided that the following conditions
1060894Smsmith * are met:
1160894Smsmith * 1. Redistributions of source code must retain the above copyright
1260894Smsmith *    notice, this list of conditions and the following disclaimer.
1360894Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1460894Smsmith *    notice, this list of conditions and the following disclaimer in the
1560894Smsmith *    documentation and/or other materials provided with the distribution.
1660894Smsmith *
1760894Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1860894Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1960894Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2060894Smsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2160894Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2260894Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2360894Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2460894Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2560894Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2660894Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2760894Smsmith * SUCH DAMAGE.
2860894Smsmith */
2960894Smsmith#include <sys/cdefs.h>
3060894Smsmith#ifdef __FreeBSD__
3160894Smsmith__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_mesh.c 246508 2013-02-07 21:24:20Z monthadar $");
3260894Smsmith#endif
3360894Smsmith
3460894Smsmith/*
3560894Smsmith * IEEE 802.11s Mesh Point (MBSS) support.
3660894Smsmith *
3760894Smsmith * Based on March 2009, D3.0 802.11s draft spec.
3860894Smsmith */
3960894Smsmith#include "opt_inet.h"
4060894Smsmith#include "opt_wlan.h"
4160894Smsmith
4260894Smsmith#include <sys/param.h>
4360894Smsmith#include <sys/systm.h>
4460894Smsmith#include <sys/mbuf.h>
4560894Smsmith#include <sys/malloc.h>
4660894Smsmith#include <sys/kernel.h>
4760894Smsmith
4860894Smsmith#include <sys/socket.h>
4960894Smsmith#include <sys/sockio.h>
5060894Smsmith#include <sys/endian.h>
5160894Smsmith#include <sys/errno.h>
5291790Smsmith#include <sys/proc.h>
5391790Smsmith#include <sys/sysctl.h>
5460894Smsmith
5560894Smsmith#include <net/if.h>
5660894Smsmith#include <net/if_media.h>
5760894Smsmith#include <net/if_llc.h>
5860894Smsmith#include <net/ethernet.h>
5960894Smsmith
6060894Smsmith#include <net80211/ieee80211_var.h>
6160894Smsmith#include <net80211/ieee80211_action.h>
6260894Smsmith#include <net80211/ieee80211_input.h>
6360894Smsmith#include <net80211/ieee80211_mesh.h>
6460894Smsmith
6560894Smsmithstatic void	mesh_rt_flush_invalid(struct ieee80211vap *);
6660894Smsmithstatic int	mesh_select_proto_path(struct ieee80211vap *, const char *);
6760894Smsmithstatic int	mesh_select_proto_metric(struct ieee80211vap *, const char *);
6860894Smsmithstatic void	mesh_vattach(struct ieee80211vap *);
6960894Smsmithstatic int	mesh_newstate(struct ieee80211vap *, enum ieee80211_state, int);
7060894Smsmithstatic void	mesh_rt_cleanup_cb(void *);
7160894Smsmithstatic void	mesh_gatemode_setup(struct ieee80211vap *);
7260894Smsmithstatic void	mesh_gatemode_cb(void *);
7360894Smsmithstatic void	mesh_linkchange(struct ieee80211_node *,
7460894Smsmith		    enum ieee80211_mesh_mlstate);
7560894Smsmithstatic void	mesh_checkid(void *, struct ieee80211_node *);
7660894Smsmithstatic uint32_t	mesh_generateid(struct ieee80211vap *);
7760894Smsmithstatic int	mesh_checkpseq(struct ieee80211vap *,
7860894Smsmith		    const uint8_t [IEEE80211_ADDR_LEN], uint32_t);
7960894Smsmithstatic struct ieee80211_node *
8060894Smsmith		mesh_find_txnode(struct ieee80211vap *,
8160894Smsmith		    const uint8_t [IEEE80211_ADDR_LEN]);
8260894Smsmithstatic void	mesh_forward(struct ieee80211vap *, struct mbuf *,
8367555Smsmith		    const struct ieee80211_meshcntl *);
8467555Smsmithstatic int	mesh_input(struct ieee80211_node *, struct mbuf *, int, int);
8567555Smsmithstatic void	mesh_recv_mgmt(struct ieee80211_node *, struct mbuf *, int,
8660894Smsmith		    int, int);
8760894Smsmithstatic void	mesh_recv_ctl(struct ieee80211_node *, struct mbuf *, int);
8860894Smsmithstatic void	mesh_peer_timeout_setup(struct ieee80211_node *);
8960894Smsmithstatic void	mesh_peer_timeout_backoff(struct ieee80211_node *);
9060894Smsmithstatic void	mesh_peer_timeout_cb(void *);
9160894Smsmithstatic __inline void
9260894Smsmith		mesh_peer_timeout_stop(struct ieee80211_node *);
9360894Smsmithstatic int	mesh_verify_meshid(struct ieee80211vap *, const uint8_t *);
9460894Smsmithstatic int	mesh_verify_meshconf(struct ieee80211vap *, const uint8_t *);
9560894Smsmithstatic int	mesh_verify_meshpeer(struct ieee80211vap *, uint8_t,
9660894Smsmith    		    const uint8_t *);
9760894Smsmithuint32_t	mesh_airtime_calc(struct ieee80211_node *);
9860894Smsmith
9960894Smsmith/*
10060894Smsmith * Timeout values come from the specification and are in milliseconds.
10160894Smsmith */
10260894Smsmithstatic SYSCTL_NODE(_net_wlan, OID_AUTO, mesh, CTLFLAG_RD, 0,
103129144Svkashyap    "IEEE 802.11s parameters");
10460894Smsmithstatic int	ieee80211_mesh_gateint = -1;
10560894SmsmithSYSCTL_PROC(_net_wlan_mesh, OID_AUTO, gateint, CTLTYPE_INT | CTLFLAG_RW,
10667684Smsmith    &ieee80211_mesh_gateint, 0, ieee80211_sysctl_msecs_ticks, "I",
10791790Smsmith    "mesh gate interval (ms)");
10891790Smsmithstatic int ieee80211_mesh_retrytimeout = -1;
10960894SmsmithSYSCTL_PROC(_net_wlan_mesh, OID_AUTO, retrytimeout, CTLTYPE_INT | CTLFLAG_RW,
11060894Smsmith    &ieee80211_mesh_retrytimeout, 0, ieee80211_sysctl_msecs_ticks, "I",
11167555Smsmith    "Retry timeout (msec)");
11267555Smsmithstatic int ieee80211_mesh_holdingtimeout = -1;
11367555SmsmithSYSCTL_PROC(_net_wlan_mesh, OID_AUTO, holdingtimeout, CTLTYPE_INT | CTLFLAG_RW,
11467555Smsmith    &ieee80211_mesh_holdingtimeout, 0, ieee80211_sysctl_msecs_ticks, "I",
11567555Smsmith    "Holding state timeout (msec)");
11667555Smsmithstatic int ieee80211_mesh_confirmtimeout = -1;
11767555SmsmithSYSCTL_PROC(_net_wlan_mesh, OID_AUTO, confirmtimeout, CTLTYPE_INT | CTLFLAG_RW,
11867555Smsmith    &ieee80211_mesh_confirmtimeout, 0, ieee80211_sysctl_msecs_ticks, "I",
11967555Smsmith    "Confirm state timeout (msec)");
12067555Smsmithstatic int ieee80211_mesh_backofftimeout = -1;
12167555SmsmithSYSCTL_PROC(_net_wlan_mesh, OID_AUTO, backofftimeout, CTLTYPE_INT | CTLFLAG_RW,
12267555Smsmith    &ieee80211_mesh_backofftimeout, 0, ieee80211_sysctl_msecs_ticks, "I",
12367555Smsmith    "Backoff timeout (msec). This is to throutles peering forever when "
124118508Sps    "not receving answer or is rejected by a neighbor");
12560894Smsmithstatic int ieee80211_mesh_maxretries = 2;
12660894SmsmithSYSCTL_INT(_net_wlan_mesh, OID_AUTO, maxretries, CTLTYPE_INT | CTLFLAG_RW,
12767555Smsmith    &ieee80211_mesh_maxretries, 0,
12867555Smsmith    "Maximum retries during peer link establishment");
12967555Smsmithstatic int ieee80211_mesh_maxholding = 2;
13060894SmsmithSYSCTL_INT(_net_wlan_mesh, OID_AUTO, maxholding, CTLTYPE_INT | CTLFLAG_RW,
13160894Smsmith    &ieee80211_mesh_maxholding, 0,
13267555Smsmith    "Maximum times we are allowed to transition to HOLDING state before "
13391790Smsmith    "backinoff during peer link establishment");
13460894Smsmith
13576340Smsmithstatic const uint8_t broadcastaddr[IEEE80211_ADDR_LEN] =
13676340Smsmith	{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
13776340Smsmith
13876340Smsmithstatic	ieee80211_recv_action_func mesh_recv_action_meshpeering_open;
13976340Smsmithstatic	ieee80211_recv_action_func mesh_recv_action_meshpeering_confirm;
14076340Smsmithstatic	ieee80211_recv_action_func mesh_recv_action_meshpeering_close;
14160894Smsmithstatic	ieee80211_recv_action_func mesh_recv_action_meshlmetric;
14260894Smsmithstatic	ieee80211_recv_action_func mesh_recv_action_meshgate;
14360894Smsmith
14460894Smsmithstatic	ieee80211_send_action_func mesh_send_action_meshpeering_open;
14567555Smsmithstatic	ieee80211_send_action_func mesh_send_action_meshpeering_confirm;
14667555Smsmithstatic	ieee80211_send_action_func mesh_send_action_meshpeering_close;
14760894Smsmithstatic	ieee80211_send_action_func mesh_send_action_meshlmetric;
14860894Smsmithstatic	ieee80211_send_action_func mesh_send_action_meshgate;
14991790Smsmith
15091790Smsmithstatic const struct ieee80211_mesh_proto_metric mesh_metric_airtime = {
15167555Smsmith	.mpm_descr	= "AIRTIME",
15260894Smsmith	.mpm_ie		= IEEE80211_MESHCONF_METRIC_AIRTIME,
15360894Smsmith	.mpm_metric	= mesh_airtime_calc,
15460894Smsmith};
15560894Smsmith
15660894Smsmithstatic struct ieee80211_mesh_proto_path		mesh_proto_paths[4];
15760894Smsmithstatic struct ieee80211_mesh_proto_metric	mesh_proto_metrics[4];
15867555Smsmith
15960894Smsmith#define	RT_ENTRY_LOCK(rt)	mtx_lock(&(rt)->rt_lock)
16060894Smsmith#define	RT_ENTRY_LOCK_ASSERT(rt) mtx_assert(&(rt)->rt_lock, MA_OWNED)
16160894Smsmith#define	RT_ENTRY_UNLOCK(rt)	mtx_unlock(&(rt)->rt_lock)
16260894Smsmith
16360894Smsmith#define	MESH_RT_LOCK(ms)	mtx_lock(&(ms)->ms_rt_lock)
16460894Smsmith#define	MESH_RT_LOCK_ASSERT(ms)	mtx_assert(&(ms)->ms_rt_lock, MA_OWNED)
165122168Sps#define	MESH_RT_UNLOCK(ms)	mtx_unlock(&(ms)->ms_rt_lock)
16660894Smsmith
16767555SmsmithMALLOC_DEFINE(M_80211_MESH_PREQ, "80211preq", "802.11 MESH Path Request frame");
16867555SmsmithMALLOC_DEFINE(M_80211_MESH_PREP, "80211prep", "802.11 MESH Path Reply frame");
16967555SmsmithMALLOC_DEFINE(M_80211_MESH_PERR, "80211perr", "802.11 MESH Path Error frame");
17067555Smsmith
17167555Smsmith/* The longer one of the lifetime should be stored as new lifetime */
17267555Smsmith#define MESH_ROUTE_LIFETIME_MAX(a, b)	(a > b ? a : b)
17367555Smsmith
17467555SmsmithMALLOC_DEFINE(M_80211_MESH_RT, "80211mesh_rt", "802.11s routing table");
17567555SmsmithMALLOC_DEFINE(M_80211_MESH_GT_RT, "80211mesh_gt", "802.11s known gates table");
17667555Smsmith
17767555Smsmith/*
178122168Sps * Helper functions to manipulate the Mesh routing table.
17967555Smsmith */
18060894Smsmith
18160894Smsmithstatic struct ieee80211_mesh_route *
18267555Smsmithmesh_rt_find_locked(struct ieee80211_mesh_state *ms,
18367555Smsmith    const uint8_t dest[IEEE80211_ADDR_LEN])
18467555Smsmith{
18567555Smsmith	struct ieee80211_mesh_route *rt;
18667555Smsmith
18767555Smsmith	MESH_RT_LOCK_ASSERT(ms);
18867555Smsmith
18967555Smsmith	TAILQ_FOREACH(rt, &ms->ms_routes, rt_next) {
19067555Smsmith		if (IEEE80211_ADDR_EQ(dest, rt->rt_dest))
19167555Smsmith			return rt;
19267555Smsmith	}
193122168Sps	return NULL;
19467555Smsmith}
19567555Smsmith
19667555Smsmithstatic struct ieee80211_mesh_route *
19767555Smsmithmesh_rt_add_locked(struct ieee80211vap *vap,
19867555Smsmith    const uint8_t dest[IEEE80211_ADDR_LEN])
19967555Smsmith{
20067555Smsmith	struct ieee80211_mesh_state *ms = vap->iv_mesh;
20167555Smsmith	struct ieee80211_mesh_route *rt;
20267555Smsmith
20367555Smsmith	KASSERT(!IEEE80211_ADDR_EQ(broadcastaddr, dest),
20467555Smsmith	    ("%s: adding broadcast to the routing table", __func__));
20567555Smsmith
20667555Smsmith	MESH_RT_LOCK_ASSERT(ms);
20767555Smsmith
20867555Smsmith	rt = malloc(ALIGN(sizeof(struct ieee80211_mesh_route)) +
20967555Smsmith	    ms->ms_ppath->mpp_privlen, M_80211_MESH_RT, M_NOWAIT | M_ZERO);
210122168Sps	if (rt != NULL) {
21167555Smsmith		rt->rt_vap = vap;
21267555Smsmith		IEEE80211_ADDR_COPY(rt->rt_dest, dest);
21367555Smsmith		rt->rt_priv = (void *)ALIGN(&rt[1]);
21467555Smsmith		mtx_init(&rt->rt_lock, "MBSS_RT", "802.11s route entry", MTX_DEF);
21567555Smsmith		callout_init(&rt->rt_discovery, CALLOUT_MPSAFE);
21667555Smsmith		rt->rt_updtime = ticks;	/* create time */
21767555Smsmith		TAILQ_INSERT_TAIL(&ms->ms_routes, rt, rt_next);
21867555Smsmith	}
21967555Smsmith	return rt;
22067555Smsmith}
22167555Smsmith
22267555Smsmithstruct ieee80211_mesh_route *
22367555Smsmithieee80211_mesh_rt_find(struct ieee80211vap *vap,
22467555Smsmith    const uint8_t dest[IEEE80211_ADDR_LEN])
22567555Smsmith{
22667555Smsmith	struct ieee80211_mesh_state *ms = vap->iv_mesh;
22767555Smsmith	struct ieee80211_mesh_route *rt;
228122168Sps
22967555Smsmith	MESH_RT_LOCK(ms);
23067555Smsmith	rt = mesh_rt_find_locked(ms, dest);
23167555Smsmith	MESH_RT_UNLOCK(ms);
23267555Smsmith	return rt;
23367555Smsmith}
23467555Smsmith
23567555Smsmithstruct ieee80211_mesh_route *
23667555Smsmithieee80211_mesh_rt_add(struct ieee80211vap *vap,
23767555Smsmith    const uint8_t dest[IEEE80211_ADDR_LEN])
23867555Smsmith{
23967555Smsmith	struct ieee80211_mesh_state *ms = vap->iv_mesh;
24067555Smsmith	struct ieee80211_mesh_route *rt;
241122168Sps
24267555Smsmith	KASSERT(ieee80211_mesh_rt_find(vap, dest) == NULL,
24367555Smsmith	    ("%s: duplicate entry in the routing table", __func__));
24467555Smsmith	KASSERT(!IEEE80211_ADDR_EQ(vap->iv_myaddr, dest),
24567555Smsmith	    ("%s: adding self to the routing table", __func__));
24667555Smsmith
24767555Smsmith	MESH_RT_LOCK(ms);
24867555Smsmith	rt = mesh_rt_add_locked(vap, dest);
24967555Smsmith	MESH_RT_UNLOCK(ms);
25067555Smsmith	return rt;
25167555Smsmith}
25267555Smsmith
25367555Smsmith/*
25467555Smsmith * Update the route lifetime and returns the updated lifetime.
255122168Sps * If new_lifetime is zero and route is timedout it will be invalidated.
25667555Smsmith * new_lifetime is in msec
25767555Smsmith */
25867555Smsmithint
25967555Smsmithieee80211_mesh_rt_update(struct ieee80211_mesh_route *rt, int new_lifetime)
26067555Smsmith{
26167555Smsmith	int timesince, now;
26267555Smsmith	uint32_t lifetime = 0;
26367555Smsmith
26467555Smsmith	KASSERT(rt != NULL, ("route is NULL"));
26567555Smsmith
26667555Smsmith	now = ticks;
26767555Smsmith	RT_ENTRY_LOCK(rt);
26867555Smsmith
26967555Smsmith	/* dont clobber a proxy entry gated by us */
27067555Smsmith	if (rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY && rt->rt_nhops == 0) {
27167555Smsmith		RT_ENTRY_UNLOCK(rt);
27267555Smsmith		return rt->rt_lifetime;
27367555Smsmith	}
274122168Sps
27567555Smsmith	timesince = ticks_to_msecs(now - rt->rt_updtime);
27667555Smsmith	rt->rt_updtime = now;
27767555Smsmith	if (timesince >= rt->rt_lifetime) {
27860894Smsmith		if (new_lifetime != 0) {
27960894Smsmith			rt->rt_lifetime = new_lifetime;
28060894Smsmith		}
28160894Smsmith		else {
28260894Smsmith			rt->rt_flags &= ~IEEE80211_MESHRT_FLAGS_VALID;
28360894Smsmith			rt->rt_lifetime = 0;
28460894Smsmith		}
285123103Sps	} else {
28691790Smsmith		/* update what is left of lifetime */
28791790Smsmith		rt->rt_lifetime = rt->rt_lifetime - timesince;
28891790Smsmith		rt->rt_lifetime  = MESH_ROUTE_LIFETIME_MAX(
28991790Smsmith			new_lifetime, rt->rt_lifetime);
29091790Smsmith	}
29191790Smsmith	lifetime = rt->rt_lifetime;
29291790Smsmith	RT_ENTRY_UNLOCK(rt);
29391790Smsmith
29491790Smsmith	return lifetime;
295122168Sps}
29691790Smsmith
29791790Smsmith/*
29891790Smsmith * Add a proxy route (as needed) for the specified destination.
29991790Smsmith */
30091790Smsmithvoid
30191790Smsmithieee80211_mesh_proxy_check(struct ieee80211vap *vap,
30291790Smsmith    const uint8_t dest[IEEE80211_ADDR_LEN])
30391790Smsmith{
30491790Smsmith	struct ieee80211_mesh_state *ms = vap->iv_mesh;
30591790Smsmith	struct ieee80211_mesh_route *rt;
30660894Smsmith
30767555Smsmith	MESH_RT_LOCK(ms);
30867555Smsmith	rt = mesh_rt_find_locked(ms, dest);
30967555Smsmith	if (rt == NULL) {
31067555Smsmith		rt = mesh_rt_add_locked(vap, dest);
31167555Smsmith		if (rt == NULL) {
31260894Smsmith			IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, dest,
313122168Sps			    "%s", "unable to add proxy entry");
31460894Smsmith			vap->iv_stats.is_mesh_rtaddfailed++;
31567555Smsmith		} else {
31667555Smsmith			IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, dest,
31760894Smsmith			    "%s", "add proxy entry");
31867555Smsmith			IEEE80211_ADDR_COPY(rt->rt_mesh_gate, vap->iv_myaddr);
31967555Smsmith			IEEE80211_ADDR_COPY(rt->rt_nexthop, vap->iv_myaddr);
32067555Smsmith			rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID
32167555Smsmith				     |  IEEE80211_MESHRT_FLAGS_PROXY;
32267555Smsmith		}
32367555Smsmith	} else if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) {
32491790Smsmith		KASSERT(rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY,
32567555Smsmith		    ("no proxy flag for poxy entry"));
32667555Smsmith		struct ieee80211com *ic = vap->iv_ic;
32767555Smsmith		/*
32860894Smsmith		 * Fix existing entry created by received frames from
32960894Smsmith		 * stations that have some memory of dest.  We also
33060894Smsmith		 * flush any frames held on the staging queue; delivering
33160894Smsmith		 * them is too much trouble right now.
33260894Smsmith		 */
33360894Smsmith		IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, dest,
33460894Smsmith		    "%s", "fix proxy entry");
33560894Smsmith		IEEE80211_ADDR_COPY(rt->rt_nexthop, vap->iv_myaddr);
33660894Smsmith		rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID
33760894Smsmith			     |  IEEE80211_MESHRT_FLAGS_PROXY;
33860894Smsmith		/* XXX belongs in hwmp */
33960894Smsmith		ieee80211_ageq_drain_node(&ic->ic_stageq,
34060894Smsmith		   (void *)(uintptr_t) ieee80211_mac_hash(ic, dest));
34167555Smsmith		/* XXX stat? */
34267555Smsmith	}
34367555Smsmith	MESH_RT_UNLOCK(ms);
34467555Smsmith}
34567555Smsmith
34667555Smsmithstatic __inline void
34767555Smsmithmesh_rt_del(struct ieee80211_mesh_state *ms, struct ieee80211_mesh_route *rt)
34867555Smsmith{
34967555Smsmith	TAILQ_REMOVE(&ms->ms_routes, rt, rt_next);
35067555Smsmith	/*
35167555Smsmith	 * Grab the lock before destroying it, to be sure no one else
35267555Smsmith	 * is holding the route.
35367555Smsmith	 */
35467555Smsmith	RT_ENTRY_LOCK(rt);
35567555Smsmith	callout_drain(&rt->rt_discovery);
35667555Smsmith	mtx_destroy(&rt->rt_lock);
35767555Smsmith	free(rt, M_80211_MESH_RT);
35867555Smsmith}
35967555Smsmith
36067555Smsmithvoid
36167555Smsmithieee80211_mesh_rt_del(struct ieee80211vap *vap,
36267555Smsmith    const uint8_t dest[IEEE80211_ADDR_LEN])
36367555Smsmith{
36467555Smsmith	struct ieee80211_mesh_state *ms = vap->iv_mesh;
36567555Smsmith	struct ieee80211_mesh_route *rt, *next;
36667555Smsmith
36767555Smsmith	MESH_RT_LOCK(ms);
36867555Smsmith	TAILQ_FOREACH_SAFE(rt, &ms->ms_routes, rt_next, next) {
36967555Smsmith		if (IEEE80211_ADDR_EQ(rt->rt_dest, dest)) {
37067555Smsmith			if (rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY) {
37167555Smsmith				ms->ms_ppath->mpp_senderror(vap, dest, rt,
37267555Smsmith				    IEEE80211_REASON_MESH_PERR_NO_PROXY);
37367555Smsmith			} else {
37467555Smsmith				ms->ms_ppath->mpp_senderror(vap, dest, rt,
37567555Smsmith				    IEEE80211_REASON_MESH_PERR_DEST_UNREACH);
37667555Smsmith			}
37767555Smsmith			mesh_rt_del(ms, rt);
37867555Smsmith			MESH_RT_UNLOCK(ms);
37967555Smsmith			return;
38067555Smsmith		}
38167555Smsmith	}
38267555Smsmith	MESH_RT_UNLOCK(ms);
38367555Smsmith}
38467555Smsmith
38567555Smsmithvoid
38667555Smsmithieee80211_mesh_rt_flush(struct ieee80211vap *vap)
38767555Smsmith{
38867555Smsmith	struct ieee80211_mesh_state *ms = vap->iv_mesh;
38967555Smsmith	struct ieee80211_mesh_route *rt, *next;
39067555Smsmith
39167555Smsmith	if (ms == NULL)
39267555Smsmith		return;
39367555Smsmith	MESH_RT_LOCK(ms);
39467555Smsmith	TAILQ_FOREACH_SAFE(rt, &ms->ms_routes, rt_next, next)
39567555Smsmith		mesh_rt_del(ms, rt);
39667555Smsmith	MESH_RT_UNLOCK(ms);
39767555Smsmith}
39867555Smsmith
39967555Smsmithvoid
40067555Smsmithieee80211_mesh_rt_flush_peer(struct ieee80211vap *vap,
40167555Smsmith    const uint8_t peer[IEEE80211_ADDR_LEN])
40267555Smsmith{
40367555Smsmith	struct ieee80211_mesh_state *ms = vap->iv_mesh;
40467555Smsmith	struct ieee80211_mesh_route *rt, *next;
40567555Smsmith
40667555Smsmith	MESH_RT_LOCK(ms);
40767555Smsmith	TAILQ_FOREACH_SAFE(rt, &ms->ms_routes, rt_next, next) {
40867555Smsmith		if (IEEE80211_ADDR_EQ(rt->rt_nexthop, peer))
40967555Smsmith			mesh_rt_del(ms, rt);
41067555Smsmith	}
41167555Smsmith	MESH_RT_UNLOCK(ms);
41267555Smsmith}
41367555Smsmith
41467555Smsmith/*
41567555Smsmith * Flush expired routing entries, i.e. those in invalid state for
41667555Smsmith * some time.
41767555Smsmith */
41867555Smsmithstatic void
41967555Smsmithmesh_rt_flush_invalid(struct ieee80211vap *vap)
42067555Smsmith{
42167555Smsmith	struct ieee80211_mesh_state *ms = vap->iv_mesh;
42267555Smsmith	struct ieee80211_mesh_route *rt, *next;
42367555Smsmith
42467555Smsmith	if (ms == NULL)
42567555Smsmith		return;
42667555Smsmith	MESH_RT_LOCK(ms);
42767555Smsmith	TAILQ_FOREACH_SAFE(rt, &ms->ms_routes, rt_next, next) {
42867555Smsmith		/* Discover paths will be deleted by their own callout */
42967555Smsmith		if (rt->rt_flags & IEEE80211_MESHRT_FLAGS_DISCOVER)
43067555Smsmith			continue;
43167555Smsmith		ieee80211_mesh_rt_update(rt, 0);
43267555Smsmith		if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0)
43367555Smsmith			mesh_rt_del(ms, rt);
43467555Smsmith	}
43567555Smsmith	MESH_RT_UNLOCK(ms);
43667555Smsmith}
43767555Smsmith
43867555Smsmith#define	N(a)	(sizeof(a) / sizeof(a[0]))
43967555Smsmithint
44067555Smsmithieee80211_mesh_register_proto_path(const struct ieee80211_mesh_proto_path *mpp)
44167555Smsmith{
44267555Smsmith	int i, firstempty = -1;
44367555Smsmith
44467555Smsmith	for (i = 0; i < N(mesh_proto_paths); i++) {
44560894Smsmith		if (strncmp(mpp->mpp_descr, mesh_proto_paths[i].mpp_descr,
44660894Smsmith		    IEEE80211_MESH_PROTO_DSZ) == 0)
44767555Smsmith			return EEXIST;
44867555Smsmith		if (!mesh_proto_paths[i].mpp_active && firstempty == -1)
44967555Smsmith			firstempty = i;
45067555Smsmith	}
45167555Smsmith	if (firstempty < 0)
45267555Smsmith		return ENOSPC;
45367555Smsmith	memcpy(&mesh_proto_paths[firstempty], mpp, sizeof(*mpp));
45467555Smsmith	mesh_proto_paths[firstempty].mpp_active = 1;
45567555Smsmith	return 0;
45667555Smsmith}
457122168Sps
45860894Smsmithint
45960894Smsmithieee80211_mesh_register_proto_metric(const struct
46060894Smsmith    ieee80211_mesh_proto_metric *mpm)
46167555Smsmith{
46267555Smsmith	int i, firstempty = -1;
46367555Smsmith
46467555Smsmith	for (i = 0; i < N(mesh_proto_metrics); i++) {
465122168Sps		if (strncmp(mpm->mpm_descr, mesh_proto_metrics[i].mpm_descr,
46660894Smsmith		    IEEE80211_MESH_PROTO_DSZ) == 0)
46760894Smsmith			return EEXIST;
46860894Smsmith		if (!mesh_proto_metrics[i].mpm_active && firstempty == -1)
46967555Smsmith			firstempty = i;
47067555Smsmith	}
47167555Smsmith	if (firstempty < 0)
47267555Smsmith		return ENOSPC;
47367555Smsmith	memcpy(&mesh_proto_metrics[firstempty], mpm, sizeof(*mpm));
47467555Smsmith	mesh_proto_metrics[firstempty].mpm_active = 1;
47567555Smsmith	return 0;
47667555Smsmith}
47767555Smsmith
47867555Smsmithstatic int
47967555Smsmithmesh_select_proto_path(struct ieee80211vap *vap, const char *name)
48067555Smsmith{
48167555Smsmith	struct ieee80211_mesh_state *ms = vap->iv_mesh;
48267555Smsmith	int i;
48367555Smsmith
48467555Smsmith	for (i = 0; i < N(mesh_proto_paths); i++) {
48567555Smsmith		if (strcasecmp(mesh_proto_paths[i].mpp_descr, name) == 0) {
486122168Sps			ms->ms_ppath = &mesh_proto_paths[i];
48760894Smsmith			return 0;
48867555Smsmith		}
48967555Smsmith	}
49067555Smsmith	return ENOENT;
49167555Smsmith}
49267555Smsmith
49367555Smsmithstatic int
494122168Spsmesh_select_proto_metric(struct ieee80211vap *vap, const char *name)
49591790Smsmith{
496	struct ieee80211_mesh_state *ms = vap->iv_mesh;
497	int i;
498
499	for (i = 0; i < N(mesh_proto_metrics); i++) {
500		if (strcasecmp(mesh_proto_metrics[i].mpm_descr, name) == 0) {
501			ms->ms_pmetric = &mesh_proto_metrics[i];
502			return 0;
503		}
504	}
505	return ENOENT;
506}
507#undef	N
508
509static void
510mesh_gatemode_setup(struct ieee80211vap *vap)
511{
512	struct ieee80211_mesh_state *ms = vap->iv_mesh;
513
514	/*
515	 * NB: When a mesh gate is running as a ROOT it shall
516	 * not send out periodic GANNs but instead mark the
517	 * mesh gate flag for the corresponding proactive PREQ
518	 * and RANN frames.
519	 */
520	if (ms->ms_flags & IEEE80211_MESHFLAGS_ROOT ||
521	    (ms->ms_flags & IEEE80211_MESHFLAGS_GATE) == 0) {
522		callout_drain(&ms->ms_gatetimer);
523		return ;
524	}
525	callout_reset(&ms->ms_gatetimer, ieee80211_mesh_gateint,
526	    mesh_gatemode_cb, vap);
527}
528
529static void
530mesh_gatemode_cb(void *arg)
531{
532	struct ieee80211vap *vap = (struct ieee80211vap *)arg;
533	struct ieee80211_mesh_state *ms = vap->iv_mesh;
534	struct ieee80211_meshgann_ie gann;
535
536	IEEE80211_NOTE(vap, IEEE80211_MSG_MESH, vap->iv_bss,
537	    "%s", "send broadcast GANN");
538
539	gann.gann_flags = 0; /* Reserved */
540	gann.gann_hopcount = 0;
541	gann.gann_ttl = ms->ms_ttl;
542	IEEE80211_ADDR_COPY(gann.gann_addr, vap->iv_myaddr);
543	gann.gann_seq = ms->ms_gateseq++;
544	gann.gann_interval = ieee80211_mesh_gateint;
545
546	ieee80211_send_action(vap->iv_bss, IEEE80211_ACTION_CAT_MESH,
547	    IEEE80211_ACTION_MESH_GANN, &gann);
548	mesh_gatemode_setup(vap);
549}
550
551static void
552ieee80211_mesh_init(void)
553{
554
555	memset(mesh_proto_paths, 0, sizeof(mesh_proto_paths));
556	memset(mesh_proto_metrics, 0, sizeof(mesh_proto_metrics));
557
558	/*
559	 * Setup mesh parameters that depends on the clock frequency.
560	 */
561	ieee80211_mesh_gateint = msecs_to_ticks(10000);
562	ieee80211_mesh_retrytimeout = msecs_to_ticks(40);
563	ieee80211_mesh_holdingtimeout = msecs_to_ticks(40);
564	ieee80211_mesh_confirmtimeout = msecs_to_ticks(40);
565	ieee80211_mesh_backofftimeout = msecs_to_ticks(5000);
566
567	/*
568	 * Register action frame handlers.
569	 */
570	ieee80211_recv_action_register(IEEE80211_ACTION_CAT_SELF_PROT,
571	    IEEE80211_ACTION_MESHPEERING_OPEN,
572	    mesh_recv_action_meshpeering_open);
573	ieee80211_recv_action_register(IEEE80211_ACTION_CAT_SELF_PROT,
574	    IEEE80211_ACTION_MESHPEERING_CONFIRM,
575	    mesh_recv_action_meshpeering_confirm);
576	ieee80211_recv_action_register(IEEE80211_ACTION_CAT_SELF_PROT,
577	    IEEE80211_ACTION_MESHPEERING_CLOSE,
578	    mesh_recv_action_meshpeering_close);
579	ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESH,
580	    IEEE80211_ACTION_MESH_LMETRIC, mesh_recv_action_meshlmetric);
581	ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESH,
582	    IEEE80211_ACTION_MESH_GANN, mesh_recv_action_meshgate);
583
584	ieee80211_send_action_register(IEEE80211_ACTION_CAT_SELF_PROT,
585	    IEEE80211_ACTION_MESHPEERING_OPEN,
586	    mesh_send_action_meshpeering_open);
587	ieee80211_send_action_register(IEEE80211_ACTION_CAT_SELF_PROT,
588	    IEEE80211_ACTION_MESHPEERING_CONFIRM,
589	    mesh_send_action_meshpeering_confirm);
590	ieee80211_send_action_register(IEEE80211_ACTION_CAT_SELF_PROT,
591	    IEEE80211_ACTION_MESHPEERING_CLOSE,
592	    mesh_send_action_meshpeering_close);
593	ieee80211_send_action_register(IEEE80211_ACTION_CAT_MESH,
594	    IEEE80211_ACTION_MESH_LMETRIC,
595	    mesh_send_action_meshlmetric);
596	ieee80211_send_action_register(IEEE80211_ACTION_CAT_MESH,
597	    IEEE80211_ACTION_MESH_GANN,
598	    mesh_send_action_meshgate);
599
600	/*
601	 * Register Airtime Link Metric.
602	 */
603	ieee80211_mesh_register_proto_metric(&mesh_metric_airtime);
604
605}
606SYSINIT(wlan_mesh, SI_SUB_DRIVERS, SI_ORDER_FIRST, ieee80211_mesh_init, NULL);
607
608void
609ieee80211_mesh_attach(struct ieee80211com *ic)
610{
611	ic->ic_vattach[IEEE80211_M_MBSS] = mesh_vattach;
612}
613
614void
615ieee80211_mesh_detach(struct ieee80211com *ic)
616{
617}
618
619static void
620mesh_vdetach_peers(void *arg, struct ieee80211_node *ni)
621{
622	struct ieee80211com *ic = ni->ni_ic;
623	uint16_t args[3];
624
625	if (ni->ni_mlstate == IEEE80211_NODE_MESH_ESTABLISHED) {
626		args[0] = ni->ni_mlpid;
627		args[1] = ni->ni_mllid;
628		args[2] = IEEE80211_REASON_PEER_LINK_CANCELED;
629		ieee80211_send_action(ni,
630		    IEEE80211_ACTION_CAT_SELF_PROT,
631		    IEEE80211_ACTION_MESHPEERING_CLOSE,
632		    args);
633	}
634	callout_drain(&ni->ni_mltimer);
635	/* XXX belongs in hwmp */
636	ieee80211_ageq_drain_node(&ic->ic_stageq,
637	   (void *)(uintptr_t) ieee80211_mac_hash(ic, ni->ni_macaddr));
638}
639
640static void
641mesh_vdetach(struct ieee80211vap *vap)
642{
643	struct ieee80211_mesh_state *ms = vap->iv_mesh;
644
645	callout_drain(&ms->ms_cleantimer);
646	ieee80211_iterate_nodes(&vap->iv_ic->ic_sta, mesh_vdetach_peers,
647	    NULL);
648	ieee80211_mesh_rt_flush(vap);
649	mtx_destroy(&ms->ms_rt_lock);
650	ms->ms_ppath->mpp_vdetach(vap);
651	free(vap->iv_mesh, M_80211_VAP);
652	vap->iv_mesh = NULL;
653}
654
655static void
656mesh_vattach(struct ieee80211vap *vap)
657{
658	struct ieee80211_mesh_state *ms;
659	vap->iv_newstate = mesh_newstate;
660	vap->iv_input = mesh_input;
661	vap->iv_opdetach = mesh_vdetach;
662	vap->iv_recv_mgmt = mesh_recv_mgmt;
663	vap->iv_recv_ctl = mesh_recv_ctl;
664	ms = malloc(sizeof(struct ieee80211_mesh_state), M_80211_VAP,
665	    M_NOWAIT | M_ZERO);
666	if (ms == NULL) {
667		printf("%s: couldn't alloc MBSS state\n", __func__);
668		return;
669	}
670	vap->iv_mesh = ms;
671	ms->ms_seq = 0;
672	ms->ms_flags = (IEEE80211_MESHFLAGS_AP | IEEE80211_MESHFLAGS_FWD);
673	ms->ms_ttl = IEEE80211_MESH_DEFAULT_TTL;
674	TAILQ_INIT(&ms->ms_known_gates);
675	TAILQ_INIT(&ms->ms_routes);
676	mtx_init(&ms->ms_rt_lock, "MBSS", "802.11s routing table", MTX_DEF);
677	callout_init(&ms->ms_cleantimer, CALLOUT_MPSAFE);
678	callout_init(&ms->ms_gatetimer, CALLOUT_MPSAFE);
679	ms->ms_gateseq = 0;
680	mesh_select_proto_metric(vap, "AIRTIME");
681	KASSERT(ms->ms_pmetric, ("ms_pmetric == NULL"));
682	mesh_select_proto_path(vap, "HWMP");
683	KASSERT(ms->ms_ppath, ("ms_ppath == NULL"));
684	ms->ms_ppath->mpp_vattach(vap);
685}
686
687/*
688 * IEEE80211_M_MBSS vap state machine handler.
689 */
690static int
691mesh_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
692{
693	struct ieee80211_mesh_state *ms = vap->iv_mesh;
694	struct ieee80211com *ic = vap->iv_ic;
695	struct ieee80211_node *ni;
696	enum ieee80211_state ostate;
697
698	IEEE80211_LOCK_ASSERT(ic);
699
700	ostate = vap->iv_state;
701	IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE, "%s: %s -> %s (%d)\n",
702	    __func__, ieee80211_state_name[ostate],
703	    ieee80211_state_name[nstate], arg);
704	vap->iv_state = nstate;		/* state transition */
705	if (ostate != IEEE80211_S_SCAN)
706		ieee80211_cancel_scan(vap);	/* background scan */
707	ni = vap->iv_bss;			/* NB: no reference held */
708	if (nstate != IEEE80211_S_RUN && ostate == IEEE80211_S_RUN) {
709		callout_drain(&ms->ms_cleantimer);
710		callout_drain(&ms->ms_gatetimer);
711	}
712	switch (nstate) {
713	case IEEE80211_S_INIT:
714		switch (ostate) {
715		case IEEE80211_S_SCAN:
716			ieee80211_cancel_scan(vap);
717			break;
718		case IEEE80211_S_CAC:
719			ieee80211_dfs_cac_stop(vap);
720			break;
721		case IEEE80211_S_RUN:
722			ieee80211_iterate_nodes(&ic->ic_sta,
723			    mesh_vdetach_peers, NULL);
724			break;
725		default:
726			break;
727		}
728		if (ostate != IEEE80211_S_INIT) {
729			/* NB: optimize INIT -> INIT case */
730			ieee80211_reset_bss(vap);
731			ieee80211_mesh_rt_flush(vap);
732		}
733		break;
734	case IEEE80211_S_SCAN:
735		switch (ostate) {
736		case IEEE80211_S_INIT:
737			if (vap->iv_des_chan != IEEE80211_CHAN_ANYC &&
738			    !IEEE80211_IS_CHAN_RADAR(vap->iv_des_chan) &&
739			    ms->ms_idlen != 0) {
740				/*
741				 * Already have a channel and a mesh ID; bypass
742				 * the scan and startup immediately.
743				 */
744				ieee80211_create_ibss(vap, vap->iv_des_chan);
745				break;
746			}
747			/*
748			 * Initiate a scan.  We can come here as a result
749			 * of an IEEE80211_IOC_SCAN_REQ too in which case
750			 * the vap will be marked with IEEE80211_FEXT_SCANREQ
751			 * and the scan request parameters will be present
752			 * in iv_scanreq.  Otherwise we do the default.
753			*/
754			if (vap->iv_flags_ext & IEEE80211_FEXT_SCANREQ) {
755				ieee80211_check_scan(vap,
756				    vap->iv_scanreq_flags,
757				    vap->iv_scanreq_duration,
758				    vap->iv_scanreq_mindwell,
759				    vap->iv_scanreq_maxdwell,
760				    vap->iv_scanreq_nssid, vap->iv_scanreq_ssid);
761				vap->iv_flags_ext &= ~IEEE80211_FEXT_SCANREQ;
762			} else
763				ieee80211_check_scan_current(vap);
764			break;
765		default:
766			break;
767		}
768		break;
769	case IEEE80211_S_CAC:
770		/*
771		 * Start CAC on a DFS channel.  We come here when starting
772		 * a bss on a DFS channel (see ieee80211_create_ibss).
773		 */
774		ieee80211_dfs_cac_start(vap);
775		break;
776	case IEEE80211_S_RUN:
777		switch (ostate) {
778		case IEEE80211_S_INIT:
779			/*
780			 * Already have a channel; bypass the
781			 * scan and startup immediately.
782			 * Note that ieee80211_create_ibss will call
783			 * back to do a RUN->RUN state change.
784			 */
785			ieee80211_create_ibss(vap,
786			    ieee80211_ht_adjust_channel(ic,
787				ic->ic_curchan, vap->iv_flags_ht));
788			/* NB: iv_bss is changed on return */
789			break;
790		case IEEE80211_S_CAC:
791			/*
792			 * NB: This is the normal state change when CAC
793			 * expires and no radar was detected; no need to
794			 * clear the CAC timer as it's already expired.
795			 */
796			/* fall thru... */
797		case IEEE80211_S_CSA:
798#if 0
799			/*
800			 * Shorten inactivity timer of associated stations
801			 * to weed out sta's that don't follow a CSA.
802			 */
803			ieee80211_iterate_nodes(&ic->ic_sta, sta_csa, vap);
804#endif
805			/*
806			 * Update bss node channel to reflect where
807			 * we landed after CSA.
808			 */
809			ieee80211_node_set_chan(vap->iv_bss,
810			    ieee80211_ht_adjust_channel(ic, ic->ic_curchan,
811				ieee80211_htchanflags(vap->iv_bss->ni_chan)));
812			/* XXX bypass debug msgs */
813			break;
814		case IEEE80211_S_SCAN:
815		case IEEE80211_S_RUN:
816#ifdef IEEE80211_DEBUG
817			if (ieee80211_msg_debug(vap)) {
818				struct ieee80211_node *ni = vap->iv_bss;
819				ieee80211_note(vap,
820				    "synchronized with %s meshid ",
821				    ether_sprintf(ni->ni_meshid));
822				ieee80211_print_essid(ni->ni_meshid,
823				    ni->ni_meshidlen);
824				/* XXX MCS/HT */
825				printf(" channel %d\n",
826				    ieee80211_chan2ieee(ic, ic->ic_curchan));
827			}
828#endif
829			break;
830		default:
831			break;
832		}
833		ieee80211_node_authorize(vap->iv_bss);
834		callout_reset(&ms->ms_cleantimer, ms->ms_ppath->mpp_inact,
835                    mesh_rt_cleanup_cb, vap);
836		mesh_gatemode_setup(vap);
837		break;
838	default:
839		break;
840	}
841	/* NB: ostate not nstate */
842	ms->ms_ppath->mpp_newstate(vap, ostate, arg);
843	return 0;
844}
845
846static void
847mesh_rt_cleanup_cb(void *arg)
848{
849	struct ieee80211vap *vap = arg;
850	struct ieee80211_mesh_state *ms = vap->iv_mesh;
851
852	mesh_rt_flush_invalid(vap);
853	callout_reset(&ms->ms_cleantimer, ms->ms_ppath->mpp_inact,
854	    mesh_rt_cleanup_cb, vap);
855}
856
857
858/*
859 * Helper function to note the Mesh Peer Link FSM change.
860 */
861static void
862mesh_linkchange(struct ieee80211_node *ni, enum ieee80211_mesh_mlstate state)
863{
864	struct ieee80211vap *vap = ni->ni_vap;
865	struct ieee80211_mesh_state *ms = vap->iv_mesh;
866#ifdef IEEE80211_DEBUG
867	static const char *meshlinkstates[] = {
868		[IEEE80211_NODE_MESH_IDLE]		= "IDLE",
869		[IEEE80211_NODE_MESH_OPENSNT]		= "OPEN SENT",
870		[IEEE80211_NODE_MESH_OPENRCV]		= "OPEN RECEIVED",
871		[IEEE80211_NODE_MESH_CONFIRMRCV]	= "CONFIRM RECEIVED",
872		[IEEE80211_NODE_MESH_ESTABLISHED]	= "ESTABLISHED",
873		[IEEE80211_NODE_MESH_HOLDING]		= "HOLDING"
874	};
875#endif
876	IEEE80211_NOTE(vap, IEEE80211_MSG_MESH,
877	    ni, "peer link: %s -> %s",
878	    meshlinkstates[ni->ni_mlstate], meshlinkstates[state]);
879
880	/* track neighbor count */
881	if (state == IEEE80211_NODE_MESH_ESTABLISHED &&
882	    ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED) {
883		KASSERT(ms->ms_neighbors < 65535, ("neighbor count overflow"));
884		ms->ms_neighbors++;
885		ieee80211_beacon_notify(vap, IEEE80211_BEACON_MESHCONF);
886	} else if (ni->ni_mlstate == IEEE80211_NODE_MESH_ESTABLISHED &&
887	    state != IEEE80211_NODE_MESH_ESTABLISHED) {
888		KASSERT(ms->ms_neighbors > 0, ("neighbor count 0"));
889		ms->ms_neighbors--;
890		ieee80211_beacon_notify(vap, IEEE80211_BEACON_MESHCONF);
891	}
892	ni->ni_mlstate = state;
893	switch (state) {
894	case IEEE80211_NODE_MESH_HOLDING:
895		ms->ms_ppath->mpp_peerdown(ni);
896		break;
897	case IEEE80211_NODE_MESH_ESTABLISHED:
898		ieee80211_mesh_discover(vap, ni->ni_macaddr, NULL);
899		break;
900	default:
901		break;
902	}
903}
904
905/*
906 * Helper function to generate a unique local ID required for mesh
907 * peer establishment.
908 */
909static void
910mesh_checkid(void *arg, struct ieee80211_node *ni)
911{
912	uint16_t *r = arg;
913
914	if (*r == ni->ni_mllid)
915		*(uint16_t *)arg = 0;
916}
917
918static uint32_t
919mesh_generateid(struct ieee80211vap *vap)
920{
921	int maxiter = 4;
922	uint16_t r;
923
924	do {
925		get_random_bytes(&r, 2);
926		ieee80211_iterate_nodes(&vap->iv_ic->ic_sta, mesh_checkid, &r);
927		maxiter--;
928	} while (r == 0 && maxiter > 0);
929	return r;
930}
931
932/*
933 * Verifies if we already received this packet by checking its
934 * sequence number.
935 * Returns 0 if the frame is to be accepted, 1 otherwise.
936 */
937static int
938mesh_checkpseq(struct ieee80211vap *vap,
939    const uint8_t source[IEEE80211_ADDR_LEN], uint32_t seq)
940{
941	struct ieee80211_mesh_route *rt;
942
943	rt = ieee80211_mesh_rt_find(vap, source);
944	if (rt == NULL) {
945		rt = ieee80211_mesh_rt_add(vap, source);
946		if (rt == NULL) {
947			IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, source,
948			    "%s", "add mcast route failed");
949			vap->iv_stats.is_mesh_rtaddfailed++;
950			return 1;
951		}
952		IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, source,
953		    "add mcast route, mesh seqno %d", seq);
954		rt->rt_lastmseq = seq;
955		return 0;
956	}
957	if (IEEE80211_MESH_SEQ_GEQ(rt->rt_lastmseq, seq)) {
958		return 1;
959	} else {
960		rt->rt_lastmseq = seq;
961		return 0;
962	}
963}
964
965/*
966 * Iterate the routing table and locate the next hop.
967 */
968static struct ieee80211_node *
969mesh_find_txnode(struct ieee80211vap *vap,
970    const uint8_t dest[IEEE80211_ADDR_LEN])
971{
972	struct ieee80211_mesh_route *rt;
973
974	rt = ieee80211_mesh_rt_find(vap, dest);
975	if (rt == NULL)
976		return NULL;
977	if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0 ||
978	    (rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY)) {
979		IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, dest,
980		    "%s: !valid or proxy, flags 0x%x", __func__, rt->rt_flags);
981		/* XXX stat */
982		return NULL;
983	}
984	return ieee80211_find_txnode(vap, rt->rt_nexthop);
985}
986
987/*
988 * Forward the specified frame.
989 * Decrement the TTL and set TA to our MAC address.
990 */
991static void
992mesh_forward(struct ieee80211vap *vap, struct mbuf *m,
993    const struct ieee80211_meshcntl *mc)
994{
995	struct ieee80211com *ic = vap->iv_ic;
996	struct ieee80211_mesh_state *ms = vap->iv_mesh;
997	struct ifnet *ifp = vap->iv_ifp;
998	struct ifnet *parent = ic->ic_ifp;
999	const struct ieee80211_frame *wh =
1000	    mtod(m, const struct ieee80211_frame *);
1001	struct mbuf *mcopy;
1002	struct ieee80211_meshcntl *mccopy;
1003	struct ieee80211_frame *whcopy;
1004	struct ieee80211_node *ni;
1005	int err;
1006
1007	/*
1008	 * mesh ttl of 1 means we are the last one receving it,
1009	 * according to amendment we decrement and then check if
1010	 * 0, if so we dont forward.
1011	 */
1012	if (mc->mc_ttl < 1) {
1013		IEEE80211_NOTE_FRAME(vap, IEEE80211_MSG_MESH, wh,
1014		    "%s", "frame not fwd'd, ttl 1");
1015		vap->iv_stats.is_mesh_fwd_ttl++;
1016		return;
1017	}
1018	if (!(ms->ms_flags & IEEE80211_MESHFLAGS_FWD)) {
1019		IEEE80211_NOTE_FRAME(vap, IEEE80211_MSG_MESH, wh,
1020		    "%s", "frame not fwd'd, fwding disabled");
1021		vap->iv_stats.is_mesh_fwd_disabled++;
1022		return;
1023	}
1024	mcopy = m_dup(m, M_NOWAIT);
1025	if (mcopy == NULL) {
1026		IEEE80211_NOTE_FRAME(vap, IEEE80211_MSG_MESH, wh,
1027		    "%s", "frame not fwd'd, cannot dup");
1028		vap->iv_stats.is_mesh_fwd_nobuf++;
1029		ifp->if_oerrors++;
1030		return;
1031	}
1032	mcopy = m_pullup(mcopy, ieee80211_hdrspace(ic, wh) +
1033	    sizeof(struct ieee80211_meshcntl));
1034	if (mcopy == NULL) {
1035		IEEE80211_NOTE_FRAME(vap, IEEE80211_MSG_MESH, wh,
1036		    "%s", "frame not fwd'd, too short");
1037		vap->iv_stats.is_mesh_fwd_tooshort++;
1038		ifp->if_oerrors++;
1039		m_freem(mcopy);
1040		return;
1041	}
1042	whcopy = mtod(mcopy, struct ieee80211_frame *);
1043	mccopy = (struct ieee80211_meshcntl *)
1044	    (mtod(mcopy, uint8_t *) + ieee80211_hdrspace(ic, wh));
1045	/* XXX clear other bits? */
1046	whcopy->i_fc[1] &= ~IEEE80211_FC1_RETRY;
1047	IEEE80211_ADDR_COPY(whcopy->i_addr2, vap->iv_myaddr);
1048	if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
1049		ni = ieee80211_ref_node(vap->iv_bss);
1050		mcopy->m_flags |= M_MCAST;
1051	} else {
1052		ni = mesh_find_txnode(vap, whcopy->i_addr3);
1053		if (ni == NULL) {
1054			/*
1055			 * [Optional] any of the following three actions:
1056			 * o silently discard
1057			 * o trigger a path discovery
1058			 * o inform TA that meshDA is unknown.
1059			 */
1060			IEEE80211_NOTE_FRAME(vap, IEEE80211_MSG_MESH, wh,
1061			    "%s", "frame not fwd'd, no path");
1062			ms->ms_ppath->mpp_senderror(vap, whcopy->i_addr3, NULL,
1063			    IEEE80211_REASON_MESH_PERR_NO_FI);
1064			vap->iv_stats.is_mesh_fwd_nopath++;
1065			m_freem(mcopy);
1066			return;
1067		}
1068		IEEE80211_ADDR_COPY(whcopy->i_addr1, ni->ni_macaddr);
1069	}
1070	KASSERT(mccopy->mc_ttl > 0, ("%s called with wrong ttl", __func__));
1071	mccopy->mc_ttl--;
1072
1073	/* XXX calculate priority so drivers can find the tx queue */
1074	M_WME_SETAC(mcopy, WME_AC_BE);
1075
1076	/* XXX do we know m_nextpkt is NULL? */
1077	mcopy->m_pkthdr.rcvif = (void *) ni;
1078	err = parent->if_transmit(parent, mcopy);
1079	if (err != 0) {
1080		/* NB: IFQ_HANDOFF reclaims mbuf */
1081		ieee80211_free_node(ni);
1082	} else {
1083		ifp->if_opackets++;
1084	}
1085}
1086
1087static struct mbuf *
1088mesh_decap(struct ieee80211vap *vap, struct mbuf *m, int hdrlen, int meshdrlen)
1089{
1090#define	WHDIR(wh)	((wh)->i_fc[1] & IEEE80211_FC1_DIR_MASK)
1091#define	MC01(mc)	((const struct ieee80211_meshcntl_ae01 *)mc)
1092	uint8_t b[sizeof(struct ieee80211_qosframe_addr4) +
1093		  sizeof(struct ieee80211_meshcntl_ae10)];
1094	const struct ieee80211_qosframe_addr4 *wh;
1095	const struct ieee80211_meshcntl_ae10 *mc;
1096	struct ether_header *eh;
1097	struct llc *llc;
1098	int ae;
1099
1100	if (m->m_len < hdrlen + sizeof(*llc) &&
1101	    (m = m_pullup(m, hdrlen + sizeof(*llc))) == NULL) {
1102		IEEE80211_DPRINTF(vap, IEEE80211_MSG_ANY,
1103		    "discard data frame: %s", "m_pullup failed");
1104		vap->iv_stats.is_rx_tooshort++;
1105		return NULL;
1106	}
1107	memcpy(b, mtod(m, caddr_t), hdrlen);
1108	wh = (const struct ieee80211_qosframe_addr4 *)&b[0];
1109	mc = (const struct ieee80211_meshcntl_ae10 *)&b[hdrlen - meshdrlen];
1110	KASSERT(WHDIR(wh) == IEEE80211_FC1_DIR_FROMDS ||
1111		WHDIR(wh) == IEEE80211_FC1_DIR_DSTODS,
1112	    ("bogus dir, fc 0x%x:0x%x", wh->i_fc[0], wh->i_fc[1]));
1113
1114	llc = (struct llc *)(mtod(m, caddr_t) + hdrlen);
1115	if (llc->llc_dsap == LLC_SNAP_LSAP && llc->llc_ssap == LLC_SNAP_LSAP &&
1116	    llc->llc_control == LLC_UI && llc->llc_snap.org_code[0] == 0 &&
1117	    llc->llc_snap.org_code[1] == 0 && llc->llc_snap.org_code[2] == 0 &&
1118	    /* NB: preserve AppleTalk frames that have a native SNAP hdr */
1119	    !(llc->llc_snap.ether_type == htons(ETHERTYPE_AARP) ||
1120	      llc->llc_snap.ether_type == htons(ETHERTYPE_IPX))) {
1121		m_adj(m, hdrlen + sizeof(struct llc) - sizeof(*eh));
1122		llc = NULL;
1123	} else {
1124		m_adj(m, hdrlen - sizeof(*eh));
1125	}
1126	eh = mtod(m, struct ether_header *);
1127	ae = mc->mc_flags & IEEE80211_MESH_AE_MASK;
1128	if (WHDIR(wh) == IEEE80211_FC1_DIR_FROMDS) {
1129		IEEE80211_ADDR_COPY(eh->ether_dhost, wh->i_addr1);
1130		if (ae == IEEE80211_MESH_AE_00) {
1131			IEEE80211_ADDR_COPY(eh->ether_shost, wh->i_addr3);
1132		} else if (ae == IEEE80211_MESH_AE_01) {
1133			IEEE80211_ADDR_COPY(eh->ether_shost,
1134			    MC01(mc)->mc_addr4);
1135		} else {
1136			IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
1137			    (const struct ieee80211_frame *)wh, NULL,
1138			    "bad AE %d", ae);
1139			vap->iv_stats.is_mesh_badae++;
1140			m_freem(m);
1141			return NULL;
1142		}
1143	} else {
1144		if (ae == IEEE80211_MESH_AE_00) {
1145			IEEE80211_ADDR_COPY(eh->ether_dhost, wh->i_addr3);
1146			IEEE80211_ADDR_COPY(eh->ether_shost, wh->i_addr4);
1147		} else if (ae == IEEE80211_MESH_AE_10) {
1148			IEEE80211_ADDR_COPY(eh->ether_dhost, mc->mc_addr5);
1149			IEEE80211_ADDR_COPY(eh->ether_shost, mc->mc_addr6);
1150		} else {
1151			IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
1152			    (const struct ieee80211_frame *)wh, NULL,
1153			    "bad AE %d", ae);
1154			vap->iv_stats.is_mesh_badae++;
1155			m_freem(m);
1156			return NULL;
1157		}
1158	}
1159#ifdef ALIGNED_POINTER
1160	if (!ALIGNED_POINTER(mtod(m, caddr_t) + sizeof(*eh), uint32_t)) {
1161		m = ieee80211_realign(vap, m, sizeof(*eh));
1162		if (m == NULL)
1163			return NULL;
1164	}
1165#endif /* ALIGNED_POINTER */
1166	if (llc != NULL) {
1167		eh = mtod(m, struct ether_header *);
1168		eh->ether_type = htons(m->m_pkthdr.len - sizeof(*eh));
1169	}
1170	return m;
1171#undef	WDIR
1172#undef	MC01
1173}
1174
1175/*
1176 * Return non-zero if the unicast mesh data frame should be processed
1177 * locally.  Frames that are not proxy'd have our address, otherwise
1178 * we need to consult the routing table to look for a proxy entry.
1179 */
1180static __inline int
1181mesh_isucastforme(struct ieee80211vap *vap, const struct ieee80211_frame *wh,
1182    const struct ieee80211_meshcntl *mc)
1183{
1184	int ae = mc->mc_flags & 3;
1185
1186	KASSERT((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS,
1187	    ("bad dir 0x%x:0x%x", wh->i_fc[0], wh->i_fc[1]));
1188	KASSERT(ae == IEEE80211_MESH_AE_00 || ae == IEEE80211_MESH_AE_10,
1189	    ("bad AE %d", ae));
1190	if (ae == IEEE80211_MESH_AE_10) {	/* ucast w/ proxy */
1191		const struct ieee80211_meshcntl_ae10 *mc10 =
1192		    (const struct ieee80211_meshcntl_ae10 *) mc;
1193		struct ieee80211_mesh_route *rt =
1194		    ieee80211_mesh_rt_find(vap, mc10->mc_addr5);
1195		/* check for proxy route to ourself */
1196		return (rt != NULL &&
1197		    (rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY));
1198	} else					/* ucast w/o proxy */
1199		return IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_myaddr);
1200}
1201
1202/*
1203 * Verifies transmitter, updates lifetime, precursor list and forwards data.
1204 * > 0 means we have forwarded data and no need to process locally
1205 * == 0 means we want to process locally (and we may have forwarded data
1206 * < 0 means there was an error and data should be discarded
1207 */
1208static int
1209mesh_recv_indiv_data_to_fwrd(struct ieee80211vap *vap, struct mbuf *m,
1210    struct ieee80211_frame *wh, const struct ieee80211_meshcntl *mc)
1211{
1212	struct ieee80211_qosframe_addr4 *qwh;
1213	struct ieee80211_mesh_state *ms = vap->iv_mesh;
1214	struct ieee80211_mesh_route *rt_meshda, *rt_meshsa;
1215
1216	qwh = (struct ieee80211_qosframe_addr4 *)wh;
1217
1218	/*
1219	 * TODO:
1220	 * o verify addr2 is  a legitimate transmitter
1221	 * o lifetime of precursor of addr3 (addr2) is max(init, curr)
1222	 * o lifetime of precursor of addr4 (nexthop) is max(init, curr)
1223	 */
1224
1225	/* set lifetime of addr3 (meshDA) to initial value */
1226	rt_meshda = ieee80211_mesh_rt_find(vap, qwh->i_addr3);
1227	if (rt_meshda == NULL) {
1228		IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, qwh->i_addr2,
1229		    "no route to meshDA(%6D)", qwh->i_addr3, ":");
1230		/*
1231		 * [Optional] any of the following three actions:
1232		 * o silently discard 				[X]
1233		 * o trigger a path discovery			[ ]
1234		 * o inform TA that meshDA is unknown.		[ ]
1235		 */
1236		/* XXX: stats */
1237		return (-1);
1238	}
1239
1240	ieee80211_mesh_rt_update(rt_meshda, ticks_to_msecs(
1241	    ms->ms_ppath->mpp_inact));
1242
1243	/* set lifetime of addr4 (meshSA) to initial value */
1244	rt_meshsa = ieee80211_mesh_rt_find(vap, qwh->i_addr4);
1245	KASSERT(rt_meshsa != NULL, ("no route"));
1246	ieee80211_mesh_rt_update(rt_meshsa, ticks_to_msecs(
1247	    ms->ms_ppath->mpp_inact));
1248
1249	mesh_forward(vap, m, mc);
1250	return (1); /* dont process locally */
1251}
1252
1253/*
1254 * Verifies transmitter, updates lifetime, precursor list and process data
1255 * locally, if data is proxy with AE = 10 it could mean data should go
1256 * on another mesh path or data should be forwarded to the DS.
1257 *
1258 * > 0 means we have forwarded data and no need to process locally
1259 * == 0 means we want to process locally (and we may have forwarded data
1260 * < 0 means there was an error and data should be discarded
1261 */
1262static int
1263mesh_recv_indiv_data_to_me(struct ieee80211vap *vap, struct mbuf *m,
1264    struct ieee80211_frame *wh, const struct ieee80211_meshcntl *mc)
1265{
1266	struct ieee80211_qosframe_addr4 *qwh;
1267	const struct ieee80211_meshcntl_ae10 *mc10;
1268	struct ieee80211_mesh_state *ms = vap->iv_mesh;
1269	struct ieee80211_mesh_route *rt;
1270	int ae;
1271
1272	qwh = (struct ieee80211_qosframe_addr4 *)wh;
1273	mc10 = (const struct ieee80211_meshcntl_ae10 *)mc;
1274
1275	/*
1276	 * TODO:
1277	 * o verify addr2 is  a legitimate transmitter
1278	 * o lifetime of precursor entry is max(init, curr)
1279	 */
1280
1281	/* set lifetime of addr4 (meshSA) to initial value */
1282	rt = ieee80211_mesh_rt_find(vap, qwh->i_addr4);
1283	KASSERT(rt != NULL, ("no route"));
1284	ieee80211_mesh_rt_update(rt, ticks_to_msecs(ms->ms_ppath->mpp_inact));
1285	rt = NULL;
1286
1287	ae = mc10->mc_flags & IEEE80211_MESH_AE_MASK;
1288	KASSERT(ae == IEEE80211_MESH_AE_00 ||
1289	    ae == IEEE80211_MESH_AE_10, ("bad AE %d", ae));
1290	if (ae == IEEE80211_MESH_AE_10) {
1291		if (IEEE80211_ADDR_EQ(mc10->mc_addr5, qwh->i_addr3)) {
1292			return (0); /* process locally */
1293		}
1294
1295		rt =  ieee80211_mesh_rt_find(vap, mc10->mc_addr5);
1296		if (rt != NULL &&
1297		    (rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) &&
1298		    (rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY) == 0) {
1299			/*
1300			 * Forward on another mesh-path, according to
1301			 * amendment as specified in 9.32.4.1
1302			 */
1303			IEEE80211_ADDR_COPY(qwh->i_addr3, mc10->mc_addr5);
1304			mesh_forward(vap, m,
1305			    (const struct ieee80211_meshcntl *)mc10);
1306			return (1); /* dont process locally */
1307		}
1308		/*
1309		 * All other cases: forward of MSDUs from the MBSS to DS indiv.
1310		 * addressed according to 13.11.3.2.
1311		 */
1312		IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_OUTPUT, qwh->i_addr2,
1313		    "forward frame to DS, SA(%6D) DA(%6D)",
1314		    mc10->mc_addr6, ":", mc10->mc_addr5, ":");
1315	}
1316	return (0); /* process locally */
1317}
1318
1319/*
1320 * Try to forward the group addressed data on to other mesh STAs, and
1321 * also to the DS.
1322 *
1323 * > 0 means we have forwarded data and no need to process locally
1324 * == 0 means we want to process locally (and we may have forwarded data
1325 * < 0 means there was an error and data should be discarded
1326 */
1327static int
1328mesh_recv_group_data(struct ieee80211vap *vap, struct mbuf *m,
1329    struct ieee80211_frame *wh, const struct ieee80211_meshcntl *mc)
1330{
1331#define	MC01(mc)	((const struct ieee80211_meshcntl_ae01 *)mc)
1332	struct ieee80211_mesh_state *ms = vap->iv_mesh;
1333
1334	mesh_forward(vap, m, mc);
1335
1336	if(mc->mc_ttl > 0) {
1337		if (mc->mc_flags & IEEE80211_MESH_AE_01) {
1338			/*
1339			 * Forward of MSDUs from the MBSS to DS group addressed
1340			 * (according to 13.11.3.2)
1341			 * This happens by delivering the packet, and a bridge
1342			 * will sent it on another port member.
1343			 */
1344			if (ms->ms_flags & IEEE80211_MESHFLAGS_GATE &&
1345			    ms->ms_flags & IEEE80211_MESHFLAGS_FWD)
1346				IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH,
1347				    MC01(mc)->mc_addr4, "%s",
1348				    "forward from MBSS to the DS");
1349		}
1350	}
1351	return (0); /* process locally */
1352#undef	MC01
1353}
1354
1355static int
1356mesh_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf)
1357{
1358#define	HAS_SEQ(type)	((type & 0x4) == 0)
1359#define	MC01(mc)	((const struct ieee80211_meshcntl_ae01 *)mc)
1360#define	MC10(mc)	((const struct ieee80211_meshcntl_ae10 *)mc)
1361	struct ieee80211vap *vap = ni->ni_vap;
1362	struct ieee80211com *ic = ni->ni_ic;
1363	struct ifnet *ifp = vap->iv_ifp;
1364	struct ieee80211_frame *wh;
1365	const struct ieee80211_meshcntl *mc;
1366	int hdrspace, meshdrlen, need_tap, error;
1367	uint8_t dir, type, subtype, ae;
1368	uint32_t seq;
1369	const uint8_t *addr;
1370	uint8_t qos[2];
1371	ieee80211_seq rxseq;
1372
1373	KASSERT(ni != NULL, ("null node"));
1374	ni->ni_inact = ni->ni_inact_reload;
1375
1376	need_tap = 1;			/* mbuf need to be tapped. */
1377	type = -1;			/* undefined */
1378
1379	if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_min)) {
1380		IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
1381		    ni->ni_macaddr, NULL,
1382		    "too short (1): len %u", m->m_pkthdr.len);
1383		vap->iv_stats.is_rx_tooshort++;
1384		goto out;
1385	}
1386	/*
1387	 * Bit of a cheat here, we use a pointer for a 3-address
1388	 * frame format but don't reference fields past outside
1389	 * ieee80211_frame_min w/o first validating the data is
1390	 * present.
1391	*/
1392	wh = mtod(m, struct ieee80211_frame *);
1393
1394	if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) !=
1395	    IEEE80211_FC0_VERSION_0) {
1396		IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
1397		    ni->ni_macaddr, NULL, "wrong version %x", wh->i_fc[0]);
1398		vap->iv_stats.is_rx_badversion++;
1399		goto err;
1400	}
1401	dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
1402	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
1403	subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
1404	if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) {
1405		IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi);
1406		ni->ni_noise = nf;
1407		if (HAS_SEQ(type)) {
1408			uint8_t tid = ieee80211_gettid(wh);
1409
1410			if (IEEE80211_QOS_HAS_SEQ(wh) &&
1411			    TID_TO_WME_AC(tid) >= WME_AC_VI)
1412				ic->ic_wme.wme_hipri_traffic++;
1413			rxseq = le16toh(*(uint16_t *)wh->i_seq);
1414			if (! ieee80211_check_rxseq(ni, wh)) {
1415				/* duplicate, discard */
1416				IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
1417				    wh->i_addr1, "duplicate",
1418				    "seqno <%u,%u> fragno <%u,%u> tid %u",
1419				    rxseq >> IEEE80211_SEQ_SEQ_SHIFT,
1420				    ni->ni_rxseqs[tid] >>
1421				    IEEE80211_SEQ_SEQ_SHIFT,
1422				    rxseq & IEEE80211_SEQ_FRAG_MASK,
1423				    ni->ni_rxseqs[tid] &
1424				    IEEE80211_SEQ_FRAG_MASK,
1425				    tid);
1426				vap->iv_stats.is_rx_dup++;
1427				IEEE80211_NODE_STAT(ni, rx_dup);
1428				goto out;
1429			}
1430			ni->ni_rxseqs[tid] = rxseq;
1431		}
1432	}
1433#ifdef IEEE80211_DEBUG
1434	/*
1435	 * It's easier, but too expensive, to simulate different mesh
1436	 * topologies by consulting the ACL policy very early, so do this
1437	 * only under DEBUG.
1438	 *
1439	 * NB: this check is also done upon peering link initiation.
1440	 */
1441	if (vap->iv_acl != NULL && !vap->iv_acl->iac_check(vap, wh)) {
1442		IEEE80211_DISCARD(vap, IEEE80211_MSG_ACL,
1443		    wh, NULL, "%s", "disallowed by ACL");
1444		vap->iv_stats.is_rx_acl++;
1445		goto out;
1446	}
1447#endif
1448	switch (type) {
1449	case IEEE80211_FC0_TYPE_DATA:
1450		if (ni == vap->iv_bss)
1451			goto out;
1452		if (ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED) {
1453			IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_MESH,
1454			    ni->ni_macaddr, NULL,
1455			    "peer link not yet established (%d)",
1456			    ni->ni_mlstate);
1457			vap->iv_stats.is_mesh_nolink++;
1458			goto out;
1459		}
1460		if (dir != IEEE80211_FC1_DIR_FROMDS &&
1461		    dir != IEEE80211_FC1_DIR_DSTODS) {
1462			IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
1463			    wh, "data", "incorrect dir 0x%x", dir);
1464			vap->iv_stats.is_rx_wrongdir++;
1465			goto err;
1466		}
1467
1468		/* All Mesh data frames are QoS subtype */
1469		if (!HAS_SEQ(type)) {
1470			IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
1471			    wh, "data", "incorrect subtype 0x%x", subtype);
1472			vap->iv_stats.is_rx_badsubtype++;
1473			goto err;
1474		}
1475
1476		/*
1477		 * Next up, any fragmentation.
1478		 * XXX: we defrag before we even try to forward,
1479		 * Mesh Control field is not present in sub-sequent
1480		 * fragmented frames. This is in contrast to Draft 4.0.
1481		 */
1482		hdrspace = ieee80211_hdrspace(ic, wh);
1483		if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
1484			m = ieee80211_defrag(ni, m, hdrspace);
1485			if (m == NULL) {
1486				/* Fragment dropped or frame not complete yet */
1487				goto out;
1488			}
1489		}
1490		wh = mtod(m, struct ieee80211_frame *); /* NB: after defrag */
1491
1492		/*
1493		 * Now we have a complete Mesh Data frame.
1494		 */
1495
1496		/*
1497		 * Only fromDStoDS data frames use 4 address qos frames
1498		 * as specified in amendment. Otherwise addr4 is located
1499		 * in the Mesh Control field and a 3 address qos frame
1500		 * is used.
1501		 */
1502		if (IEEE80211_IS_DSTODS(wh))
1503			*(uint16_t *)qos = *(uint16_t *)
1504			    ((struct ieee80211_qosframe_addr4 *)wh)->i_qos;
1505		else
1506			*(uint16_t *)qos = *(uint16_t *)
1507			    ((struct ieee80211_qosframe *)wh)->i_qos;
1508
1509		/*
1510		 * NB: The mesh STA sets the Mesh Control Present
1511		 * subfield to 1 in the Mesh Data frame containing
1512		 * an unfragmented MSDU, an A-MSDU, or the first
1513		 * fragment of an MSDU.
1514		 * After defrag it should always be present.
1515		 */
1516		if (!(qos[1] & IEEE80211_QOS_MC)) {
1517			IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_MESH,
1518			    ni->ni_macaddr, NULL,
1519			    "%s", "Mesh control field not present");
1520			vap->iv_stats.is_rx_elem_missing++; /* XXX: kinda */
1521			goto err;
1522		}
1523
1524		/* pull up enough to get to the mesh control */
1525		if (m->m_len < hdrspace + sizeof(struct ieee80211_meshcntl) &&
1526		    (m = m_pullup(m, hdrspace +
1527		        sizeof(struct ieee80211_meshcntl))) == NULL) {
1528			IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
1529			    ni->ni_macaddr, NULL,
1530			    "data too short: expecting %u", hdrspace);
1531			vap->iv_stats.is_rx_tooshort++;
1532			goto out;		/* XXX */
1533		}
1534		/*
1535		 * Now calculate the full extent of the headers. Note
1536		 * mesh_decap will pull up anything we didn't get
1537		 * above when it strips the 802.11 headers.
1538		 */
1539		mc = (const struct ieee80211_meshcntl *)
1540		    (mtod(m, const uint8_t *) + hdrspace);
1541		ae = mc->mc_flags & IEEE80211_MESH_AE_MASK;
1542		meshdrlen = sizeof(struct ieee80211_meshcntl) +
1543		    ae * IEEE80211_ADDR_LEN;
1544		hdrspace += meshdrlen;
1545
1546		/* pull complete hdrspace = ieee80211_hdrspace + meshcontrol */
1547		if ((meshdrlen > sizeof(struct ieee80211_meshcntl)) &&
1548		    (m->m_len < hdrspace) &&
1549		    ((m = m_pullup(m, hdrspace)) == NULL)) {
1550			IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
1551			    ni->ni_macaddr, NULL,
1552			    "data too short: expecting %u", hdrspace);
1553			vap->iv_stats.is_rx_tooshort++;
1554			goto out;		/* XXX */
1555		}
1556		/* XXX: are we sure there is no reallocating after m_pullup? */
1557
1558		seq = LE_READ_4(mc->mc_seq);
1559		if (IEEE80211_IS_MULTICAST(wh->i_addr1))
1560			addr = wh->i_addr3;
1561		else if (ae == IEEE80211_MESH_AE_01)
1562			addr = MC01(mc)->mc_addr4;
1563		else
1564			addr = ((struct ieee80211_qosframe_addr4 *)wh)->i_addr4;
1565		if (IEEE80211_ADDR_EQ(vap->iv_myaddr, addr)) {
1566			IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
1567			    addr, "data", "%s", "not to me");
1568			vap->iv_stats.is_rx_wrongbss++;	/* XXX kinda */
1569			goto out;
1570		}
1571		if (mesh_checkpseq(vap, addr, seq) != 0) {
1572			vap->iv_stats.is_rx_dup++;
1573			goto out;
1574		}
1575
1576		/* This code "routes" the frame to the right control path */
1577		if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
1578			if (IEEE80211_ADDR_EQ(vap->iv_myaddr, wh->i_addr3))
1579				error =
1580				    mesh_recv_indiv_data_to_me(vap, m, wh, mc);
1581			else if (IEEE80211_IS_MULTICAST(wh->i_addr3))
1582				error = mesh_recv_group_data(vap, m, wh, mc);
1583			else
1584				error = mesh_recv_indiv_data_to_fwrd(vap, m,
1585				    wh, mc);
1586		} else
1587			error = mesh_recv_group_data(vap, m, wh, mc);
1588		if (error < 0)
1589			goto err;
1590		else if (error > 0)
1591			goto out;
1592
1593		if (ieee80211_radiotap_active_vap(vap))
1594			ieee80211_radiotap_rx(vap, m);
1595		need_tap = 0;
1596
1597		/*
1598		 * Finally, strip the 802.11 header.
1599		 */
1600		m = mesh_decap(vap, m, hdrspace, meshdrlen);
1601		if (m == NULL) {
1602			/* XXX mask bit to check for both */
1603			/* don't count Null data frames as errors */
1604			if (subtype == IEEE80211_FC0_SUBTYPE_NODATA ||
1605			    subtype == IEEE80211_FC0_SUBTYPE_QOS_NULL)
1606				goto out;
1607			IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
1608			    ni->ni_macaddr, "data", "%s", "decap error");
1609			vap->iv_stats.is_rx_decap++;
1610			IEEE80211_NODE_STAT(ni, rx_decap);
1611			goto err;
1612		}
1613		if (qos[0] & IEEE80211_QOS_AMSDU) {
1614			m = ieee80211_decap_amsdu(ni, m);
1615			if (m == NULL)
1616				return IEEE80211_FC0_TYPE_DATA;
1617		}
1618		ieee80211_deliver_data(vap, ni, m);
1619		return type;
1620	case IEEE80211_FC0_TYPE_MGT:
1621		vap->iv_stats.is_rx_mgmt++;
1622		IEEE80211_NODE_STAT(ni, rx_mgmt);
1623		if (dir != IEEE80211_FC1_DIR_NODS) {
1624			IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
1625			    wh, "mgt", "incorrect dir 0x%x", dir);
1626			vap->iv_stats.is_rx_wrongdir++;
1627			goto err;
1628		}
1629		if (m->m_pkthdr.len < sizeof(struct ieee80211_frame)) {
1630			IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
1631			    ni->ni_macaddr, "mgt", "too short: len %u",
1632			    m->m_pkthdr.len);
1633			vap->iv_stats.is_rx_tooshort++;
1634			goto out;
1635		}
1636#ifdef IEEE80211_DEBUG
1637		if ((ieee80211_msg_debug(vap) &&
1638		    (vap->iv_ic->ic_flags & IEEE80211_F_SCAN)) ||
1639		    ieee80211_msg_dumppkts(vap)) {
1640			if_printf(ifp, "received %s from %s rssi %d\n",
1641			    ieee80211_mgt_subtype_name[subtype >>
1642			    IEEE80211_FC0_SUBTYPE_SHIFT],
1643			    ether_sprintf(wh->i_addr2), rssi);
1644		}
1645#endif
1646		if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1647			IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
1648			    wh, NULL, "%s", "WEP set but not permitted");
1649			vap->iv_stats.is_rx_mgtdiscard++; /* XXX */
1650			goto out;
1651		}
1652		vap->iv_recv_mgmt(ni, m, subtype, rssi, nf);
1653		goto out;
1654	case IEEE80211_FC0_TYPE_CTL:
1655		vap->iv_stats.is_rx_ctl++;
1656		IEEE80211_NODE_STAT(ni, rx_ctrl);
1657		goto out;
1658	default:
1659		IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
1660		    wh, "bad", "frame type 0x%x", type);
1661		/* should not come here */
1662		break;
1663	}
1664err:
1665	ifp->if_ierrors++;
1666out:
1667	if (m != NULL) {
1668		if (need_tap && ieee80211_radiotap_active_vap(vap))
1669			ieee80211_radiotap_rx(vap, m);
1670		m_freem(m);
1671	}
1672	return type;
1673#undef	HAS_SEQ
1674#undef	MC01
1675#undef	MC10
1676}
1677
1678static void
1679mesh_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype,
1680    int rssi, int nf)
1681{
1682	struct ieee80211vap *vap = ni->ni_vap;
1683	struct ieee80211_mesh_state *ms = vap->iv_mesh;
1684	struct ieee80211com *ic = ni->ni_ic;
1685	struct ieee80211_frame *wh;
1686	struct ieee80211_mesh_route *rt;
1687	uint8_t *frm, *efrm;
1688
1689	wh = mtod(m0, struct ieee80211_frame *);
1690	frm = (uint8_t *)&wh[1];
1691	efrm = mtod(m0, uint8_t *) + m0->m_len;
1692	switch (subtype) {
1693	case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
1694	case IEEE80211_FC0_SUBTYPE_BEACON:
1695	{
1696		struct ieee80211_scanparams scan;
1697		/*
1698		 * We process beacon/probe response
1699		 * frames to discover neighbors.
1700		 */
1701		if (ieee80211_parse_beacon(ni, m0, &scan) != 0)
1702			return;
1703		/*
1704		 * Count frame now that we know it's to be processed.
1705		 */
1706		if (subtype == IEEE80211_FC0_SUBTYPE_BEACON) {
1707			vap->iv_stats.is_rx_beacon++;	/* XXX remove */
1708			IEEE80211_NODE_STAT(ni, rx_beacons);
1709		} else
1710			IEEE80211_NODE_STAT(ni, rx_proberesp);
1711		/*
1712		 * If scanning, just pass information to the scan module.
1713		 */
1714		if (ic->ic_flags & IEEE80211_F_SCAN) {
1715			if (ic->ic_flags_ext & IEEE80211_FEXT_PROBECHAN) {
1716				/*
1717				 * Actively scanning a channel marked passive;
1718				 * send a probe request now that we know there
1719				 * is 802.11 traffic present.
1720				 *
1721				 * XXX check if the beacon we recv'd gives
1722				 * us what we need and suppress the probe req
1723				 */
1724				ieee80211_probe_curchan(vap, 1);
1725				ic->ic_flags_ext &= ~IEEE80211_FEXT_PROBECHAN;
1726			}
1727			ieee80211_add_scan(vap, &scan, wh,
1728			    subtype, rssi, nf);
1729			return;
1730		}
1731
1732		/* The rest of this code assumes we are running */
1733		if (vap->iv_state != IEEE80211_S_RUN)
1734			return;
1735		/*
1736		 * Ignore non-mesh STAs.
1737		 */
1738		if ((scan.capinfo &
1739		     (IEEE80211_CAPINFO_ESS|IEEE80211_CAPINFO_IBSS)) ||
1740		    scan.meshid == NULL || scan.meshconf == NULL) {
1741			IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
1742			    wh, "beacon", "%s", "not a mesh sta");
1743			vap->iv_stats.is_mesh_wrongmesh++;
1744			return;
1745		}
1746		/*
1747		 * Ignore STAs for other mesh networks.
1748		 */
1749		if (memcmp(scan.meshid+2, ms->ms_id, ms->ms_idlen) != 0 ||
1750		    mesh_verify_meshconf(vap, scan.meshconf)) {
1751			IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
1752			    wh, "beacon", "%s", "not for our mesh");
1753			vap->iv_stats.is_mesh_wrongmesh++;
1754			return;
1755		}
1756		/*
1757		 * Peer only based on the current ACL policy.
1758		 */
1759		if (vap->iv_acl != NULL && !vap->iv_acl->iac_check(vap, wh)) {
1760			IEEE80211_DISCARD(vap, IEEE80211_MSG_ACL,
1761			    wh, NULL, "%s", "disallowed by ACL");
1762			vap->iv_stats.is_rx_acl++;
1763			return;
1764		}
1765		/*
1766		 * Do neighbor discovery.
1767		 */
1768		if (!IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_macaddr)) {
1769			/*
1770			 * Create a new entry in the neighbor table.
1771			 */
1772			ni = ieee80211_add_neighbor(vap, wh, &scan);
1773		}
1774		/*
1775		 * Automatically peer with discovered nodes if possible.
1776		 */
1777		if (ni != vap->iv_bss &&
1778		    (ms->ms_flags & IEEE80211_MESHFLAGS_AP)) {
1779			switch (ni->ni_mlstate) {
1780			case IEEE80211_NODE_MESH_IDLE:
1781			{
1782				uint16_t args[1];
1783
1784				/* Wait for backoff callout to reset counter */
1785				if (ni->ni_mlhcnt >= ieee80211_mesh_maxholding)
1786					return;
1787
1788				ni->ni_mlpid = mesh_generateid(vap);
1789				if (ni->ni_mlpid == 0)
1790					return;
1791				mesh_linkchange(ni, IEEE80211_NODE_MESH_OPENSNT);
1792				args[0] = ni->ni_mlpid;
1793				ieee80211_send_action(ni,
1794				IEEE80211_ACTION_CAT_SELF_PROT,
1795				IEEE80211_ACTION_MESHPEERING_OPEN, args);
1796				ni->ni_mlrcnt = 0;
1797				mesh_peer_timeout_setup(ni);
1798				break;
1799			}
1800			case IEEE80211_NODE_MESH_ESTABLISHED:
1801			{
1802				/*
1803				 * Valid beacon from a peer mesh STA
1804				 * bump TA lifetime
1805				 */
1806				rt = ieee80211_mesh_rt_find(vap, wh->i_addr2);
1807				if(rt != NULL) {
1808					ieee80211_mesh_rt_update(rt,
1809					    ticks_to_msecs(
1810					    ms->ms_ppath->mpp_inact));
1811				}
1812				break;
1813			}
1814			default:
1815				break; /* ignore */
1816			}
1817		}
1818		break;
1819	}
1820	case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
1821	{
1822		uint8_t *ssid, *meshid, *rates, *xrates;
1823		uint8_t *sfrm;
1824
1825		if (vap->iv_state != IEEE80211_S_RUN) {
1826			IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
1827			    wh, NULL, "wrong state %s",
1828			    ieee80211_state_name[vap->iv_state]);
1829			vap->iv_stats.is_rx_mgtdiscard++;
1830			return;
1831		}
1832		if (IEEE80211_IS_MULTICAST(wh->i_addr2)) {
1833			/* frame must be directed */
1834			IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
1835			    wh, NULL, "%s", "not unicast");
1836			vap->iv_stats.is_rx_mgtdiscard++;	/* XXX stat */
1837			return;
1838		}
1839		/*
1840		 * prreq frame format
1841		 *      [tlv] ssid
1842		 *      [tlv] supported rates
1843		 *      [tlv] extended supported rates
1844		 *	[tlv] mesh id
1845		 */
1846		ssid = meshid = rates = xrates = NULL;
1847		sfrm = frm;
1848		while (efrm - frm > 1) {
1849			IEEE80211_VERIFY_LENGTH(efrm - frm, frm[1] + 2, return);
1850			switch (*frm) {
1851			case IEEE80211_ELEMID_SSID:
1852				ssid = frm;
1853				break;
1854			case IEEE80211_ELEMID_RATES:
1855				rates = frm;
1856				break;
1857			case IEEE80211_ELEMID_XRATES:
1858				xrates = frm;
1859				break;
1860			case IEEE80211_ELEMID_MESHID:
1861				meshid = frm;
1862				break;
1863			}
1864			frm += frm[1] + 2;
1865		}
1866		IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN, return);
1867		IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE, return);
1868		if (xrates != NULL)
1869			IEEE80211_VERIFY_ELEMENT(xrates,
1870			    IEEE80211_RATE_MAXSIZE - rates[1], return);
1871		if (meshid != NULL) {
1872			IEEE80211_VERIFY_ELEMENT(meshid,
1873			    IEEE80211_MESHID_LEN, return);
1874			/* NB: meshid, not ssid */
1875			IEEE80211_VERIFY_SSID(vap->iv_bss, meshid, return);
1876		}
1877
1878		/* XXX find a better class or define it's own */
1879		IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_INPUT, wh->i_addr2,
1880		    "%s", "recv probe req");
1881		/*
1882		 * Some legacy 11b clients cannot hack a complete
1883		 * probe response frame.  When the request includes
1884		 * only a bare-bones rate set, communicate this to
1885		 * the transmit side.
1886		 */
1887		ieee80211_send_proberesp(vap, wh->i_addr2, 0);
1888		break;
1889	}
1890
1891	case IEEE80211_FC0_SUBTYPE_ACTION:
1892	case IEEE80211_FC0_SUBTYPE_ACTION_NOACK:
1893		if (ni == vap->iv_bss) {
1894			IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
1895			    wh, NULL, "%s", "unknown node");
1896			vap->iv_stats.is_rx_mgtdiscard++;
1897		} else if (!IEEE80211_ADDR_EQ(vap->iv_myaddr, wh->i_addr1) &&
1898		    !IEEE80211_IS_MULTICAST(wh->i_addr1)) {
1899			IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
1900			    wh, NULL, "%s", "not for us");
1901			vap->iv_stats.is_rx_mgtdiscard++;
1902		} else if (vap->iv_state != IEEE80211_S_RUN) {
1903			IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
1904			    wh, NULL, "wrong state %s",
1905			    ieee80211_state_name[vap->iv_state]);
1906			vap->iv_stats.is_rx_mgtdiscard++;
1907		} else {
1908			if (ieee80211_parse_action(ni, m0) == 0)
1909				(void)ic->ic_recv_action(ni, wh, frm, efrm);
1910		}
1911		break;
1912
1913	case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
1914	case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
1915	case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
1916	case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
1917	case IEEE80211_FC0_SUBTYPE_ATIM:
1918	case IEEE80211_FC0_SUBTYPE_DISASSOC:
1919	case IEEE80211_FC0_SUBTYPE_AUTH:
1920	case IEEE80211_FC0_SUBTYPE_DEAUTH:
1921		IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
1922		    wh, NULL, "%s", "not handled");
1923		vap->iv_stats.is_rx_mgtdiscard++;
1924		break;
1925
1926	default:
1927		IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
1928		    wh, "mgt", "subtype 0x%x not handled", subtype);
1929		vap->iv_stats.is_rx_badsubtype++;
1930		break;
1931	}
1932}
1933
1934static void
1935mesh_recv_ctl(struct ieee80211_node *ni, struct mbuf *m, int subtype)
1936{
1937
1938	switch (subtype) {
1939	case IEEE80211_FC0_SUBTYPE_BAR:
1940		ieee80211_recv_bar(ni, m);
1941		break;
1942	}
1943}
1944
1945/*
1946 * Parse meshpeering action ie's for MPM frames
1947 */
1948static const struct ieee80211_meshpeer_ie *
1949mesh_parse_meshpeering_action(struct ieee80211_node *ni,
1950	const struct ieee80211_frame *wh,	/* XXX for VERIFY_LENGTH */
1951	const uint8_t *frm, const uint8_t *efrm,
1952	struct ieee80211_meshpeer_ie *mp, uint8_t subtype)
1953{
1954	struct ieee80211vap *vap = ni->ni_vap;
1955	const struct ieee80211_meshpeer_ie *mpie;
1956	uint16_t args[3];
1957	const uint8_t *meshid, *meshconf, *meshpeer;
1958	uint8_t sendclose = 0; /* 1 = MPM frame rejected, close will be sent */
1959
1960	meshid = meshconf = meshpeer = NULL;
1961	while (efrm - frm > 1) {
1962		IEEE80211_VERIFY_LENGTH(efrm - frm, frm[1] + 2, return NULL);
1963		switch (*frm) {
1964		case IEEE80211_ELEMID_MESHID:
1965			meshid = frm;
1966			break;
1967		case IEEE80211_ELEMID_MESHCONF:
1968			meshconf = frm;
1969			break;
1970		case IEEE80211_ELEMID_MESHPEER:
1971			meshpeer = frm;
1972			mpie = (const struct ieee80211_meshpeer_ie *) frm;
1973			memset(mp, 0, sizeof(*mp));
1974			mp->peer_len = mpie->peer_len;
1975			mp->peer_proto = LE_READ_2(&mpie->peer_proto);
1976			mp->peer_llinkid = LE_READ_2(&mpie->peer_llinkid);
1977			switch (subtype) {
1978			case IEEE80211_ACTION_MESHPEERING_CONFIRM:
1979				mp->peer_linkid =
1980				    LE_READ_2(&mpie->peer_linkid);
1981				break;
1982			case IEEE80211_ACTION_MESHPEERING_CLOSE:
1983				/* NB: peer link ID is optional */
1984				if (mpie->peer_len ==
1985				    (IEEE80211_MPM_BASE_SZ + 2)) {
1986					mp->peer_linkid = 0;
1987					mp->peer_rcode =
1988					    LE_READ_2(&mpie->peer_linkid);
1989				} else {
1990					mp->peer_linkid =
1991					    LE_READ_2(&mpie->peer_linkid);
1992					mp->peer_rcode =
1993					    LE_READ_2(&mpie->peer_rcode);
1994				}
1995				break;
1996			}
1997			break;
1998		}
1999		frm += frm[1] + 2;
2000	}
2001
2002	/*
2003	 * Verify the contents of the frame.
2004	 * If it fails validation, close the peer link.
2005	 */
2006	if (mesh_verify_meshpeer(vap, subtype, (const uint8_t *)mp)) {
2007		sendclose = 1;
2008		IEEE80211_DISCARD(vap,
2009		    IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
2010		    wh, NULL, "%s", "MPM validation failed");
2011	}
2012
2013	/* If meshid is not the same reject any frames type. */
2014	if (sendclose == 0 && mesh_verify_meshid(vap, meshid)) {
2015		sendclose = 1;
2016		IEEE80211_DISCARD(vap,
2017		    IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
2018		    wh, NULL, "%s", "not for our mesh");
2019		if (subtype == IEEE80211_ACTION_MESHPEERING_CLOSE) {
2020			/*
2021			 * Standard not clear about this, if we dont ignore
2022			 * there will be an endless loop between nodes sending
2023			 * CLOSE frames between each other with wrong meshid.
2024			 * Discard and timers will bring FSM to IDLE state.
2025			 */
2026			return NULL;
2027		}
2028	}
2029
2030	/*
2031	 * Close frames are accepted if meshid is the same.
2032	 * Verify the other two types.
2033	 */
2034	if (sendclose == 0 && subtype != IEEE80211_ACTION_MESHPEERING_CLOSE &&
2035	    mesh_verify_meshconf(vap, meshconf)) {
2036		sendclose = 1;
2037		IEEE80211_DISCARD(vap,
2038		    IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
2039		    wh, NULL, "%s", "configuration missmatch");
2040	}
2041
2042	if (sendclose) {
2043		vap->iv_stats.is_rx_mgtdiscard++;
2044		switch (ni->ni_mlstate) {
2045		case IEEE80211_NODE_MESH_IDLE:
2046		case IEEE80211_NODE_MESH_ESTABLISHED:
2047		case IEEE80211_NODE_MESH_HOLDING:
2048			/* ignore */
2049			break;
2050		case IEEE80211_NODE_MESH_OPENSNT:
2051		case IEEE80211_NODE_MESH_OPENRCV:
2052		case IEEE80211_NODE_MESH_CONFIRMRCV:
2053			args[0] = ni->ni_mlpid;
2054			args[1] = ni->ni_mllid;
2055			/* Reason codes for rejection */
2056			switch (subtype) {
2057			case IEEE80211_ACTION_MESHPEERING_OPEN:
2058				args[2] = IEEE80211_REASON_MESH_CPVIOLATION;
2059				break;
2060			case IEEE80211_ACTION_MESHPEERING_CONFIRM:
2061				args[2] = IEEE80211_REASON_MESH_INCONS_PARAMS;
2062				break;
2063			}
2064			ieee80211_send_action(ni,
2065			    IEEE80211_ACTION_CAT_SELF_PROT,
2066			    IEEE80211_ACTION_MESHPEERING_CLOSE,
2067			    args);
2068			mesh_linkchange(ni, IEEE80211_NODE_MESH_HOLDING);
2069			mesh_peer_timeout_setup(ni);
2070			break;
2071		}
2072		return NULL;
2073	}
2074
2075	return (const struct ieee80211_meshpeer_ie *) mp;
2076}
2077
2078static int
2079mesh_recv_action_meshpeering_open(struct ieee80211_node *ni,
2080	const struct ieee80211_frame *wh,
2081	const uint8_t *frm, const uint8_t *efrm)
2082{
2083	struct ieee80211vap *vap = ni->ni_vap;
2084	struct ieee80211_mesh_state *ms = vap->iv_mesh;
2085	struct ieee80211_meshpeer_ie ie;
2086	const struct ieee80211_meshpeer_ie *meshpeer;
2087	uint16_t args[3];
2088
2089	/* +2+2 for action + code + capabilites */
2090	meshpeer = mesh_parse_meshpeering_action(ni, wh, frm+2+2, efrm, &ie,
2091	    IEEE80211_ACTION_MESHPEERING_OPEN);
2092	if (meshpeer == NULL) {
2093		return 0;
2094	}
2095
2096	/* XXX move up */
2097	IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni,
2098	    "recv PEER OPEN, lid 0x%x", meshpeer->peer_llinkid);
2099
2100	switch (ni->ni_mlstate) {
2101	case IEEE80211_NODE_MESH_IDLE:
2102		/* Reject open request if reached our maximum neighbor count */
2103		if (ms->ms_neighbors >= IEEE80211_MESH_MAX_NEIGHBORS) {
2104			args[0] = meshpeer->peer_llinkid;
2105			args[1] = 0;
2106			args[2] = IEEE80211_REASON_MESH_MAX_PEERS;
2107			ieee80211_send_action(ni,
2108			    IEEE80211_ACTION_CAT_SELF_PROT,
2109			    IEEE80211_ACTION_MESHPEERING_CLOSE,
2110			    args);
2111			/* stay in IDLE state */
2112			return (0);
2113		}
2114		/* Open frame accepted */
2115		mesh_linkchange(ni, IEEE80211_NODE_MESH_OPENRCV);
2116		ni->ni_mllid = meshpeer->peer_llinkid;
2117		ni->ni_mlpid = mesh_generateid(vap);
2118		if (ni->ni_mlpid == 0)
2119			return 0;		/* XXX */
2120		args[0] = ni->ni_mlpid;
2121		/* Announce we're open too... */
2122		ieee80211_send_action(ni,
2123		    IEEE80211_ACTION_CAT_SELF_PROT,
2124		    IEEE80211_ACTION_MESHPEERING_OPEN, args);
2125		/* ...and confirm the link. */
2126		args[0] = ni->ni_mlpid;
2127		args[1] = ni->ni_mllid;
2128		ieee80211_send_action(ni,
2129		    IEEE80211_ACTION_CAT_SELF_PROT,
2130		    IEEE80211_ACTION_MESHPEERING_CONFIRM,
2131		    args);
2132		mesh_peer_timeout_setup(ni);
2133		break;
2134	case IEEE80211_NODE_MESH_OPENRCV:
2135		/* Wrong Link ID */
2136		if (ni->ni_mllid != meshpeer->peer_llinkid) {
2137			args[0] = ni->ni_mllid;
2138			args[1] = ni->ni_mlpid;
2139			args[2] = IEEE80211_REASON_PEER_LINK_CANCELED;
2140			ieee80211_send_action(ni,
2141			    IEEE80211_ACTION_CAT_SELF_PROT,
2142			    IEEE80211_ACTION_MESHPEERING_CLOSE,
2143			    args);
2144			mesh_linkchange(ni, IEEE80211_NODE_MESH_HOLDING);
2145			mesh_peer_timeout_setup(ni);
2146			break;
2147		}
2148		/* Duplicate open, confirm again. */
2149		args[0] = ni->ni_mlpid;
2150		args[1] = ni->ni_mllid;
2151		ieee80211_send_action(ni,
2152		    IEEE80211_ACTION_CAT_SELF_PROT,
2153		    IEEE80211_ACTION_MESHPEERING_CONFIRM,
2154		    args);
2155		break;
2156	case IEEE80211_NODE_MESH_OPENSNT:
2157		ni->ni_mllid = meshpeer->peer_llinkid;
2158		mesh_linkchange(ni, IEEE80211_NODE_MESH_OPENRCV);
2159		args[0] = ni->ni_mlpid;
2160		args[1] = ni->ni_mllid;
2161		ieee80211_send_action(ni,
2162		    IEEE80211_ACTION_CAT_SELF_PROT,
2163		    IEEE80211_ACTION_MESHPEERING_CONFIRM,
2164		    args);
2165		/* NB: don't setup/clear any timeout */
2166		break;
2167	case IEEE80211_NODE_MESH_CONFIRMRCV:
2168		if (ni->ni_mlpid != meshpeer->peer_linkid ||
2169		    ni->ni_mllid != meshpeer->peer_llinkid) {
2170			args[0] = ni->ni_mlpid;
2171			args[1] = ni->ni_mllid;
2172			args[2] = IEEE80211_REASON_PEER_LINK_CANCELED;
2173			ieee80211_send_action(ni,
2174			    IEEE80211_ACTION_CAT_SELF_PROT,
2175			    IEEE80211_ACTION_MESHPEERING_CLOSE,
2176			    args);
2177			mesh_linkchange(ni,
2178			    IEEE80211_NODE_MESH_HOLDING);
2179			mesh_peer_timeout_setup(ni);
2180			break;
2181		}
2182		mesh_linkchange(ni, IEEE80211_NODE_MESH_ESTABLISHED);
2183		ni->ni_mllid = meshpeer->peer_llinkid;
2184		args[0] = ni->ni_mlpid;
2185		args[1] = ni->ni_mllid;
2186		ieee80211_send_action(ni,
2187		    IEEE80211_ACTION_CAT_SELF_PROT,
2188		    IEEE80211_ACTION_MESHPEERING_CONFIRM,
2189		    args);
2190		mesh_peer_timeout_stop(ni);
2191		break;
2192	case IEEE80211_NODE_MESH_ESTABLISHED:
2193		if (ni->ni_mllid != meshpeer->peer_llinkid) {
2194			args[0] = ni->ni_mllid;
2195			args[1] = ni->ni_mlpid;
2196			args[2] = IEEE80211_REASON_PEER_LINK_CANCELED;
2197			ieee80211_send_action(ni,
2198			    IEEE80211_ACTION_CAT_SELF_PROT,
2199			    IEEE80211_ACTION_MESHPEERING_CLOSE,
2200			    args);
2201			mesh_linkchange(ni, IEEE80211_NODE_MESH_HOLDING);
2202			mesh_peer_timeout_setup(ni);
2203			break;
2204		}
2205		args[0] = ni->ni_mlpid;
2206		args[1] = ni->ni_mllid;
2207		ieee80211_send_action(ni,
2208		    IEEE80211_ACTION_CAT_SELF_PROT,
2209		    IEEE80211_ACTION_MESHPEERING_CONFIRM,
2210		    args);
2211		break;
2212	case IEEE80211_NODE_MESH_HOLDING:
2213		args[0] = ni->ni_mlpid;
2214		args[1] = meshpeer->peer_llinkid;
2215		/* Standard not clear about what the reaason code should be */
2216		args[2] = IEEE80211_REASON_PEER_LINK_CANCELED;
2217		ieee80211_send_action(ni,
2218		    IEEE80211_ACTION_CAT_SELF_PROT,
2219		    IEEE80211_ACTION_MESHPEERING_CLOSE,
2220		    args);
2221		break;
2222	}
2223	return 0;
2224}
2225
2226static int
2227mesh_recv_action_meshpeering_confirm(struct ieee80211_node *ni,
2228	const struct ieee80211_frame *wh,
2229	const uint8_t *frm, const uint8_t *efrm)
2230{
2231	struct ieee80211vap *vap = ni->ni_vap;
2232	struct ieee80211_meshpeer_ie ie;
2233	const struct ieee80211_meshpeer_ie *meshpeer;
2234	uint16_t args[3];
2235
2236	/* +2+2+2+2 for action + code + capabilites + status code + AID */
2237	meshpeer = mesh_parse_meshpeering_action(ni, wh, frm+2+2+2+2, efrm, &ie,
2238	    IEEE80211_ACTION_MESHPEERING_CONFIRM);
2239	if (meshpeer == NULL) {
2240		return 0;
2241	}
2242
2243	IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni,
2244	    "recv PEER CONFIRM, local id 0x%x, peer id 0x%x",
2245	    meshpeer->peer_llinkid, meshpeer->peer_linkid);
2246
2247	switch (ni->ni_mlstate) {
2248	case IEEE80211_NODE_MESH_OPENRCV:
2249		mesh_linkchange(ni, IEEE80211_NODE_MESH_ESTABLISHED);
2250		mesh_peer_timeout_stop(ni);
2251		break;
2252	case IEEE80211_NODE_MESH_OPENSNT:
2253		mesh_linkchange(ni, IEEE80211_NODE_MESH_CONFIRMRCV);
2254		mesh_peer_timeout_setup(ni);
2255		break;
2256	case IEEE80211_NODE_MESH_HOLDING:
2257		args[0] = ni->ni_mlpid;
2258		args[1] = meshpeer->peer_llinkid;
2259		/* Standard not clear about what the reaason code should be */
2260		args[2] = IEEE80211_REASON_PEER_LINK_CANCELED;
2261		ieee80211_send_action(ni,
2262		    IEEE80211_ACTION_CAT_SELF_PROT,
2263		    IEEE80211_ACTION_MESHPEERING_CLOSE,
2264		    args);
2265		break;
2266	case IEEE80211_NODE_MESH_CONFIRMRCV:
2267		if (ni->ni_mllid != meshpeer->peer_llinkid) {
2268			args[0] = ni->ni_mlpid;
2269			args[1] = ni->ni_mllid;
2270			args[2] = IEEE80211_REASON_PEER_LINK_CANCELED;
2271			ieee80211_send_action(ni,
2272			    IEEE80211_ACTION_CAT_SELF_PROT,
2273			    IEEE80211_ACTION_MESHPEERING_CLOSE,
2274			    args);
2275			mesh_linkchange(ni, IEEE80211_NODE_MESH_HOLDING);
2276			mesh_peer_timeout_setup(ni);
2277		}
2278		break;
2279	default:
2280		IEEE80211_DISCARD(vap,
2281		    IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
2282		    wh, NULL, "received confirm in invalid state %d",
2283		    ni->ni_mlstate);
2284		vap->iv_stats.is_rx_mgtdiscard++;
2285		break;
2286	}
2287	return 0;
2288}
2289
2290static int
2291mesh_recv_action_meshpeering_close(struct ieee80211_node *ni,
2292	const struct ieee80211_frame *wh,
2293	const uint8_t *frm, const uint8_t *efrm)
2294{
2295	struct ieee80211_meshpeer_ie ie;
2296	const struct ieee80211_meshpeer_ie *meshpeer;
2297	uint16_t args[3];
2298
2299	/* +2 for action + code */
2300	meshpeer = mesh_parse_meshpeering_action(ni, wh, frm+2, efrm, &ie,
2301	    IEEE80211_ACTION_MESHPEERING_CLOSE);
2302	if (meshpeer == NULL) {
2303		return 0;
2304	}
2305
2306	/*
2307	 * XXX: check reason code, for example we could receive
2308	 * IEEE80211_REASON_MESH_MAX_PEERS then we should not attempt
2309	 * to peer again.
2310	 */
2311
2312	IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
2313	    ni, "%s", "recv PEER CLOSE");
2314
2315	switch (ni->ni_mlstate) {
2316	case IEEE80211_NODE_MESH_IDLE:
2317		/* ignore */
2318		break;
2319	case IEEE80211_NODE_MESH_OPENRCV:
2320	case IEEE80211_NODE_MESH_OPENSNT:
2321	case IEEE80211_NODE_MESH_CONFIRMRCV:
2322	case IEEE80211_NODE_MESH_ESTABLISHED:
2323		args[0] = ni->ni_mlpid;
2324		args[1] = ni->ni_mllid;
2325		args[2] = IEEE80211_REASON_MESH_CLOSE_RCVD;
2326		ieee80211_send_action(ni,
2327		    IEEE80211_ACTION_CAT_SELF_PROT,
2328		    IEEE80211_ACTION_MESHPEERING_CLOSE,
2329		    args);
2330		mesh_linkchange(ni, IEEE80211_NODE_MESH_HOLDING);
2331		mesh_peer_timeout_setup(ni);
2332		break;
2333	case IEEE80211_NODE_MESH_HOLDING:
2334		mesh_linkchange(ni, IEEE80211_NODE_MESH_IDLE);
2335		mesh_peer_timeout_stop(ni);
2336		break;
2337	}
2338	return 0;
2339}
2340
2341/*
2342 * Link Metric handling.
2343 */
2344static int
2345mesh_recv_action_meshlmetric(struct ieee80211_node *ni,
2346	const struct ieee80211_frame *wh,
2347	const uint8_t *frm, const uint8_t *efrm)
2348{
2349	const struct ieee80211_meshlmetric_ie *ie =
2350	    (const struct ieee80211_meshlmetric_ie *)
2351	    (frm+2); /* action + code */
2352	struct ieee80211_meshlmetric_ie lm_rep;
2353
2354	if (ie->lm_flags & IEEE80211_MESH_LMETRIC_FLAGS_REQ) {
2355		lm_rep.lm_flags = 0;
2356		lm_rep.lm_metric = mesh_airtime_calc(ni);
2357		ieee80211_send_action(ni,
2358		    IEEE80211_ACTION_CAT_MESH,
2359		    IEEE80211_ACTION_MESH_LMETRIC,
2360		    &lm_rep);
2361	}
2362	/* XXX: else do nothing for now */
2363	return 0;
2364}
2365
2366/*
2367 * Mesh Gate Announcement handling.
2368 */
2369static int
2370mesh_recv_action_meshgate(struct ieee80211_node *ni,
2371	const struct ieee80211_frame *wh,
2372	const uint8_t *frm, const uint8_t *efrm)
2373{
2374	struct ieee80211vap *vap = ni->ni_vap;
2375	struct ieee80211_mesh_state *ms = vap->iv_mesh;
2376	struct ieee80211_mesh_gate_route *gr, *next;
2377	struct ieee80211_mesh_route *rt_gate;
2378	struct ieee80211_meshgann_ie pgann;
2379	int found = 0;
2380	const struct ieee80211_meshgann_ie *ie =
2381	    (const struct ieee80211_meshgann_ie *)
2382	    (frm+2); /* action + code */
2383
2384	if (IEEE80211_ADDR_EQ(vap->iv_myaddr, ie->gann_addr))
2385		return 0;
2386
2387	IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, ni->ni_macaddr,
2388	    "received GANN, meshgate: %6D (seq %u)", ie->gann_addr, ":",
2389	    ie->gann_seq);
2390
2391	if (ms == NULL)
2392		return (0);
2393	MESH_RT_LOCK(ms);
2394	TAILQ_FOREACH_SAFE(gr, &ms->ms_known_gates, gr_next, next) {
2395		if (!IEEE80211_ADDR_EQ(gr->gr_addr, ie->gann_addr))
2396			continue;
2397		if (ie->gann_seq <= gr->gr_lastseq) {
2398			IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_MESH,
2399			    ni->ni_macaddr, NULL,
2400			    "GANN old seqno %u <= %u",
2401			    ie->gann_seq, gr->gr_lastseq);
2402			MESH_RT_UNLOCK(ms);
2403			return (0);
2404		}
2405		/* corresponding mesh gate found & GANN accepted */
2406		found = 1;
2407		break;
2408
2409	}
2410	if (found == 0) {
2411		/* this GANN is from a new mesh Gate add it to known table. */
2412		IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, ie->gann_addr,
2413		    "stored new GANN information, seq %u.", ie->gann_seq);
2414		gr = malloc(ALIGN(sizeof(struct ieee80211_mesh_gate_route)),
2415		    M_80211_MESH_GT_RT, M_NOWAIT | M_ZERO);
2416		IEEE80211_ADDR_COPY(gr->gr_addr, ie->gann_addr);
2417		TAILQ_INSERT_TAIL(&ms->ms_known_gates, gr, gr_next);
2418	}
2419	gr->gr_lastseq = ie->gann_seq;
2420
2421	/* check if we have a path to this gate */
2422	rt_gate = mesh_rt_find_locked(ms, gr->gr_addr);
2423	if (rt_gate != NULL &&
2424	    rt_gate->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) {
2425		gr->gr_route = rt_gate;
2426		rt_gate->rt_flags |= IEEE80211_MESHRT_FLAGS_GATE;
2427	}
2428
2429	MESH_RT_UNLOCK(ms);
2430
2431	/* popagate only if decremented ttl >= 1 && forwarding is enabled */
2432	if ((ie->gann_ttl - 1) < 1 &&
2433	    !(ms->ms_flags & IEEE80211_MESHFLAGS_FWD))
2434		return 0;
2435	pgann.gann_flags = ie->gann_flags; /* Reserved */
2436	pgann.gann_hopcount = ie->gann_hopcount + 1;
2437	pgann.gann_ttl = ie->gann_ttl - 1;
2438	IEEE80211_ADDR_COPY(pgann.gann_addr, ie->gann_addr);
2439	pgann.gann_seq = ie->gann_seq;
2440	pgann.gann_interval = ie->gann_interval;
2441
2442	IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, ie->gann_addr,
2443	    "%s", "propagate GANN");
2444
2445	ieee80211_send_action(vap->iv_bss, IEEE80211_ACTION_CAT_MESH,
2446	    IEEE80211_ACTION_MESH_GANN, &pgann);
2447
2448	return 0;
2449}
2450
2451static int
2452mesh_send_action(struct ieee80211_node *ni,
2453    const uint8_t sa[IEEE80211_ADDR_LEN],
2454    const uint8_t da[IEEE80211_ADDR_LEN],
2455    struct mbuf *m)
2456{
2457	struct ieee80211vap *vap = ni->ni_vap;
2458	struct ieee80211com *ic = ni->ni_ic;
2459	struct ieee80211_bpf_params params;
2460	struct ieee80211_frame *wh;
2461
2462	KASSERT(ni != NULL, ("null node"));
2463
2464	if (vap->iv_state == IEEE80211_S_CAC) {
2465		IEEE80211_NOTE(vap, IEEE80211_MSG_OUTPUT, ni,
2466		    "block %s frame in CAC state", "Mesh action");
2467		vap->iv_stats.is_tx_badstate++;
2468		ieee80211_free_node(ni);
2469		m_freem(m);
2470		return EIO;		/* XXX */
2471	}
2472
2473	M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT);
2474	if (m == NULL) {
2475		ieee80211_free_node(ni);
2476		return ENOMEM;
2477	}
2478
2479	wh = mtod(m, struct ieee80211_frame *);
2480	ieee80211_send_setup(ni, m,
2481	     IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_ACTION,
2482	     IEEE80211_NONQOS_TID, sa, da, sa);
2483	m->m_flags |= M_ENCAP;		/* mark encapsulated */
2484
2485	memset(&params, 0, sizeof(params));
2486	params.ibp_pri = WME_AC_VO;
2487	params.ibp_rate0 = ni->ni_txparms->mgmtrate;
2488	if (IEEE80211_IS_MULTICAST(da))
2489		params.ibp_try0 = 1;
2490	else
2491		params.ibp_try0 = ni->ni_txparms->maxretry;
2492	params.ibp_power = ni->ni_txpower;
2493
2494	IEEE80211_NODE_STAT(ni, tx_mgmt);
2495
2496	return ic->ic_raw_xmit(ni, m, &params);
2497}
2498
2499#define	ADDSHORT(frm, v) do {			\
2500	frm[0] = (v) & 0xff;			\
2501	frm[1] = (v) >> 8;			\
2502	frm += 2;				\
2503} while (0)
2504#define	ADDWORD(frm, v) do {			\
2505	frm[0] = (v) & 0xff;			\
2506	frm[1] = ((v) >> 8) & 0xff;		\
2507	frm[2] = ((v) >> 16) & 0xff;		\
2508	frm[3] = ((v) >> 24) & 0xff;		\
2509	frm += 4;				\
2510} while (0)
2511
2512static int
2513mesh_send_action_meshpeering_open(struct ieee80211_node *ni,
2514	int category, int action, void *args0)
2515{
2516	struct ieee80211vap *vap = ni->ni_vap;
2517	struct ieee80211com *ic = ni->ni_ic;
2518	uint16_t *args = args0;
2519	const struct ieee80211_rateset *rs;
2520	struct mbuf *m;
2521	uint8_t *frm;
2522
2523	IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni,
2524	    "send PEER OPEN action: localid 0x%x", args[0]);
2525
2526	IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
2527	    "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__,
2528	    ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)+1);
2529	ieee80211_ref_node(ni);
2530
2531	m = ieee80211_getmgtframe(&frm,
2532	    ic->ic_headroom + sizeof(struct ieee80211_frame),
2533	    sizeof(uint16_t)	/* action+category */
2534	    + sizeof(uint16_t)	/* capabilites */
2535	    + 2 + IEEE80211_RATE_SIZE
2536	    + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)
2537	    + 2 + IEEE80211_MESHID_LEN
2538	    + sizeof(struct ieee80211_meshconf_ie)
2539	    + sizeof(struct ieee80211_meshpeer_ie)
2540	);
2541	if (m != NULL) {
2542		/*
2543		 * mesh peer open action frame format:
2544		 *   [1] category
2545		 *   [1] action
2546		 *   [2] capabilities
2547		 *   [tlv] rates
2548		 *   [tlv] xrates
2549		 *   [tlv] mesh id
2550		 *   [tlv] mesh conf
2551		 *   [tlv] mesh peer link mgmt
2552		 */
2553		*frm++ = category;
2554		*frm++ = action;
2555		ADDSHORT(frm, ieee80211_getcapinfo(vap, ni->ni_chan));
2556		rs = ieee80211_get_suprates(ic, ic->ic_curchan);
2557		frm = ieee80211_add_rates(frm, rs);
2558		frm = ieee80211_add_xrates(frm, rs);
2559		frm = ieee80211_add_meshid(frm, vap);
2560		frm = ieee80211_add_meshconf(frm, vap);
2561		frm = ieee80211_add_meshpeer(frm, IEEE80211_ACTION_MESHPEERING_OPEN,
2562		    args[0], 0, 0);
2563		m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
2564		return mesh_send_action(ni, vap->iv_myaddr, ni->ni_macaddr, m);
2565	} else {
2566		vap->iv_stats.is_tx_nobuf++;
2567		ieee80211_free_node(ni);
2568		return ENOMEM;
2569	}
2570}
2571
2572static int
2573mesh_send_action_meshpeering_confirm(struct ieee80211_node *ni,
2574	int category, int action, void *args0)
2575{
2576	struct ieee80211vap *vap = ni->ni_vap;
2577	struct ieee80211com *ic = ni->ni_ic;
2578	uint16_t *args = args0;
2579	const struct ieee80211_rateset *rs;
2580	struct mbuf *m;
2581	uint8_t *frm;
2582
2583	IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni,
2584	    "send PEER CONFIRM action: localid 0x%x, peerid 0x%x",
2585	    args[0], args[1]);
2586
2587	IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
2588	    "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__,
2589	    ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)+1);
2590	ieee80211_ref_node(ni);
2591
2592	m = ieee80211_getmgtframe(&frm,
2593	    ic->ic_headroom + sizeof(struct ieee80211_frame),
2594	    sizeof(uint16_t)	/* action+category */
2595	    + sizeof(uint16_t)	/* capabilites */
2596	    + sizeof(uint16_t)	/* status code */
2597	    + sizeof(uint16_t)	/* AID */
2598	    + 2 + IEEE80211_RATE_SIZE
2599	    + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)
2600	    + 2 + IEEE80211_MESHID_LEN
2601	    + sizeof(struct ieee80211_meshconf_ie)
2602	    + sizeof(struct ieee80211_meshpeer_ie)
2603	);
2604	if (m != NULL) {
2605		/*
2606		 * mesh peer confirm action frame format:
2607		 *   [1] category
2608		 *   [1] action
2609		 *   [2] capabilities
2610		 *   [2] status code
2611		 *   [2] association id (peer ID)
2612		 *   [tlv] rates
2613		 *   [tlv] xrates
2614		 *   [tlv] mesh id
2615		 *   [tlv] mesh conf
2616		 *   [tlv] mesh peer link mgmt
2617		 */
2618		*frm++ = category;
2619		*frm++ = action;
2620		ADDSHORT(frm, ieee80211_getcapinfo(vap, ni->ni_chan));
2621		ADDSHORT(frm, 0);		/* status code */
2622		ADDSHORT(frm, args[1]);		/* AID */
2623		rs = ieee80211_get_suprates(ic, ic->ic_curchan);
2624		frm = ieee80211_add_rates(frm, rs);
2625		frm = ieee80211_add_xrates(frm, rs);
2626		frm = ieee80211_add_meshid(frm, vap);
2627		frm = ieee80211_add_meshconf(frm, vap);
2628		frm = ieee80211_add_meshpeer(frm,
2629		    IEEE80211_ACTION_MESHPEERING_CONFIRM,
2630		    args[0], args[1], 0);
2631		m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
2632		return mesh_send_action(ni, vap->iv_myaddr, ni->ni_macaddr, m);
2633	} else {
2634		vap->iv_stats.is_tx_nobuf++;
2635		ieee80211_free_node(ni);
2636		return ENOMEM;
2637	}
2638}
2639
2640static int
2641mesh_send_action_meshpeering_close(struct ieee80211_node *ni,
2642	int category, int action, void *args0)
2643{
2644	struct ieee80211vap *vap = ni->ni_vap;
2645	struct ieee80211com *ic = ni->ni_ic;
2646	uint16_t *args = args0;
2647	struct mbuf *m;
2648	uint8_t *frm;
2649
2650	IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni,
2651	    "send PEER CLOSE action: localid 0x%x, peerid 0x%x reason %d",
2652	    args[0], args[1], args[2]);
2653
2654	IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
2655	    "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__,
2656	    ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)+1);
2657	ieee80211_ref_node(ni);
2658
2659	m = ieee80211_getmgtframe(&frm,
2660	    ic->ic_headroom + sizeof(struct ieee80211_frame),
2661	    sizeof(uint16_t)	/* action+category */
2662	    + sizeof(uint16_t)	/* reason code */
2663	    + 2 + IEEE80211_MESHID_LEN
2664	    + sizeof(struct ieee80211_meshpeer_ie)
2665	);
2666	if (m != NULL) {
2667		/*
2668		 * mesh peer close action frame format:
2669		 *   [1] category
2670		 *   [1] action
2671		 *   [tlv] mesh id
2672		 *   [tlv] mesh peer link mgmt
2673		 */
2674		*frm++ = category;
2675		*frm++ = action;
2676		frm = ieee80211_add_meshid(frm, vap);
2677		frm = ieee80211_add_meshpeer(frm,
2678		    IEEE80211_ACTION_MESHPEERING_CLOSE,
2679		    args[0], args[1], args[2]);
2680		m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
2681		return mesh_send_action(ni, vap->iv_myaddr, ni->ni_macaddr, m);
2682	} else {
2683		vap->iv_stats.is_tx_nobuf++;
2684		ieee80211_free_node(ni);
2685		return ENOMEM;
2686	}
2687}
2688
2689static int
2690mesh_send_action_meshlmetric(struct ieee80211_node *ni,
2691	int category, int action, void *arg0)
2692{
2693	struct ieee80211vap *vap = ni->ni_vap;
2694	struct ieee80211com *ic = ni->ni_ic;
2695	struct ieee80211_meshlmetric_ie *ie = arg0;
2696	struct mbuf *m;
2697	uint8_t *frm;
2698
2699	if (ie->lm_flags & IEEE80211_MESH_LMETRIC_FLAGS_REQ) {
2700		IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
2701		    ni, "%s", "send LINK METRIC REQUEST action");
2702	} else {
2703		IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
2704		    ni, "send LINK METRIC REPLY action: metric 0x%x",
2705		    ie->lm_metric);
2706	}
2707	IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
2708	    "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__,
2709	    ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)+1);
2710	ieee80211_ref_node(ni);
2711
2712	m = ieee80211_getmgtframe(&frm,
2713	    ic->ic_headroom + sizeof(struct ieee80211_frame),
2714	    sizeof(uint16_t) +	/* action+category */
2715	    sizeof(struct ieee80211_meshlmetric_ie)
2716	);
2717	if (m != NULL) {
2718		/*
2719		 * mesh link metric
2720		 *   [1] category
2721		 *   [1] action
2722		 *   [tlv] mesh link metric
2723		 */
2724		*frm++ = category;
2725		*frm++ = action;
2726		frm = ieee80211_add_meshlmetric(frm,
2727		    ie->lm_flags, ie->lm_metric);
2728		m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
2729		return mesh_send_action(ni, vap->iv_myaddr, ni->ni_macaddr, m);
2730	} else {
2731		vap->iv_stats.is_tx_nobuf++;
2732		ieee80211_free_node(ni);
2733		return ENOMEM;
2734	}
2735}
2736
2737static int
2738mesh_send_action_meshgate(struct ieee80211_node *ni,
2739	int category, int action, void *arg0)
2740{
2741	struct ieee80211vap *vap = ni->ni_vap;
2742	struct ieee80211com *ic = ni->ni_ic;
2743	struct ieee80211_meshgann_ie *ie = arg0;
2744	struct mbuf *m;
2745	uint8_t *frm;
2746
2747	IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
2748	    "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__,
2749	    ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)+1);
2750	ieee80211_ref_node(ni);
2751
2752	m = ieee80211_getmgtframe(&frm,
2753	    ic->ic_headroom + sizeof(struct ieee80211_frame),
2754	    sizeof(uint16_t) +	/* action+category */
2755	    IEEE80211_MESHGANN_BASE_SZ
2756	);
2757	if (m != NULL) {
2758		/*
2759		 * mesh link metric
2760		 *   [1] category
2761		 *   [1] action
2762		 *   [tlv] mesh gate annoucement
2763		 */
2764		*frm++ = category;
2765		*frm++ = action;
2766		frm = ieee80211_add_meshgate(frm, ie);
2767		m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
2768		return mesh_send_action(ni, vap->iv_myaddr, broadcastaddr, m);
2769	} else {
2770		vap->iv_stats.is_tx_nobuf++;
2771		ieee80211_free_node(ni);
2772		return ENOMEM;
2773	}
2774}
2775
2776static void
2777mesh_peer_timeout_setup(struct ieee80211_node *ni)
2778{
2779	switch (ni->ni_mlstate) {
2780	case IEEE80211_NODE_MESH_HOLDING:
2781		ni->ni_mltval = ieee80211_mesh_holdingtimeout;
2782		break;
2783	case IEEE80211_NODE_MESH_CONFIRMRCV:
2784		ni->ni_mltval = ieee80211_mesh_confirmtimeout;
2785		break;
2786	case IEEE80211_NODE_MESH_IDLE:
2787		ni->ni_mltval = 0;
2788		break;
2789	default:
2790		ni->ni_mltval = ieee80211_mesh_retrytimeout;
2791		break;
2792	}
2793	if (ni->ni_mltval)
2794		callout_reset(&ni->ni_mltimer, ni->ni_mltval,
2795		    mesh_peer_timeout_cb, ni);
2796}
2797
2798/*
2799 * Same as above but backoffs timer statisically 50%.
2800 */
2801static void
2802mesh_peer_timeout_backoff(struct ieee80211_node *ni)
2803{
2804	uint32_t r;
2805
2806	r = arc4random();
2807	ni->ni_mltval += r % ni->ni_mltval;
2808	callout_reset(&ni->ni_mltimer, ni->ni_mltval, mesh_peer_timeout_cb,
2809	    ni);
2810}
2811
2812static __inline void
2813mesh_peer_timeout_stop(struct ieee80211_node *ni)
2814{
2815	callout_drain(&ni->ni_mltimer);
2816}
2817
2818static void
2819mesh_peer_backoff_cb(void *arg)
2820{
2821	struct ieee80211_node *ni = (struct ieee80211_node *)arg;
2822
2823	/* After backoff timeout, try to peer automatically again. */
2824	ni->ni_mlhcnt = 0;
2825}
2826
2827/*
2828 * Mesh Peer Link Management FSM timeout handling.
2829 */
2830static void
2831mesh_peer_timeout_cb(void *arg)
2832{
2833	struct ieee80211_node *ni = (struct ieee80211_node *)arg;
2834	uint16_t args[3];
2835
2836	IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_MESH,
2837	    ni, "mesh link timeout, state %d, retry counter %d",
2838	    ni->ni_mlstate, ni->ni_mlrcnt);
2839
2840	switch (ni->ni_mlstate) {
2841	case IEEE80211_NODE_MESH_IDLE:
2842	case IEEE80211_NODE_MESH_ESTABLISHED:
2843		break;
2844	case IEEE80211_NODE_MESH_OPENSNT:
2845	case IEEE80211_NODE_MESH_OPENRCV:
2846		if (ni->ni_mlrcnt == ieee80211_mesh_maxretries) {
2847			args[0] = ni->ni_mlpid;
2848			args[2] = IEEE80211_REASON_MESH_MAX_RETRIES;
2849			ieee80211_send_action(ni,
2850			    IEEE80211_ACTION_CAT_SELF_PROT,
2851			    IEEE80211_ACTION_MESHPEERING_CLOSE, args);
2852			ni->ni_mlrcnt = 0;
2853			mesh_linkchange(ni, IEEE80211_NODE_MESH_HOLDING);
2854			mesh_peer_timeout_setup(ni);
2855		} else {
2856			args[0] = ni->ni_mlpid;
2857			ieee80211_send_action(ni,
2858			    IEEE80211_ACTION_CAT_SELF_PROT,
2859			    IEEE80211_ACTION_MESHPEERING_OPEN, args);
2860			ni->ni_mlrcnt++;
2861			mesh_peer_timeout_backoff(ni);
2862		}
2863		break;
2864	case IEEE80211_NODE_MESH_CONFIRMRCV:
2865		args[0] = ni->ni_mlpid;
2866		args[2] = IEEE80211_REASON_MESH_CONFIRM_TIMEOUT;
2867		ieee80211_send_action(ni,
2868		    IEEE80211_ACTION_CAT_SELF_PROT,
2869		    IEEE80211_ACTION_MESHPEERING_CLOSE, args);
2870		mesh_linkchange(ni, IEEE80211_NODE_MESH_HOLDING);
2871		mesh_peer_timeout_setup(ni);
2872		break;
2873	case IEEE80211_NODE_MESH_HOLDING:
2874		ni->ni_mlhcnt++;
2875		if (ni->ni_mlhcnt >= ieee80211_mesh_maxholding)
2876			callout_reset(&ni->ni_mlhtimer,
2877			    ieee80211_mesh_backofftimeout,
2878			    mesh_peer_backoff_cb, ni);
2879		mesh_linkchange(ni, IEEE80211_NODE_MESH_IDLE);
2880		break;
2881	}
2882}
2883
2884static int
2885mesh_verify_meshid(struct ieee80211vap *vap, const uint8_t *ie)
2886{
2887	struct ieee80211_mesh_state *ms = vap->iv_mesh;
2888
2889	if (ie == NULL || ie[1] != ms->ms_idlen)
2890		return 1;
2891	return memcmp(ms->ms_id, ie + 2, ms->ms_idlen);
2892}
2893
2894/*
2895 * Check if we are using the same algorithms for this mesh.
2896 */
2897static int
2898mesh_verify_meshconf(struct ieee80211vap *vap, const uint8_t *ie)
2899{
2900	const struct ieee80211_meshconf_ie *meshconf =
2901	    (const struct ieee80211_meshconf_ie *) ie;
2902	const struct ieee80211_mesh_state *ms = vap->iv_mesh;
2903
2904	if (meshconf == NULL)
2905		return 1;
2906	if (meshconf->conf_pselid != ms->ms_ppath->mpp_ie) {
2907		IEEE80211_DPRINTF(vap, IEEE80211_MSG_MESH,
2908		    "unknown path selection algorithm: 0x%x\n",
2909		    meshconf->conf_pselid);
2910		return 1;
2911	}
2912	if (meshconf->conf_pmetid != ms->ms_pmetric->mpm_ie) {
2913		IEEE80211_DPRINTF(vap, IEEE80211_MSG_MESH,
2914		    "unknown path metric algorithm: 0x%x\n",
2915		    meshconf->conf_pmetid);
2916		return 1;
2917	}
2918	if (meshconf->conf_ccid != 0) {
2919		IEEE80211_DPRINTF(vap, IEEE80211_MSG_MESH,
2920		    "unknown congestion control algorithm: 0x%x\n",
2921		    meshconf->conf_ccid);
2922		return 1;
2923	}
2924	if (meshconf->conf_syncid != IEEE80211_MESHCONF_SYNC_NEIGHOFF) {
2925		IEEE80211_DPRINTF(vap, IEEE80211_MSG_MESH,
2926		    "unknown sync algorithm: 0x%x\n",
2927		    meshconf->conf_syncid);
2928		return 1;
2929	}
2930	if (meshconf->conf_authid != 0) {
2931		IEEE80211_DPRINTF(vap, IEEE80211_MSG_MESH,
2932		    "unknown auth auth algorithm: 0x%x\n",
2933		    meshconf->conf_pselid);
2934		return 1;
2935	}
2936	/* Not accepting peers */
2937	if (!(meshconf->conf_cap & IEEE80211_MESHCONF_CAP_AP)) {
2938		IEEE80211_DPRINTF(vap, IEEE80211_MSG_MESH,
2939		    "not accepting peers: 0x%x\n", meshconf->conf_cap);
2940		return 1;
2941	}
2942	return 0;
2943}
2944
2945static int
2946mesh_verify_meshpeer(struct ieee80211vap *vap, uint8_t subtype,
2947    const uint8_t *ie)
2948{
2949	const struct ieee80211_meshpeer_ie *meshpeer =
2950	    (const struct ieee80211_meshpeer_ie *) ie;
2951
2952	if (meshpeer == NULL ||
2953	    meshpeer->peer_len < IEEE80211_MPM_BASE_SZ ||
2954	    meshpeer->peer_len > IEEE80211_MPM_MAX_SZ)
2955		return 1;
2956	if (meshpeer->peer_proto != IEEE80211_MPPID_MPM) {
2957		IEEE80211_DPRINTF(vap,
2958		    IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
2959		    "Only MPM protocol is supported (proto: 0x%02X)",
2960		    meshpeer->peer_proto);
2961		return 1;
2962	}
2963	switch (subtype) {
2964	case IEEE80211_ACTION_MESHPEERING_OPEN:
2965		if (meshpeer->peer_len != IEEE80211_MPM_BASE_SZ)
2966			return 1;
2967		break;
2968	case IEEE80211_ACTION_MESHPEERING_CONFIRM:
2969		if (meshpeer->peer_len != IEEE80211_MPM_BASE_SZ + 2)
2970			return 1;
2971		break;
2972	case IEEE80211_ACTION_MESHPEERING_CLOSE:
2973		if (meshpeer->peer_len < IEEE80211_MPM_BASE_SZ + 2)
2974			return 1;
2975		if (meshpeer->peer_len == (IEEE80211_MPM_BASE_SZ + 2) &&
2976		    meshpeer->peer_linkid != 0)
2977			return 1;
2978		if (meshpeer->peer_rcode == 0)
2979			return 1;
2980		break;
2981	}
2982	return 0;
2983}
2984
2985/*
2986 * Add a Mesh ID IE to a frame.
2987 */
2988uint8_t *
2989ieee80211_add_meshid(uint8_t *frm, struct ieee80211vap *vap)
2990{
2991	struct ieee80211_mesh_state *ms = vap->iv_mesh;
2992
2993	KASSERT(vap->iv_opmode == IEEE80211_M_MBSS, ("not a mbss vap"));
2994
2995	*frm++ = IEEE80211_ELEMID_MESHID;
2996	*frm++ = ms->ms_idlen;
2997	memcpy(frm, ms->ms_id, ms->ms_idlen);
2998	return frm + ms->ms_idlen;
2999}
3000
3001/*
3002 * Add a Mesh Configuration IE to a frame.
3003 * For now just use HWMP routing, Airtime link metric, Null Congestion
3004 * Signaling, Null Sync Protocol and Null Authentication.
3005 */
3006uint8_t *
3007ieee80211_add_meshconf(uint8_t *frm, struct ieee80211vap *vap)
3008{
3009	const struct ieee80211_mesh_state *ms = vap->iv_mesh;
3010	uint16_t caps;
3011
3012	KASSERT(vap->iv_opmode == IEEE80211_M_MBSS, ("not a MBSS vap"));
3013
3014	*frm++ = IEEE80211_ELEMID_MESHCONF;
3015	*frm++ = IEEE80211_MESH_CONF_SZ;
3016	*frm++ = ms->ms_ppath->mpp_ie;		/* path selection */
3017	*frm++ = ms->ms_pmetric->mpm_ie;	/* link metric */
3018	*frm++ = IEEE80211_MESHCONF_CC_DISABLED;
3019	*frm++ = IEEE80211_MESHCONF_SYNC_NEIGHOFF;
3020	*frm++ = IEEE80211_MESHCONF_AUTH_DISABLED;
3021	/* NB: set the number of neighbors before the rest */
3022	*frm = (ms->ms_neighbors > IEEE80211_MESH_MAX_NEIGHBORS ?
3023	    IEEE80211_MESH_MAX_NEIGHBORS : ms->ms_neighbors) << 1;
3024	if (ms->ms_flags & IEEE80211_MESHFLAGS_GATE)
3025		*frm |= IEEE80211_MESHCONF_FORM_GATE;
3026	frm += 1;
3027	caps = 0;
3028	if (ms->ms_flags & IEEE80211_MESHFLAGS_AP)
3029		caps |= IEEE80211_MESHCONF_CAP_AP;
3030	if (ms->ms_flags & IEEE80211_MESHFLAGS_FWD)
3031		caps |= IEEE80211_MESHCONF_CAP_FWRD;
3032	*frm++ = caps;
3033	return frm;
3034}
3035
3036/*
3037 * Add a Mesh Peer Management IE to a frame.
3038 */
3039uint8_t *
3040ieee80211_add_meshpeer(uint8_t *frm, uint8_t subtype, uint16_t localid,
3041    uint16_t peerid, uint16_t reason)
3042{
3043
3044	KASSERT(localid != 0, ("localid == 0"));
3045
3046	*frm++ = IEEE80211_ELEMID_MESHPEER;
3047	switch (subtype) {
3048	case IEEE80211_ACTION_MESHPEERING_OPEN:
3049		*frm++ = IEEE80211_MPM_BASE_SZ;		/* length */
3050		ADDSHORT(frm, IEEE80211_MPPID_MPM);	/* proto */
3051		ADDSHORT(frm, localid);			/* local ID */
3052		break;
3053	case IEEE80211_ACTION_MESHPEERING_CONFIRM:
3054		KASSERT(peerid != 0, ("sending peer confirm without peer id"));
3055		*frm++ = IEEE80211_MPM_BASE_SZ + 2;	/* length */
3056		ADDSHORT(frm, IEEE80211_MPPID_MPM);	/* proto */
3057		ADDSHORT(frm, localid);			/* local ID */
3058		ADDSHORT(frm, peerid);			/* peer ID */
3059		break;
3060	case IEEE80211_ACTION_MESHPEERING_CLOSE:
3061		if (peerid)
3062			*frm++ = IEEE80211_MPM_MAX_SZ;	/* length */
3063		else
3064			*frm++ = IEEE80211_MPM_BASE_SZ + 2; /* length */
3065		ADDSHORT(frm, IEEE80211_MPPID_MPM);	/* proto */
3066		ADDSHORT(frm, localid);	/* local ID */
3067		if (peerid)
3068			ADDSHORT(frm, peerid);	/* peer ID */
3069		ADDSHORT(frm, reason);
3070		break;
3071	}
3072	return frm;
3073}
3074
3075/*
3076 * Compute an Airtime Link Metric for the link with this node.
3077 *
3078 * Based on Draft 3.0 spec (11B.10, p.149).
3079 */
3080/*
3081 * Max 802.11s overhead.
3082 */
3083#define IEEE80211_MESH_MAXOVERHEAD \
3084	(sizeof(struct ieee80211_qosframe_addr4) \
3085	 + sizeof(struct ieee80211_meshcntl_ae10) \
3086	+ sizeof(struct llc) \
3087	+ IEEE80211_ADDR_LEN \
3088	+ IEEE80211_WEP_IVLEN \
3089	+ IEEE80211_WEP_KIDLEN \
3090	+ IEEE80211_WEP_CRCLEN \
3091	+ IEEE80211_WEP_MICLEN \
3092	+ IEEE80211_CRC_LEN)
3093uint32_t
3094mesh_airtime_calc(struct ieee80211_node *ni)
3095{
3096#define M_BITS 8
3097#define S_FACTOR (2 * M_BITS)
3098	struct ieee80211com *ic = ni->ni_ic;
3099	struct ifnet *ifp = ni->ni_vap->iv_ifp;
3100	const static int nbits = 8192 << M_BITS;
3101	uint32_t overhead, rate, errrate;
3102	uint64_t res;
3103
3104	/* Time to transmit a frame */
3105	rate = ni->ni_txrate;
3106	overhead = ieee80211_compute_duration(ic->ic_rt,
3107	    ifp->if_mtu + IEEE80211_MESH_MAXOVERHEAD, rate, 0) << M_BITS;
3108	/* Error rate in percentage */
3109	/* XXX assuming small failures are ok */
3110	errrate = (((ifp->if_oerrors +
3111	    ifp->if_ierrors) / 100) << M_BITS) / 100;
3112	res = (overhead + (nbits / rate)) *
3113	    ((1 << S_FACTOR) / ((1 << M_BITS) - errrate));
3114
3115	return (uint32_t)(res >> S_FACTOR);
3116#undef M_BITS
3117#undef S_FACTOR
3118}
3119
3120/*
3121 * Add a Mesh Link Metric report IE to a frame.
3122 */
3123uint8_t *
3124ieee80211_add_meshlmetric(uint8_t *frm, uint8_t flags, uint32_t metric)
3125{
3126	*frm++ = IEEE80211_ELEMID_MESHLINK;
3127	*frm++ = 5;
3128	*frm++ = flags;
3129	ADDWORD(frm, metric);
3130	return frm;
3131}
3132
3133/*
3134 * Add a Mesh Gate Announcement IE to a frame.
3135 */
3136uint8_t *
3137ieee80211_add_meshgate(uint8_t *frm, struct ieee80211_meshgann_ie *ie)
3138{
3139	*frm++ = IEEE80211_ELEMID_MESHGANN; /* ie */
3140	*frm++ = IEEE80211_MESHGANN_BASE_SZ; /* len */
3141	*frm++ = ie->gann_flags;
3142	*frm++ = ie->gann_hopcount;
3143	*frm++ = ie->gann_ttl;
3144	IEEE80211_ADDR_COPY(frm, ie->gann_addr);
3145	frm += 6;
3146	ADDWORD(frm, ie->gann_seq);
3147	ADDSHORT(frm, ie->gann_interval);
3148	return frm;
3149}
3150#undef ADDSHORT
3151#undef ADDWORD
3152
3153/*
3154 * Initialize any mesh-specific node state.
3155 */
3156void
3157ieee80211_mesh_node_init(struct ieee80211vap *vap, struct ieee80211_node *ni)
3158{
3159	ni->ni_flags |= IEEE80211_NODE_QOS;
3160	callout_init(&ni->ni_mltimer, CALLOUT_MPSAFE);
3161	callout_init(&ni->ni_mlhtimer, CALLOUT_MPSAFE);
3162}
3163
3164/*
3165 * Cleanup any mesh-specific node state.
3166 */
3167void
3168ieee80211_mesh_node_cleanup(struct ieee80211_node *ni)
3169{
3170	struct ieee80211vap *vap = ni->ni_vap;
3171	struct ieee80211_mesh_state *ms = vap->iv_mesh;
3172
3173	callout_drain(&ni->ni_mltimer);
3174	callout_drain(&ni->ni_mlhtimer);
3175	/* NB: short-circuit callbacks after mesh_vdetach */
3176	if (vap->iv_mesh != NULL)
3177		ms->ms_ppath->mpp_peerdown(ni);
3178}
3179
3180void
3181ieee80211_parse_meshid(struct ieee80211_node *ni, const uint8_t *ie)
3182{
3183	ni->ni_meshidlen = ie[1];
3184	memcpy(ni->ni_meshid, ie + 2, ie[1]);
3185}
3186
3187/*
3188 * Setup mesh-specific node state on neighbor discovery.
3189 */
3190void
3191ieee80211_mesh_init_neighbor(struct ieee80211_node *ni,
3192	const struct ieee80211_frame *wh,
3193	const struct ieee80211_scanparams *sp)
3194{
3195	ieee80211_parse_meshid(ni, sp->meshid);
3196}
3197
3198void
3199ieee80211_mesh_update_beacon(struct ieee80211vap *vap,
3200	struct ieee80211_beacon_offsets *bo)
3201{
3202	KASSERT(vap->iv_opmode == IEEE80211_M_MBSS, ("not a MBSS vap"));
3203
3204	if (isset(bo->bo_flags, IEEE80211_BEACON_MESHCONF)) {
3205		(void)ieee80211_add_meshconf(bo->bo_meshconf, vap);
3206		clrbit(bo->bo_flags, IEEE80211_BEACON_MESHCONF);
3207	}
3208}
3209
3210static int
3211mesh_ioctl_get80211(struct ieee80211vap *vap, struct ieee80211req *ireq)
3212{
3213	struct ieee80211_mesh_state *ms = vap->iv_mesh;
3214	uint8_t tmpmeshid[IEEE80211_NWID_LEN];
3215	struct ieee80211_mesh_route *rt;
3216	struct ieee80211req_mesh_route *imr;
3217	size_t len, off;
3218	uint8_t *p;
3219	int error;
3220
3221	if (vap->iv_opmode != IEEE80211_M_MBSS)
3222		return ENOSYS;
3223
3224	error = 0;
3225	switch (ireq->i_type) {
3226	case IEEE80211_IOC_MESH_ID:
3227		ireq->i_len = ms->ms_idlen;
3228		memcpy(tmpmeshid, ms->ms_id, ireq->i_len);
3229		error = copyout(tmpmeshid, ireq->i_data, ireq->i_len);
3230		break;
3231	case IEEE80211_IOC_MESH_AP:
3232		ireq->i_val = (ms->ms_flags & IEEE80211_MESHFLAGS_AP) != 0;
3233		break;
3234	case IEEE80211_IOC_MESH_FWRD:
3235		ireq->i_val = (ms->ms_flags & IEEE80211_MESHFLAGS_FWD) != 0;
3236		break;
3237	case IEEE80211_IOC_MESH_GATE:
3238		ireq->i_val = (ms->ms_flags & IEEE80211_MESHFLAGS_GATE) != 0;
3239		break;
3240	case IEEE80211_IOC_MESH_TTL:
3241		ireq->i_val = ms->ms_ttl;
3242		break;
3243	case IEEE80211_IOC_MESH_RTCMD:
3244		switch (ireq->i_val) {
3245		case IEEE80211_MESH_RTCMD_LIST:
3246			len = 0;
3247			MESH_RT_LOCK(ms);
3248			TAILQ_FOREACH(rt, &ms->ms_routes, rt_next) {
3249				len += sizeof(*imr);
3250			}
3251			MESH_RT_UNLOCK(ms);
3252			if (len > ireq->i_len || ireq->i_len < sizeof(*imr)) {
3253				ireq->i_len = len;
3254				return ENOMEM;
3255			}
3256			ireq->i_len = len;
3257			/* XXX M_WAIT? */
3258			p = malloc(len, M_TEMP, M_NOWAIT | M_ZERO);
3259			if (p == NULL)
3260				return ENOMEM;
3261			off = 0;
3262			MESH_RT_LOCK(ms);
3263			TAILQ_FOREACH(rt, &ms->ms_routes, rt_next) {
3264				if (off >= len)
3265					break;
3266				imr = (struct ieee80211req_mesh_route *)
3267				    (p + off);
3268				IEEE80211_ADDR_COPY(imr->imr_dest,
3269				    rt->rt_dest);
3270				IEEE80211_ADDR_COPY(imr->imr_nexthop,
3271				    rt->rt_nexthop);
3272				imr->imr_metric = rt->rt_metric;
3273				imr->imr_nhops = rt->rt_nhops;
3274				imr->imr_lifetime =
3275				    ieee80211_mesh_rt_update(rt, 0);
3276				imr->imr_lastmseq = rt->rt_lastmseq;
3277				imr->imr_flags = rt->rt_flags; /* last */
3278				off += sizeof(*imr);
3279			}
3280			MESH_RT_UNLOCK(ms);
3281			error = copyout(p, (uint8_t *)ireq->i_data,
3282			    ireq->i_len);
3283			free(p, M_TEMP);
3284			break;
3285		case IEEE80211_MESH_RTCMD_FLUSH:
3286		case IEEE80211_MESH_RTCMD_ADD:
3287		case IEEE80211_MESH_RTCMD_DELETE:
3288			return EINVAL;
3289		default:
3290			return ENOSYS;
3291		}
3292		break;
3293	case IEEE80211_IOC_MESH_PR_METRIC:
3294		len = strlen(ms->ms_pmetric->mpm_descr);
3295		if (ireq->i_len < len)
3296			return EINVAL;
3297		ireq->i_len = len;
3298		error = copyout(ms->ms_pmetric->mpm_descr,
3299		    (uint8_t *)ireq->i_data, len);
3300		break;
3301	case IEEE80211_IOC_MESH_PR_PATH:
3302		len = strlen(ms->ms_ppath->mpp_descr);
3303		if (ireq->i_len < len)
3304			return EINVAL;
3305		ireq->i_len = len;
3306		error = copyout(ms->ms_ppath->mpp_descr,
3307		    (uint8_t *)ireq->i_data, len);
3308		break;
3309	default:
3310		return ENOSYS;
3311	}
3312
3313	return error;
3314}
3315IEEE80211_IOCTL_GET(mesh, mesh_ioctl_get80211);
3316
3317static int
3318mesh_ioctl_set80211(struct ieee80211vap *vap, struct ieee80211req *ireq)
3319{
3320	struct ieee80211_mesh_state *ms = vap->iv_mesh;
3321	uint8_t tmpmeshid[IEEE80211_NWID_LEN];
3322	uint8_t tmpaddr[IEEE80211_ADDR_LEN];
3323	char tmpproto[IEEE80211_MESH_PROTO_DSZ];
3324	int error;
3325
3326	if (vap->iv_opmode != IEEE80211_M_MBSS)
3327		return ENOSYS;
3328
3329	error = 0;
3330	switch (ireq->i_type) {
3331	case IEEE80211_IOC_MESH_ID:
3332		if (ireq->i_val != 0 || ireq->i_len > IEEE80211_MESHID_LEN)
3333			return EINVAL;
3334		error = copyin(ireq->i_data, tmpmeshid, ireq->i_len);
3335		if (error != 0)
3336			break;
3337		memset(ms->ms_id, 0, IEEE80211_NWID_LEN);
3338		ms->ms_idlen = ireq->i_len;
3339		memcpy(ms->ms_id, tmpmeshid, ireq->i_len);
3340		error = ENETRESET;
3341		break;
3342	case IEEE80211_IOC_MESH_AP:
3343		if (ireq->i_val)
3344			ms->ms_flags |= IEEE80211_MESHFLAGS_AP;
3345		else
3346			ms->ms_flags &= ~IEEE80211_MESHFLAGS_AP;
3347		error = ENETRESET;
3348		break;
3349	case IEEE80211_IOC_MESH_FWRD:
3350		if (ireq->i_val)
3351			ms->ms_flags |= IEEE80211_MESHFLAGS_FWD;
3352		else
3353			ms->ms_flags &= ~IEEE80211_MESHFLAGS_FWD;
3354		mesh_gatemode_setup(vap);
3355		break;
3356	case IEEE80211_IOC_MESH_GATE:
3357		if (ireq->i_val)
3358			ms->ms_flags |= IEEE80211_MESHFLAGS_GATE;
3359		else
3360			ms->ms_flags &= ~IEEE80211_MESHFLAGS_GATE;
3361		break;
3362	case IEEE80211_IOC_MESH_TTL:
3363		ms->ms_ttl = (uint8_t) ireq->i_val;
3364		break;
3365	case IEEE80211_IOC_MESH_RTCMD:
3366		switch (ireq->i_val) {
3367		case IEEE80211_MESH_RTCMD_LIST:
3368			return EINVAL;
3369		case IEEE80211_MESH_RTCMD_FLUSH:
3370			ieee80211_mesh_rt_flush(vap);
3371			break;
3372		case IEEE80211_MESH_RTCMD_ADD:
3373			if (IEEE80211_ADDR_EQ(vap->iv_myaddr, ireq->i_data) ||
3374			    IEEE80211_ADDR_EQ(broadcastaddr, ireq->i_data))
3375				return EINVAL;
3376			error = copyin(ireq->i_data, &tmpaddr,
3377			    IEEE80211_ADDR_LEN);
3378			if (error == 0)
3379				ieee80211_mesh_discover(vap, tmpaddr, NULL);
3380			break;
3381		case IEEE80211_MESH_RTCMD_DELETE:
3382			ieee80211_mesh_rt_del(vap, ireq->i_data);
3383			break;
3384		default:
3385			return ENOSYS;
3386		}
3387		break;
3388	case IEEE80211_IOC_MESH_PR_METRIC:
3389		error = copyin(ireq->i_data, tmpproto, sizeof(tmpproto));
3390		if (error == 0) {
3391			error = mesh_select_proto_metric(vap, tmpproto);
3392			if (error == 0)
3393				error = ENETRESET;
3394		}
3395		break;
3396	case IEEE80211_IOC_MESH_PR_PATH:
3397		error = copyin(ireq->i_data, tmpproto, sizeof(tmpproto));
3398		if (error == 0) {
3399			error = mesh_select_proto_path(vap, tmpproto);
3400			if (error == 0)
3401				error = ENETRESET;
3402		}
3403		break;
3404	default:
3405		return ENOSYS;
3406	}
3407	return error;
3408}
3409IEEE80211_IOCTL_SET(mesh, mesh_ioctl_set80211);
3410