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