xref: /freebsd/sys/net80211/ieee80211_mesh.c (revision 6486b015fc84e96725fef22b0e3363351399ae83)
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$");
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 
65 static void	mesh_rt_flush_invalid(struct ieee80211vap *);
66 static int	mesh_select_proto_path(struct ieee80211vap *, const char *);
67 static int	mesh_select_proto_metric(struct ieee80211vap *, const char *);
68 static void	mesh_vattach(struct ieee80211vap *);
69 static int	mesh_newstate(struct ieee80211vap *, enum ieee80211_state, int);
70 static void	mesh_rt_cleanup_cb(void *);
71 static void	mesh_linkchange(struct ieee80211_node *,
72 		    enum ieee80211_mesh_mlstate);
73 static void	mesh_checkid(void *, struct ieee80211_node *);
74 static uint32_t	mesh_generateid(struct ieee80211vap *);
75 static int	mesh_checkpseq(struct ieee80211vap *,
76 		    const uint8_t [IEEE80211_ADDR_LEN], uint32_t);
77 static struct ieee80211_node *
78 		mesh_find_txnode(struct ieee80211vap *,
79 		    const uint8_t [IEEE80211_ADDR_LEN]);
80 static void	mesh_forward(struct ieee80211vap *, struct mbuf *,
81 		    const struct ieee80211_meshcntl *);
82 static int	mesh_input(struct ieee80211_node *, struct mbuf *, int, int);
83 static void	mesh_recv_mgmt(struct ieee80211_node *, struct mbuf *, int,
84 		    int, int);
85 static void	mesh_recv_ctl(struct ieee80211_node *, struct mbuf *, int);
86 static void	mesh_peer_timeout_setup(struct ieee80211_node *);
87 static void	mesh_peer_timeout_backoff(struct ieee80211_node *);
88 static void	mesh_peer_timeout_cb(void *);
89 static __inline void
90 		mesh_peer_timeout_stop(struct ieee80211_node *);
91 static int	mesh_verify_meshid(struct ieee80211vap *, const uint8_t *);
92 static int	mesh_verify_meshconf(struct ieee80211vap *, const uint8_t *);
93 static int	mesh_verify_meshpeer(struct ieee80211vap *, uint8_t,
94     		    const uint8_t *);
95 uint32_t	mesh_airtime_calc(struct ieee80211_node *);
96 
97 /*
98  * Timeout values come from the specification and are in milliseconds.
99  */
100 static SYSCTL_NODE(_net_wlan, OID_AUTO, mesh, CTLFLAG_RD, 0,
101     "IEEE 802.11s parameters");
102 static int ieee80211_mesh_retrytimeout = -1;
103 SYSCTL_PROC(_net_wlan_mesh, OID_AUTO, retrytimeout, CTLTYPE_INT | CTLFLAG_RW,
104     &ieee80211_mesh_retrytimeout, 0, ieee80211_sysctl_msecs_ticks, "I",
105     "Retry timeout (msec)");
106 static int ieee80211_mesh_holdingtimeout = -1;
107 SYSCTL_PROC(_net_wlan_mesh, OID_AUTO, holdingtimeout, CTLTYPE_INT | CTLFLAG_RW,
108     &ieee80211_mesh_holdingtimeout, 0, ieee80211_sysctl_msecs_ticks, "I",
109     "Holding state timeout (msec)");
110 static int ieee80211_mesh_confirmtimeout = -1;
111 SYSCTL_PROC(_net_wlan_mesh, OID_AUTO, confirmtimeout, CTLTYPE_INT | CTLFLAG_RW,
112     &ieee80211_mesh_confirmtimeout, 0, ieee80211_sysctl_msecs_ticks, "I",
113     "Confirm state timeout (msec)");
114 static int ieee80211_mesh_maxretries = 2;
115 SYSCTL_INT(_net_wlan_mesh, OID_AUTO, maxretries, CTLTYPE_INT | CTLFLAG_RW,
116     &ieee80211_mesh_maxretries, 0,
117     "Maximum retries during peer link establishment");
118 
119 static const uint8_t broadcastaddr[IEEE80211_ADDR_LEN] =
120 	{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
121 
122 static	ieee80211_recv_action_func mesh_recv_action_meshpeering_open;
123 static	ieee80211_recv_action_func mesh_recv_action_meshpeering_confirm;
124 static	ieee80211_recv_action_func mesh_recv_action_meshpeering_close;
125 static	ieee80211_recv_action_func mesh_recv_action_meshlmetric;
126 
127 static	ieee80211_send_action_func mesh_send_action_meshpeering_open;
128 static	ieee80211_send_action_func mesh_send_action_meshpeering_confirm;
129 static	ieee80211_send_action_func mesh_send_action_meshpeering_close;
130 static	ieee80211_send_action_func mesh_send_action_meshlmetric;
131 
132 static const struct ieee80211_mesh_proto_metric mesh_metric_airtime = {
133 	.mpm_descr	= "AIRTIME",
134 	.mpm_ie		= IEEE80211_MESHCONF_METRIC_AIRTIME,
135 	.mpm_metric	= mesh_airtime_calc,
136 };
137 
138 static struct ieee80211_mesh_proto_path		mesh_proto_paths[4];
139 static struct ieee80211_mesh_proto_metric	mesh_proto_metrics[4];
140 
141 #define	MESH_RT_LOCK(ms)	mtx_lock(&(ms)->ms_rt_lock)
142 #define	MESH_RT_LOCK_ASSERT(ms)	mtx_assert(&(ms)->ms_rt_lock, MA_OWNED)
143 #define	MESH_RT_UNLOCK(ms)	mtx_unlock(&(ms)->ms_rt_lock)
144 
145 MALLOC_DEFINE(M_80211_MESH_PREQ, "80211preq", "802.11 MESH Path Request frame");
146 MALLOC_DEFINE(M_80211_MESH_PREP, "80211prep", "802.11 MESH Path Reply frame");
147 MALLOC_DEFINE(M_80211_MESH_PERR, "80211perr", "802.11 MESH Path Error frame");
148 
149 MALLOC_DEFINE(M_80211_MESH_RT, "80211mesh", "802.11s routing table");
150 
151 /*
152  * Helper functions to manipulate the Mesh routing table.
153  */
154 
155 static struct ieee80211_mesh_route *
156 mesh_rt_find_locked(struct ieee80211_mesh_state *ms,
157     const uint8_t dest[IEEE80211_ADDR_LEN])
158 {
159 	struct ieee80211_mesh_route *rt;
160 
161 	MESH_RT_LOCK_ASSERT(ms);
162 
163 	TAILQ_FOREACH(rt, &ms->ms_routes, rt_next) {
164 		if (IEEE80211_ADDR_EQ(dest, rt->rt_dest))
165 			return rt;
166 	}
167 	return NULL;
168 }
169 
170 static struct ieee80211_mesh_route *
171 mesh_rt_add_locked(struct ieee80211_mesh_state *ms,
172     const uint8_t dest[IEEE80211_ADDR_LEN])
173 {
174 	struct ieee80211_mesh_route *rt;
175 
176 	KASSERT(!IEEE80211_ADDR_EQ(broadcastaddr, dest),
177 	    ("%s: adding broadcast to the routing table", __func__));
178 
179 	MESH_RT_LOCK_ASSERT(ms);
180 
181 	rt = malloc(ALIGN(sizeof(struct ieee80211_mesh_route)) +
182 	    ms->ms_ppath->mpp_privlen, M_80211_MESH_RT, M_NOWAIT | M_ZERO);
183 	if (rt != NULL) {
184 		IEEE80211_ADDR_COPY(rt->rt_dest, dest);
185 		rt->rt_priv = (void *)ALIGN(&rt[1]);
186 		rt->rt_crtime = ticks;
187 		TAILQ_INSERT_TAIL(&ms->ms_routes, rt, rt_next);
188 	}
189 	return rt;
190 }
191 
192 struct ieee80211_mesh_route *
193 ieee80211_mesh_rt_find(struct ieee80211vap *vap,
194     const uint8_t dest[IEEE80211_ADDR_LEN])
195 {
196 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
197 	struct ieee80211_mesh_route *rt;
198 
199 	MESH_RT_LOCK(ms);
200 	rt = mesh_rt_find_locked(ms, dest);
201 	MESH_RT_UNLOCK(ms);
202 	return rt;
203 }
204 
205 struct ieee80211_mesh_route *
206 ieee80211_mesh_rt_add(struct ieee80211vap *vap,
207     const uint8_t dest[IEEE80211_ADDR_LEN])
208 {
209 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
210 	struct ieee80211_mesh_route *rt;
211 
212 	KASSERT(ieee80211_mesh_rt_find(vap, dest) == NULL,
213 	    ("%s: duplicate entry in the routing table", __func__));
214 	KASSERT(!IEEE80211_ADDR_EQ(vap->iv_myaddr, dest),
215 	    ("%s: adding self to the routing table", __func__));
216 
217 	MESH_RT_LOCK(ms);
218 	rt = mesh_rt_add_locked(ms, dest);
219 	MESH_RT_UNLOCK(ms);
220 	return rt;
221 }
222 
223 /*
224  * Add a proxy route (as needed) for the specified destination.
225  */
226 void
227 ieee80211_mesh_proxy_check(struct ieee80211vap *vap,
228     const uint8_t dest[IEEE80211_ADDR_LEN])
229 {
230 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
231 	struct ieee80211_mesh_route *rt;
232 
233 	MESH_RT_LOCK(ms);
234 	rt = mesh_rt_find_locked(ms, dest);
235 	if (rt == NULL) {
236 		rt = mesh_rt_add_locked(ms, dest);
237 		if (rt == NULL) {
238 			IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, dest,
239 			    "%s", "unable to add proxy entry");
240 			vap->iv_stats.is_mesh_rtaddfailed++;
241 		} else {
242 			IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, dest,
243 			    "%s", "add proxy entry");
244 			IEEE80211_ADDR_COPY(rt->rt_nexthop, vap->iv_myaddr);
245 			rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID
246 				     |  IEEE80211_MESHRT_FLAGS_PROXY;
247 		}
248 	/* XXX assert PROXY? */
249 	} else if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) {
250 		struct ieee80211com *ic = vap->iv_ic;
251 		/*
252 		 * Fix existing entry created by received frames from
253 		 * stations that have some memory of dest.  We also
254 		 * flush any frames held on the staging queue; delivering
255 		 * them is too much trouble right now.
256 		 */
257 		IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, dest,
258 		    "%s", "fix proxy entry");
259 		IEEE80211_ADDR_COPY(rt->rt_nexthop, vap->iv_myaddr);
260 		rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID
261 			     |  IEEE80211_MESHRT_FLAGS_PROXY;
262 		/* XXX belongs in hwmp */
263 		ieee80211_ageq_drain_node(&ic->ic_stageq,
264 		   (void *)(uintptr_t) ieee80211_mac_hash(ic, dest));
265 		/* XXX stat? */
266 	}
267 	MESH_RT_UNLOCK(ms);
268 }
269 
270 static __inline void
271 mesh_rt_del(struct ieee80211_mesh_state *ms, struct ieee80211_mesh_route *rt)
272 {
273 	TAILQ_REMOVE(&ms->ms_routes, rt, rt_next);
274 	free(rt, M_80211_MESH_RT);
275 }
276 
277 void
278 ieee80211_mesh_rt_del(struct ieee80211vap *vap,
279     const uint8_t dest[IEEE80211_ADDR_LEN])
280 {
281 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
282 	struct ieee80211_mesh_route *rt, *next;
283 
284 	MESH_RT_LOCK(ms);
285 	TAILQ_FOREACH_SAFE(rt, &ms->ms_routes, rt_next, next) {
286 		if (IEEE80211_ADDR_EQ(rt->rt_dest, dest)) {
287 			mesh_rt_del(ms, rt);
288 			MESH_RT_UNLOCK(ms);
289 			return;
290 		}
291 	}
292 	MESH_RT_UNLOCK(ms);
293 }
294 
295 void
296 ieee80211_mesh_rt_flush(struct ieee80211vap *vap)
297 {
298 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
299 	struct ieee80211_mesh_route *rt, *next;
300 
301 	if (ms == NULL)
302 		return;
303 	MESH_RT_LOCK(ms);
304 	TAILQ_FOREACH_SAFE(rt, &ms->ms_routes, rt_next, next)
305 		mesh_rt_del(ms, rt);
306 	MESH_RT_UNLOCK(ms);
307 }
308 
309 void
310 ieee80211_mesh_rt_flush_peer(struct ieee80211vap *vap,
311     const uint8_t peer[IEEE80211_ADDR_LEN])
312 {
313 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
314 	struct ieee80211_mesh_route *rt, *next;
315 
316 	MESH_RT_LOCK(ms);
317 	TAILQ_FOREACH_SAFE(rt, &ms->ms_routes, rt_next, next) {
318 		if (IEEE80211_ADDR_EQ(rt->rt_nexthop, peer))
319 			mesh_rt_del(ms, rt);
320 	}
321 	MESH_RT_UNLOCK(ms);
322 }
323 
324 /*
325  * Flush expired routing entries, i.e. those in invalid state for
326  * some time.
327  */
328 static void
329 mesh_rt_flush_invalid(struct ieee80211vap *vap)
330 {
331 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
332 	struct ieee80211_mesh_route *rt, *next;
333 
334 	if (ms == NULL)
335 		return;
336 	MESH_RT_LOCK(ms);
337 	TAILQ_FOREACH_SAFE(rt, &ms->ms_routes, rt_next, next) {
338 		if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0 &&
339 		    ticks - rt->rt_crtime >= ms->ms_ppath->mpp_inact)
340 			mesh_rt_del(ms, rt);
341 	}
342 	MESH_RT_UNLOCK(ms);
343 }
344 
345 #define	N(a)	(sizeof(a) / sizeof(a[0]))
346 int
347 ieee80211_mesh_register_proto_path(const struct ieee80211_mesh_proto_path *mpp)
348 {
349 	int i, firstempty = -1;
350 
351 	for (i = 0; i < N(mesh_proto_paths); i++) {
352 		if (strncmp(mpp->mpp_descr, mesh_proto_paths[i].mpp_descr,
353 		    IEEE80211_MESH_PROTO_DSZ) == 0)
354 			return EEXIST;
355 		if (!mesh_proto_paths[i].mpp_active && firstempty == -1)
356 			firstempty = i;
357 	}
358 	if (firstempty < 0)
359 		return ENOSPC;
360 	memcpy(&mesh_proto_paths[firstempty], mpp, sizeof(*mpp));
361 	mesh_proto_paths[firstempty].mpp_active = 1;
362 	return 0;
363 }
364 
365 int
366 ieee80211_mesh_register_proto_metric(const struct
367     ieee80211_mesh_proto_metric *mpm)
368 {
369 	int i, firstempty = -1;
370 
371 	for (i = 0; i < N(mesh_proto_metrics); i++) {
372 		if (strncmp(mpm->mpm_descr, mesh_proto_metrics[i].mpm_descr,
373 		    IEEE80211_MESH_PROTO_DSZ) == 0)
374 			return EEXIST;
375 		if (!mesh_proto_metrics[i].mpm_active && firstempty == -1)
376 			firstempty = i;
377 	}
378 	if (firstempty < 0)
379 		return ENOSPC;
380 	memcpy(&mesh_proto_metrics[firstempty], mpm, sizeof(*mpm));
381 	mesh_proto_metrics[firstempty].mpm_active = 1;
382 	return 0;
383 }
384 
385 static int
386 mesh_select_proto_path(struct ieee80211vap *vap, const char *name)
387 {
388 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
389 	int i;
390 
391 	for (i = 0; i < N(mesh_proto_paths); i++) {
392 		if (strcasecmp(mesh_proto_paths[i].mpp_descr, name) == 0) {
393 			ms->ms_ppath = &mesh_proto_paths[i];
394 			return 0;
395 		}
396 	}
397 	return ENOENT;
398 }
399 
400 static int
401 mesh_select_proto_metric(struct ieee80211vap *vap, const char *name)
402 {
403 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
404 	int i;
405 
406 	for (i = 0; i < N(mesh_proto_metrics); i++) {
407 		if (strcasecmp(mesh_proto_metrics[i].mpm_descr, name) == 0) {
408 			ms->ms_pmetric = &mesh_proto_metrics[i];
409 			return 0;
410 		}
411 	}
412 	return ENOENT;
413 }
414 #undef	N
415 
416 static void
417 ieee80211_mesh_init(void)
418 {
419 
420 	memset(mesh_proto_paths, 0, sizeof(mesh_proto_paths));
421 	memset(mesh_proto_metrics, 0, sizeof(mesh_proto_metrics));
422 
423 	/*
424 	 * Setup mesh parameters that depends on the clock frequency.
425 	 */
426 	ieee80211_mesh_retrytimeout = msecs_to_ticks(40);
427 	ieee80211_mesh_holdingtimeout = msecs_to_ticks(40);
428 	ieee80211_mesh_confirmtimeout = msecs_to_ticks(40);
429 
430 	/*
431 	 * Register action frame handlers.
432 	 */
433 	ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESHPEERING,
434 	    IEEE80211_ACTION_MESHPEERING_OPEN,
435 	    mesh_recv_action_meshpeering_open);
436 	ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESHPEERING,
437 	    IEEE80211_ACTION_MESHPEERING_CONFIRM,
438 	    mesh_recv_action_meshpeering_confirm);
439 	ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESHPEERING,
440 	    IEEE80211_ACTION_MESHPEERING_CLOSE,
441 	    mesh_recv_action_meshpeering_close);
442 	ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESH,
443 	    IEEE80211_ACTION_MESH_LMETRIC, mesh_recv_action_meshlmetric);
444 
445 	ieee80211_send_action_register(IEEE80211_ACTION_CAT_MESHPEERING,
446 	    IEEE80211_ACTION_MESHPEERING_OPEN,
447 	    mesh_send_action_meshpeering_open);
448 	ieee80211_send_action_register(IEEE80211_ACTION_CAT_MESHPEERING,
449 	    IEEE80211_ACTION_MESHPEERING_CONFIRM,
450 	    mesh_send_action_meshpeering_confirm);
451 	ieee80211_send_action_register(IEEE80211_ACTION_CAT_MESHPEERING,
452 	    IEEE80211_ACTION_MESHPEERING_CLOSE,
453 	    mesh_send_action_meshpeering_close);
454 	ieee80211_send_action_register(IEEE80211_ACTION_CAT_MESH,
455 	    IEEE80211_ACTION_MESH_LMETRIC,
456 	    mesh_send_action_meshlmetric);
457 
458 	/*
459 	 * Register Airtime Link Metric.
460 	 */
461 	ieee80211_mesh_register_proto_metric(&mesh_metric_airtime);
462 
463 }
464 SYSINIT(wlan_mesh, SI_SUB_DRIVERS, SI_ORDER_FIRST, ieee80211_mesh_init, NULL);
465 
466 void
467 ieee80211_mesh_attach(struct ieee80211com *ic)
468 {
469 	ic->ic_vattach[IEEE80211_M_MBSS] = mesh_vattach;
470 }
471 
472 void
473 ieee80211_mesh_detach(struct ieee80211com *ic)
474 {
475 }
476 
477 static void
478 mesh_vdetach_peers(void *arg, struct ieee80211_node *ni)
479 {
480 	struct ieee80211com *ic = ni->ni_ic;
481 	uint16_t args[3];
482 
483 	if (ni->ni_mlstate == IEEE80211_NODE_MESH_ESTABLISHED) {
484 		args[0] = ni->ni_mlpid;
485 		args[1] = ni->ni_mllid;
486 		args[2] = IEEE80211_REASON_PEER_LINK_CANCELED;
487 		ieee80211_send_action(ni,
488 		    IEEE80211_ACTION_CAT_MESHPEERING,
489 		    IEEE80211_ACTION_MESHPEERING_CLOSE,
490 		    args);
491 	}
492 	callout_drain(&ni->ni_mltimer);
493 	/* XXX belongs in hwmp */
494 	ieee80211_ageq_drain_node(&ic->ic_stageq,
495 	   (void *)(uintptr_t) ieee80211_mac_hash(ic, ni->ni_macaddr));
496 }
497 
498 static void
499 mesh_vdetach(struct ieee80211vap *vap)
500 {
501 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
502 
503 	callout_drain(&ms->ms_cleantimer);
504 	ieee80211_iterate_nodes(&vap->iv_ic->ic_sta, mesh_vdetach_peers,
505 	    NULL);
506 	ieee80211_mesh_rt_flush(vap);
507 	mtx_destroy(&ms->ms_rt_lock);
508 	ms->ms_ppath->mpp_vdetach(vap);
509 	free(vap->iv_mesh, M_80211_VAP);
510 	vap->iv_mesh = NULL;
511 }
512 
513 static void
514 mesh_vattach(struct ieee80211vap *vap)
515 {
516 	struct ieee80211_mesh_state *ms;
517 	vap->iv_newstate = mesh_newstate;
518 	vap->iv_input = mesh_input;
519 	vap->iv_opdetach = mesh_vdetach;
520 	vap->iv_recv_mgmt = mesh_recv_mgmt;
521 	vap->iv_recv_ctl = mesh_recv_ctl;
522 	ms = malloc(sizeof(struct ieee80211_mesh_state), M_80211_VAP,
523 	    M_NOWAIT | M_ZERO);
524 	if (ms == NULL) {
525 		printf("%s: couldn't alloc MBSS state\n", __func__);
526 		return;
527 	}
528 	vap->iv_mesh = ms;
529 	ms->ms_seq = 0;
530 	ms->ms_flags = (IEEE80211_MESHFLAGS_AP | IEEE80211_MESHFLAGS_FWD);
531 	ms->ms_ttl = IEEE80211_MESH_DEFAULT_TTL;
532 	TAILQ_INIT(&ms->ms_routes);
533 	mtx_init(&ms->ms_rt_lock, "MBSS", "802.11s routing table", MTX_DEF);
534 	callout_init(&ms->ms_cleantimer, CALLOUT_MPSAFE);
535 	mesh_select_proto_metric(vap, "AIRTIME");
536 	KASSERT(ms->ms_pmetric, ("ms_pmetric == NULL"));
537 	mesh_select_proto_path(vap, "HWMP");
538 	KASSERT(ms->ms_ppath, ("ms_ppath == NULL"));
539 	ms->ms_ppath->mpp_vattach(vap);
540 }
541 
542 /*
543  * IEEE80211_M_MBSS vap state machine handler.
544  */
545 static int
546 mesh_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
547 {
548 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
549 	struct ieee80211com *ic = vap->iv_ic;
550 	struct ieee80211_node *ni;
551 	enum ieee80211_state ostate;
552 
553 	IEEE80211_LOCK_ASSERT(ic);
554 
555 	ostate = vap->iv_state;
556 	IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE, "%s: %s -> %s (%d)\n",
557 	    __func__, ieee80211_state_name[ostate],
558 	    ieee80211_state_name[nstate], arg);
559 	vap->iv_state = nstate;		/* state transition */
560 	if (ostate != IEEE80211_S_SCAN)
561 		ieee80211_cancel_scan(vap);	/* background scan */
562 	ni = vap->iv_bss;			/* NB: no reference held */
563 	if (nstate != IEEE80211_S_RUN && ostate == IEEE80211_S_RUN)
564 		callout_drain(&ms->ms_cleantimer);
565 	switch (nstate) {
566 	case IEEE80211_S_INIT:
567 		switch (ostate) {
568 		case IEEE80211_S_SCAN:
569 			ieee80211_cancel_scan(vap);
570 			break;
571 		case IEEE80211_S_CAC:
572 			ieee80211_dfs_cac_stop(vap);
573 			break;
574 		case IEEE80211_S_RUN:
575 			ieee80211_iterate_nodes(&ic->ic_sta,
576 			    mesh_vdetach_peers, NULL);
577 			break;
578 		default:
579 			break;
580 		}
581 		if (ostate != IEEE80211_S_INIT) {
582 			/* NB: optimize INIT -> INIT case */
583 			ieee80211_reset_bss(vap);
584 			ieee80211_mesh_rt_flush(vap);
585 		}
586 		break;
587 	case IEEE80211_S_SCAN:
588 		switch (ostate) {
589 		case IEEE80211_S_INIT:
590 			if (vap->iv_des_chan != IEEE80211_CHAN_ANYC &&
591 			    !IEEE80211_IS_CHAN_RADAR(vap->iv_des_chan) &&
592 			    ms->ms_idlen != 0) {
593 				/*
594 				 * Already have a channel and a mesh ID; bypass
595 				 * the scan and startup immediately.
596 				 */
597 				ieee80211_create_ibss(vap, vap->iv_des_chan);
598 				break;
599 			}
600 			/*
601 			 * Initiate a scan.  We can come here as a result
602 			 * of an IEEE80211_IOC_SCAN_REQ too in which case
603 			 * the vap will be marked with IEEE80211_FEXT_SCANREQ
604 			 * and the scan request parameters will be present
605 			 * in iv_scanreq.  Otherwise we do the default.
606 			*/
607 			if (vap->iv_flags_ext & IEEE80211_FEXT_SCANREQ) {
608 				ieee80211_check_scan(vap,
609 				    vap->iv_scanreq_flags,
610 				    vap->iv_scanreq_duration,
611 				    vap->iv_scanreq_mindwell,
612 				    vap->iv_scanreq_maxdwell,
613 				    vap->iv_scanreq_nssid, vap->iv_scanreq_ssid);
614 				vap->iv_flags_ext &= ~IEEE80211_FEXT_SCANREQ;
615 			} else
616 				ieee80211_check_scan_current(vap);
617 			break;
618 		default:
619 			break;
620 		}
621 		break;
622 	case IEEE80211_S_CAC:
623 		/*
624 		 * Start CAC on a DFS channel.  We come here when starting
625 		 * a bss on a DFS channel (see ieee80211_create_ibss).
626 		 */
627 		ieee80211_dfs_cac_start(vap);
628 		break;
629 	case IEEE80211_S_RUN:
630 		switch (ostate) {
631 		case IEEE80211_S_INIT:
632 			/*
633 			 * Already have a channel; bypass the
634 			 * scan and startup immediately.
635 			 * Note that ieee80211_create_ibss will call
636 			 * back to do a RUN->RUN state change.
637 			 */
638 			ieee80211_create_ibss(vap,
639 			    ieee80211_ht_adjust_channel(ic,
640 				ic->ic_curchan, vap->iv_flags_ht));
641 			/* NB: iv_bss is changed on return */
642 			break;
643 		case IEEE80211_S_CAC:
644 			/*
645 			 * NB: This is the normal state change when CAC
646 			 * expires and no radar was detected; no need to
647 			 * clear the CAC timer as it's already expired.
648 			 */
649 			/* fall thru... */
650 		case IEEE80211_S_CSA:
651 #if 0
652 			/*
653 			 * Shorten inactivity timer of associated stations
654 			 * to weed out sta's that don't follow a CSA.
655 			 */
656 			ieee80211_iterate_nodes(&ic->ic_sta, sta_csa, vap);
657 #endif
658 			/*
659 			 * Update bss node channel to reflect where
660 			 * we landed after CSA.
661 			 */
662 			ieee80211_node_set_chan(vap->iv_bss,
663 			    ieee80211_ht_adjust_channel(ic, ic->ic_curchan,
664 				ieee80211_htchanflags(vap->iv_bss->ni_chan)));
665 			/* XXX bypass debug msgs */
666 			break;
667 		case IEEE80211_S_SCAN:
668 		case IEEE80211_S_RUN:
669 #ifdef IEEE80211_DEBUG
670 			if (ieee80211_msg_debug(vap)) {
671 				struct ieee80211_node *ni = vap->iv_bss;
672 				ieee80211_note(vap,
673 				    "synchronized with %s meshid ",
674 				    ether_sprintf(ni->ni_meshid));
675 				ieee80211_print_essid(ni->ni_meshid,
676 				    ni->ni_meshidlen);
677 				/* XXX MCS/HT */
678 				printf(" channel %d\n",
679 				    ieee80211_chan2ieee(ic, ic->ic_curchan));
680 			}
681 #endif
682 			break;
683 		default:
684 			break;
685 		}
686 		ieee80211_node_authorize(vap->iv_bss);
687 		callout_reset(&ms->ms_cleantimer, ms->ms_ppath->mpp_inact,
688                     mesh_rt_cleanup_cb, vap);
689 		break;
690 	default:
691 		break;
692 	}
693 	/* NB: ostate not nstate */
694 	ms->ms_ppath->mpp_newstate(vap, ostate, arg);
695 	return 0;
696 }
697 
698 static void
699 mesh_rt_cleanup_cb(void *arg)
700 {
701 	struct ieee80211vap *vap = arg;
702 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
703 
704 	mesh_rt_flush_invalid(vap);
705 	callout_reset(&ms->ms_cleantimer, ms->ms_ppath->mpp_inact,
706 	    mesh_rt_cleanup_cb, vap);
707 }
708 
709 
710 /*
711  * Helper function to note the Mesh Peer Link FSM change.
712  */
713 static void
714 mesh_linkchange(struct ieee80211_node *ni, enum ieee80211_mesh_mlstate state)
715 {
716 	struct ieee80211vap *vap = ni->ni_vap;
717 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
718 #ifdef IEEE80211_DEBUG
719 	static const char *meshlinkstates[] = {
720 		[IEEE80211_NODE_MESH_IDLE]		= "IDLE",
721 		[IEEE80211_NODE_MESH_OPENSNT]		= "OPEN SENT",
722 		[IEEE80211_NODE_MESH_OPENRCV]		= "OPEN RECEIVED",
723 		[IEEE80211_NODE_MESH_CONFIRMRCV]	= "CONFIRM RECEIVED",
724 		[IEEE80211_NODE_MESH_ESTABLISHED]	= "ESTABLISHED",
725 		[IEEE80211_NODE_MESH_HOLDING]		= "HOLDING"
726 	};
727 #endif
728 	IEEE80211_NOTE(vap, IEEE80211_MSG_MESH,
729 	    ni, "peer link: %s -> %s",
730 	    meshlinkstates[ni->ni_mlstate], meshlinkstates[state]);
731 
732 	/* track neighbor count */
733 	if (state == IEEE80211_NODE_MESH_ESTABLISHED &&
734 	    ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED) {
735 		KASSERT(ms->ms_neighbors < 65535, ("neighbor count overflow"));
736 		ms->ms_neighbors++;
737 		ieee80211_beacon_notify(vap, IEEE80211_BEACON_MESHCONF);
738 	} else if (ni->ni_mlstate == IEEE80211_NODE_MESH_ESTABLISHED &&
739 	    state != IEEE80211_NODE_MESH_ESTABLISHED) {
740 		KASSERT(ms->ms_neighbors > 0, ("neighbor count 0"));
741 		ms->ms_neighbors--;
742 		ieee80211_beacon_notify(vap, IEEE80211_BEACON_MESHCONF);
743 	}
744 	ni->ni_mlstate = state;
745 	switch (state) {
746 	case IEEE80211_NODE_MESH_HOLDING:
747 		ms->ms_ppath->mpp_peerdown(ni);
748 		break;
749 	case IEEE80211_NODE_MESH_ESTABLISHED:
750 		ieee80211_mesh_discover(vap, ni->ni_macaddr, NULL);
751 		break;
752 	default:
753 		break;
754 	}
755 }
756 
757 /*
758  * Helper function to generate a unique local ID required for mesh
759  * peer establishment.
760  */
761 static void
762 mesh_checkid(void *arg, struct ieee80211_node *ni)
763 {
764 	uint16_t *r = arg;
765 
766 	if (*r == ni->ni_mllid)
767 		*(uint16_t *)arg = 0;
768 }
769 
770 static uint32_t
771 mesh_generateid(struct ieee80211vap *vap)
772 {
773 	int maxiter = 4;
774 	uint16_t r;
775 
776 	do {
777 		get_random_bytes(&r, 2);
778 		ieee80211_iterate_nodes(&vap->iv_ic->ic_sta, mesh_checkid, &r);
779 		maxiter--;
780 	} while (r == 0 && maxiter > 0);
781 	return r;
782 }
783 
784 /*
785  * Verifies if we already received this packet by checking its
786  * sequence number.
787  * Returns 0 if the frame is to be accepted, 1 otherwise.
788  */
789 static int
790 mesh_checkpseq(struct ieee80211vap *vap,
791     const uint8_t source[IEEE80211_ADDR_LEN], uint32_t seq)
792 {
793 	struct ieee80211_mesh_route *rt;
794 
795 	rt = ieee80211_mesh_rt_find(vap, source);
796 	if (rt == NULL) {
797 		rt = ieee80211_mesh_rt_add(vap, source);
798 		if (rt == NULL) {
799 			IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, source,
800 			    "%s", "add mcast route failed");
801 			vap->iv_stats.is_mesh_rtaddfailed++;
802 			return 1;
803 		}
804 		IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, source,
805 		    "add mcast route, mesh seqno %d", seq);
806 		rt->rt_lastmseq = seq;
807 		return 0;
808 	}
809 	if (IEEE80211_MESH_SEQ_GEQ(rt->rt_lastmseq, seq)) {
810 		return 1;
811 	} else {
812 		rt->rt_lastmseq = seq;
813 		return 0;
814 	}
815 }
816 
817 /*
818  * Iterate the routing table and locate the next hop.
819  */
820 static struct ieee80211_node *
821 mesh_find_txnode(struct ieee80211vap *vap,
822     const uint8_t dest[IEEE80211_ADDR_LEN])
823 {
824 	struct ieee80211_mesh_route *rt;
825 
826 	rt = ieee80211_mesh_rt_find(vap, dest);
827 	if (rt == NULL)
828 		return NULL;
829 	if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0 ||
830 	    (rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY)) {
831 		IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, dest,
832 		    "%s: !valid or proxy, flags 0x%x", __func__, rt->rt_flags);
833 		/* XXX stat */
834 		return NULL;
835 	}
836 	return ieee80211_find_txnode(vap, rt->rt_nexthop);
837 }
838 
839 /*
840  * Forward the specified frame.
841  * Decrement the TTL and set TA to our MAC address.
842  */
843 static void
844 mesh_forward(struct ieee80211vap *vap, struct mbuf *m,
845     const struct ieee80211_meshcntl *mc)
846 {
847 	struct ieee80211com *ic = vap->iv_ic;
848 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
849 	struct ifnet *ifp = vap->iv_ifp;
850 	struct ifnet *parent = ic->ic_ifp;
851 	const struct ieee80211_frame *wh =
852 	    mtod(m, const struct ieee80211_frame *);
853 	struct mbuf *mcopy;
854 	struct ieee80211_meshcntl *mccopy;
855 	struct ieee80211_frame *whcopy;
856 	struct ieee80211_node *ni;
857 	int err;
858 
859 	if (mc->mc_ttl == 0) {
860 		IEEE80211_NOTE_FRAME(vap, IEEE80211_MSG_MESH, wh,
861 		    "%s", "frame not fwd'd, ttl 0");
862 		vap->iv_stats.is_mesh_fwd_ttl++;
863 		return;
864 	}
865 	if (!(ms->ms_flags & IEEE80211_MESHFLAGS_FWD)) {
866 		IEEE80211_NOTE_FRAME(vap, IEEE80211_MSG_MESH, wh,
867 		    "%s", "frame not fwd'd, fwding disabled");
868 		vap->iv_stats.is_mesh_fwd_disabled++;
869 		return;
870 	}
871 	mcopy = m_dup(m, M_DONTWAIT);
872 	if (mcopy == NULL) {
873 		IEEE80211_NOTE_FRAME(vap, IEEE80211_MSG_MESH, wh,
874 		    "%s", "frame not fwd'd, cannot dup");
875 		vap->iv_stats.is_mesh_fwd_nobuf++;
876 		ifp->if_oerrors++;
877 		return;
878 	}
879 	mcopy = m_pullup(mcopy, ieee80211_hdrspace(ic, wh) +
880 	    sizeof(struct ieee80211_meshcntl));
881 	if (mcopy == NULL) {
882 		IEEE80211_NOTE_FRAME(vap, IEEE80211_MSG_MESH, wh,
883 		    "%s", "frame not fwd'd, too short");
884 		vap->iv_stats.is_mesh_fwd_tooshort++;
885 		ifp->if_oerrors++;
886 		m_freem(mcopy);
887 		return;
888 	}
889 	whcopy = mtod(mcopy, struct ieee80211_frame *);
890 	mccopy = (struct ieee80211_meshcntl *)
891 	    (mtod(mcopy, uint8_t *) + ieee80211_hdrspace(ic, wh));
892 	/* XXX clear other bits? */
893 	whcopy->i_fc[1] &= ~IEEE80211_FC1_RETRY;
894 	IEEE80211_ADDR_COPY(whcopy->i_addr2, vap->iv_myaddr);
895 	if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
896 		ni = ieee80211_ref_node(vap->iv_bss);
897 		mcopy->m_flags |= M_MCAST;
898 	} else {
899 		ni = mesh_find_txnode(vap, whcopy->i_addr3);
900 		if (ni == NULL) {
901 			IEEE80211_NOTE_FRAME(vap, IEEE80211_MSG_MESH, wh,
902 			    "%s", "frame not fwd'd, no path");
903 			vap->iv_stats.is_mesh_fwd_nopath++;
904 			m_freem(mcopy);
905 			return;
906 		}
907 		IEEE80211_ADDR_COPY(whcopy->i_addr1, ni->ni_macaddr);
908 	}
909 	KASSERT(mccopy->mc_ttl > 0, ("%s called with wrong ttl", __func__));
910 	mccopy->mc_ttl--;
911 
912 	/* XXX calculate priority so drivers can find the tx queue */
913 	M_WME_SETAC(mcopy, WME_AC_BE);
914 
915 	/* XXX do we know m_nextpkt is NULL? */
916 	mcopy->m_pkthdr.rcvif = (void *) ni;
917 	err = parent->if_transmit(parent, mcopy);
918 	if (err != 0) {
919 		/* NB: IFQ_HANDOFF reclaims mbuf */
920 		ieee80211_free_node(ni);
921 	} else {
922 		ifp->if_opackets++;
923 	}
924 }
925 
926 static struct mbuf *
927 mesh_decap(struct ieee80211vap *vap, struct mbuf *m, int hdrlen, int meshdrlen)
928 {
929 #define	WHDIR(wh) ((wh)->i_fc[1] & IEEE80211_FC1_DIR_MASK)
930 	uint8_t b[sizeof(struct ieee80211_qosframe_addr4) +
931 		  sizeof(struct ieee80211_meshcntl_ae11)];
932 	const struct ieee80211_qosframe_addr4 *wh;
933 	const struct ieee80211_meshcntl_ae10 *mc;
934 	struct ether_header *eh;
935 	struct llc *llc;
936 	int ae;
937 
938 	if (m->m_len < hdrlen + sizeof(*llc) &&
939 	    (m = m_pullup(m, hdrlen + sizeof(*llc))) == NULL) {
940 		IEEE80211_DPRINTF(vap, IEEE80211_MSG_ANY,
941 		    "discard data frame: %s", "m_pullup failed");
942 		vap->iv_stats.is_rx_tooshort++;
943 		return NULL;
944 	}
945 	memcpy(b, mtod(m, caddr_t), hdrlen);
946 	wh = (const struct ieee80211_qosframe_addr4 *)&b[0];
947 	mc = (const struct ieee80211_meshcntl_ae10 *)&b[hdrlen - meshdrlen];
948 	KASSERT(WHDIR(wh) == IEEE80211_FC1_DIR_FROMDS ||
949 		WHDIR(wh) == IEEE80211_FC1_DIR_DSTODS,
950 	    ("bogus dir, fc 0x%x:0x%x", wh->i_fc[0], wh->i_fc[1]));
951 
952 	llc = (struct llc *)(mtod(m, caddr_t) + hdrlen);
953 	if (llc->llc_dsap == LLC_SNAP_LSAP && llc->llc_ssap == LLC_SNAP_LSAP &&
954 	    llc->llc_control == LLC_UI && llc->llc_snap.org_code[0] == 0 &&
955 	    llc->llc_snap.org_code[1] == 0 && llc->llc_snap.org_code[2] == 0 &&
956 	    /* NB: preserve AppleTalk frames that have a native SNAP hdr */
957 	    !(llc->llc_snap.ether_type == htons(ETHERTYPE_AARP) ||
958 	      llc->llc_snap.ether_type == htons(ETHERTYPE_IPX))) {
959 		m_adj(m, hdrlen + sizeof(struct llc) - sizeof(*eh));
960 		llc = NULL;
961 	} else {
962 		m_adj(m, hdrlen - sizeof(*eh));
963 	}
964 	eh = mtod(m, struct ether_header *);
965 	ae = mc->mc_flags & 3;
966 	if (WHDIR(wh) == IEEE80211_FC1_DIR_FROMDS) {
967 		IEEE80211_ADDR_COPY(eh->ether_dhost, wh->i_addr1);
968 		if (ae == 0) {
969 			IEEE80211_ADDR_COPY(eh->ether_shost, wh->i_addr3);
970 		} else if (ae == 1) {
971 			IEEE80211_ADDR_COPY(eh->ether_shost, mc->mc_addr4);
972 		} else {
973 			IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
974 			    (const struct ieee80211_frame *)wh, NULL,
975 			    "bad AE %d", ae);
976 			vap->iv_stats.is_mesh_badae++;
977 			m_freem(m);
978 			return NULL;
979 		}
980 	} else {
981 		if (ae == 0) {
982 			IEEE80211_ADDR_COPY(eh->ether_dhost, wh->i_addr3);
983 			IEEE80211_ADDR_COPY(eh->ether_shost, wh->i_addr4);
984 		} else if (ae == 2) {
985 			IEEE80211_ADDR_COPY(eh->ether_dhost, mc->mc_addr4);
986 			IEEE80211_ADDR_COPY(eh->ether_shost, mc->mc_addr5);
987 		} else {
988 			IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
989 			    (const struct ieee80211_frame *)wh, NULL,
990 			    "bad AE %d", ae);
991 			vap->iv_stats.is_mesh_badae++;
992 			m_freem(m);
993 			return NULL;
994 		}
995 	}
996 #ifdef ALIGNED_POINTER
997 	if (!ALIGNED_POINTER(mtod(m, caddr_t) + sizeof(*eh), uint32_t)) {
998 		m = ieee80211_realign(vap, m, sizeof(*eh));
999 		if (m == NULL)
1000 			return NULL;
1001 	}
1002 #endif /* ALIGNED_POINTER */
1003 	if (llc != NULL) {
1004 		eh = mtod(m, struct ether_header *);
1005 		eh->ether_type = htons(m->m_pkthdr.len - sizeof(*eh));
1006 	}
1007 	return m;
1008 #undef WDIR
1009 }
1010 
1011 /*
1012  * Return non-zero if the unicast mesh data frame should be processed
1013  * locally.  Frames that are not proxy'd have our address, otherwise
1014  * we need to consult the routing table to look for a proxy entry.
1015  */
1016 static __inline int
1017 mesh_isucastforme(struct ieee80211vap *vap, const struct ieee80211_frame *wh,
1018     const struct ieee80211_meshcntl *mc)
1019 {
1020 	int ae = mc->mc_flags & 3;
1021 
1022 	KASSERT((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS,
1023 	    ("bad dir 0x%x:0x%x", wh->i_fc[0], wh->i_fc[1]));
1024 	KASSERT(ae == 0 || ae == 2, ("bad AE %d", ae));
1025 	if (ae == 2) {				/* ucast w/ proxy */
1026 		const struct ieee80211_meshcntl_ae10 *mc10 =
1027 		    (const struct ieee80211_meshcntl_ae10 *) mc;
1028 		struct ieee80211_mesh_route *rt =
1029 		    ieee80211_mesh_rt_find(vap, mc10->mc_addr4);
1030 		/* check for proxy route to ourself */
1031 		return (rt != NULL &&
1032 		    (rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY));
1033 	} else					/* ucast w/o proxy */
1034 		return IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_myaddr);
1035 }
1036 
1037 static int
1038 mesh_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf)
1039 {
1040 #define	HAS_SEQ(type)	((type & 0x4) == 0)
1041 	struct ieee80211vap *vap = ni->ni_vap;
1042 	struct ieee80211com *ic = ni->ni_ic;
1043 	struct ifnet *ifp = vap->iv_ifp;
1044 	struct ieee80211_frame *wh;
1045 	const struct ieee80211_meshcntl *mc;
1046 	int hdrspace, meshdrlen, need_tap;
1047 	uint8_t dir, type, subtype;
1048 	uint32_t seq;
1049 	uint8_t *addr, qos[2];
1050 	ieee80211_seq rxseq;
1051 
1052 	KASSERT(ni != NULL, ("null node"));
1053 	ni->ni_inact = ni->ni_inact_reload;
1054 
1055 	need_tap = 1;			/* mbuf need to be tapped. */
1056 	type = -1;			/* undefined */
1057 
1058 	if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_min)) {
1059 		IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
1060 		    ni->ni_macaddr, NULL,
1061 		    "too short (1): len %u", m->m_pkthdr.len);
1062 		vap->iv_stats.is_rx_tooshort++;
1063 		goto out;
1064 	}
1065 	/*
1066 	 * Bit of a cheat here, we use a pointer for a 3-address
1067 	 * frame format but don't reference fields past outside
1068 	 * ieee80211_frame_min w/o first validating the data is
1069 	 * present.
1070 	*/
1071 	wh = mtod(m, struct ieee80211_frame *);
1072 
1073 	if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) !=
1074 	    IEEE80211_FC0_VERSION_0) {
1075 		IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
1076 		    ni->ni_macaddr, NULL, "wrong version %x", wh->i_fc[0]);
1077 		vap->iv_stats.is_rx_badversion++;
1078 		goto err;
1079 	}
1080 	dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
1081 	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
1082 	subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
1083 	if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) {
1084 		IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi);
1085 		ni->ni_noise = nf;
1086 		if (HAS_SEQ(type)) {
1087 			uint8_t tid = ieee80211_gettid(wh);
1088 
1089 			if (IEEE80211_QOS_HAS_SEQ(wh) &&
1090 			    TID_TO_WME_AC(tid) >= WME_AC_VI)
1091 				ic->ic_wme.wme_hipri_traffic++;
1092 			rxseq = le16toh(*(uint16_t *)wh->i_seq);
1093 			if (! ieee80211_check_rxseq(ni, wh)) {
1094 				/* duplicate, discard */
1095 				IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
1096 				    wh->i_addr1, "duplicate",
1097 				    "seqno <%u,%u> fragno <%u,%u> tid %u",
1098 				    rxseq >> IEEE80211_SEQ_SEQ_SHIFT,
1099 				    ni->ni_rxseqs[tid] >>
1100 				    IEEE80211_SEQ_SEQ_SHIFT,
1101 				    rxseq & IEEE80211_SEQ_FRAG_MASK,
1102 				    ni->ni_rxseqs[tid] &
1103 				    IEEE80211_SEQ_FRAG_MASK,
1104 				    tid);
1105 				vap->iv_stats.is_rx_dup++;
1106 				IEEE80211_NODE_STAT(ni, rx_dup);
1107 				goto out;
1108 			}
1109 			ni->ni_rxseqs[tid] = rxseq;
1110 		}
1111 	}
1112 #ifdef IEEE80211_DEBUG
1113 	/*
1114 	 * It's easier, but too expensive, to simulate different mesh
1115 	 * topologies by consulting the ACL policy very early, so do this
1116 	 * only under DEBUG.
1117 	 *
1118 	 * NB: this check is also done upon peering link initiation.
1119 	 */
1120 	if (vap->iv_acl != NULL && !vap->iv_acl->iac_check(vap, wh)) {
1121 		IEEE80211_DISCARD(vap, IEEE80211_MSG_ACL,
1122 		    wh, NULL, "%s", "disallowed by ACL");
1123 		vap->iv_stats.is_rx_acl++;
1124 		goto out;
1125 	}
1126 #endif
1127 	switch (type) {
1128 	case IEEE80211_FC0_TYPE_DATA:
1129 		if (ni == vap->iv_bss)
1130 			goto out;
1131 		if (ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED) {
1132 			IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_MESH,
1133 			    ni->ni_macaddr, NULL,
1134 			    "peer link not yet established (%d)",
1135 			    ni->ni_mlstate);
1136 			vap->iv_stats.is_mesh_nolink++;
1137 			goto out;
1138 		}
1139 		if (dir != IEEE80211_FC1_DIR_FROMDS &&
1140 		    dir != IEEE80211_FC1_DIR_DSTODS) {
1141 			IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
1142 			    wh, "data", "incorrect dir 0x%x", dir);
1143 			vap->iv_stats.is_rx_wrongdir++;
1144 			goto err;
1145 		}
1146 
1147 		/* All Mesh data frames are QoS subtype */
1148 		if (!HAS_SEQ(type)) {
1149 			IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
1150 			    wh, "data", "incorrect subtype 0x%x", subtype);
1151 			vap->iv_stats.is_rx_badsubtype++;
1152 			goto err;
1153 		}
1154 
1155 		/*
1156 		 * Next up, any fragmentation.
1157 		 * XXX: we defrag before we even try to forward,
1158 		 * Mesh Control field is not present in sub-sequent
1159 		 * fragmented frames. This is in contrast to Draft 4.0.
1160 		 */
1161 		hdrspace = ieee80211_hdrspace(ic, wh);
1162 		if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
1163 			m = ieee80211_defrag(ni, m, hdrspace);
1164 			if (m == NULL) {
1165 				/* Fragment dropped or frame not complete yet */
1166 				goto out;
1167 			}
1168 		}
1169 		wh = mtod(m, struct ieee80211_frame *); /* NB: after defrag */
1170 
1171 		/*
1172 		 * Now we have a complete Mesh Data frame.
1173 		 */
1174 
1175 		/*
1176 		 * Only fromDStoDS data frames use 4 address qos frames
1177 		 * as specified in amendment. Otherwise addr4 is located
1178 		 * in the Mesh Control field and a 3 address qos frame
1179 		 * is used.
1180 		 */
1181 		if (IEEE80211_IS_DSTODS(wh))
1182 			*(uint16_t *)qos = *(uint16_t *)
1183 			    ((struct ieee80211_qosframe_addr4 *)wh)->i_qos;
1184 		else
1185 			*(uint16_t *)qos = *(uint16_t *)
1186 			    ((struct ieee80211_qosframe *)wh)->i_qos;
1187 
1188 		/*
1189 		 * NB: The mesh STA sets the Mesh Control Present
1190 		 * subfield to 1 in the Mesh Data frame containing
1191 		 * an unfragmented MSDU, an A-MSDU, or the first
1192 		 * fragment of an MSDU.
1193 		 * After defrag it should always be present.
1194 		 */
1195 		if (!(qos[1] & IEEE80211_QOS_MC)) {
1196 			IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_MESH,
1197 			    ni->ni_macaddr, NULL,
1198 			    "%s", "Mesh control field not present");
1199 			vap->iv_stats.is_rx_elem_missing++; /* XXX: kinda */
1200 			goto err;
1201 		}
1202 
1203 		/* pull up enough to get to the mesh control */
1204 		if (m->m_len < hdrspace + sizeof(struct ieee80211_meshcntl) &&
1205 		    (m = m_pullup(m, hdrspace +
1206 		        sizeof(struct ieee80211_meshcntl))) == NULL) {
1207 			IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
1208 			    ni->ni_macaddr, NULL,
1209 			    "data too short: expecting %u", hdrspace);
1210 			vap->iv_stats.is_rx_tooshort++;
1211 			goto out;		/* XXX */
1212 		}
1213 		/*
1214 		 * Now calculate the full extent of the headers. Note
1215 		 * mesh_decap will pull up anything we didn't get
1216 		 * above when it strips the 802.11 headers.
1217 		 */
1218 		mc = (const struct ieee80211_meshcntl *)
1219 		    (mtod(m, const uint8_t *) + hdrspace);
1220 		meshdrlen = sizeof(struct ieee80211_meshcntl) +
1221 		    (mc->mc_flags & 3) * IEEE80211_ADDR_LEN;
1222 		hdrspace += meshdrlen;
1223 		seq = LE_READ_4(mc->mc_seq);
1224 		if (IEEE80211_IS_MULTICAST(wh->i_addr1))
1225 			addr = wh->i_addr3;
1226 		else
1227 			addr = ((struct ieee80211_qosframe_addr4 *)wh)->i_addr4;
1228 		if (IEEE80211_ADDR_EQ(vap->iv_myaddr, addr)) {
1229 			IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
1230 			    addr, "data", "%s", "not to me");
1231 			vap->iv_stats.is_rx_wrongbss++;	/* XXX kinda */
1232 			goto out;
1233 		}
1234 		if (mesh_checkpseq(vap, addr, seq) != 0) {
1235 			vap->iv_stats.is_rx_dup++;
1236 			goto out;
1237 		}
1238 
1239 		/*
1240 		 * Potentially forward packet.  See table s36 (p140)
1241 		 * for the rules.  XXX tap fwd'd packets not for us?
1242 		 */
1243 		if (dir == IEEE80211_FC1_DIR_FROMDS ||
1244 		    !mesh_isucastforme(vap, wh, mc)) {
1245 			mesh_forward(vap, m, mc);
1246 			if (dir == IEEE80211_FC1_DIR_DSTODS)
1247 				goto out;
1248 			/* NB: fall thru to deliver mcast frames locally */
1249 		}
1250 
1251 		if (ieee80211_radiotap_active_vap(vap))
1252 			ieee80211_radiotap_rx(vap, m);
1253 		need_tap = 0;
1254 
1255 		/*
1256 		 * Finally, strip the 802.11 header.
1257 		 */
1258 		m = mesh_decap(vap, m, hdrspace, meshdrlen);
1259 		if (m == NULL) {
1260 			/* XXX mask bit to check for both */
1261 			/* don't count Null data frames as errors */
1262 			if (subtype == IEEE80211_FC0_SUBTYPE_NODATA ||
1263 			    subtype == IEEE80211_FC0_SUBTYPE_QOS_NULL)
1264 				goto out;
1265 			IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
1266 			    ni->ni_macaddr, "data", "%s", "decap error");
1267 			vap->iv_stats.is_rx_decap++;
1268 			IEEE80211_NODE_STAT(ni, rx_decap);
1269 			goto err;
1270 		}
1271 		if (qos[0] & IEEE80211_QOS_AMSDU) {
1272 			m = ieee80211_decap_amsdu(ni, m);
1273 			if (m == NULL)
1274 				return IEEE80211_FC0_TYPE_DATA;
1275 		}
1276 		ieee80211_deliver_data(vap, ni, m);
1277 		return type;
1278 	case IEEE80211_FC0_TYPE_MGT:
1279 		vap->iv_stats.is_rx_mgmt++;
1280 		IEEE80211_NODE_STAT(ni, rx_mgmt);
1281 		if (dir != IEEE80211_FC1_DIR_NODS) {
1282 			IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
1283 			    wh, "mgt", "incorrect dir 0x%x", dir);
1284 			vap->iv_stats.is_rx_wrongdir++;
1285 			goto err;
1286 		}
1287 		if (m->m_pkthdr.len < sizeof(struct ieee80211_frame)) {
1288 			IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
1289 			    ni->ni_macaddr, "mgt", "too short: len %u",
1290 			    m->m_pkthdr.len);
1291 			vap->iv_stats.is_rx_tooshort++;
1292 			goto out;
1293 		}
1294 #ifdef IEEE80211_DEBUG
1295 		if ((ieee80211_msg_debug(vap) &&
1296 		    (vap->iv_ic->ic_flags & IEEE80211_F_SCAN)) ||
1297 		    ieee80211_msg_dumppkts(vap)) {
1298 			if_printf(ifp, "received %s from %s rssi %d\n",
1299 			    ieee80211_mgt_subtype_name[subtype >>
1300 			    IEEE80211_FC0_SUBTYPE_SHIFT],
1301 			    ether_sprintf(wh->i_addr2), rssi);
1302 		}
1303 #endif
1304 		if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1305 			IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
1306 			    wh, NULL, "%s", "WEP set but not permitted");
1307 			vap->iv_stats.is_rx_mgtdiscard++; /* XXX */
1308 			goto out;
1309 		}
1310 		vap->iv_recv_mgmt(ni, m, subtype, rssi, nf);
1311 		goto out;
1312 	case IEEE80211_FC0_TYPE_CTL:
1313 		vap->iv_stats.is_rx_ctl++;
1314 		IEEE80211_NODE_STAT(ni, rx_ctrl);
1315 		goto out;
1316 	default:
1317 		IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
1318 		    wh, "bad", "frame type 0x%x", type);
1319 		/* should not come here */
1320 		break;
1321 	}
1322 err:
1323 	ifp->if_ierrors++;
1324 out:
1325 	if (m != NULL) {
1326 		if (need_tap && ieee80211_radiotap_active_vap(vap))
1327 			ieee80211_radiotap_rx(vap, m);
1328 		m_freem(m);
1329 	}
1330 	return type;
1331 }
1332 
1333 static void
1334 mesh_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype,
1335     int rssi, int nf)
1336 {
1337 	struct ieee80211vap *vap = ni->ni_vap;
1338 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
1339 	struct ieee80211com *ic = ni->ni_ic;
1340 	struct ieee80211_frame *wh;
1341 	uint8_t *frm, *efrm;
1342 
1343 	wh = mtod(m0, struct ieee80211_frame *);
1344 	frm = (uint8_t *)&wh[1];
1345 	efrm = mtod(m0, uint8_t *) + m0->m_len;
1346 	switch (subtype) {
1347 	case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
1348 	case IEEE80211_FC0_SUBTYPE_BEACON:
1349 	{
1350 		struct ieee80211_scanparams scan;
1351 		/*
1352 		 * We process beacon/probe response
1353 		 * frames to discover neighbors.
1354 		 */
1355 		if (ieee80211_parse_beacon(ni, m0, &scan) != 0)
1356 			return;
1357 		/*
1358 		 * Count frame now that we know it's to be processed.
1359 		 */
1360 		if (subtype == IEEE80211_FC0_SUBTYPE_BEACON) {
1361 			vap->iv_stats.is_rx_beacon++;	/* XXX remove */
1362 			IEEE80211_NODE_STAT(ni, rx_beacons);
1363 		} else
1364 			IEEE80211_NODE_STAT(ni, rx_proberesp);
1365 		/*
1366 		 * If scanning, just pass information to the scan module.
1367 		 */
1368 		if (ic->ic_flags & IEEE80211_F_SCAN) {
1369 			if (ic->ic_flags_ext & IEEE80211_FEXT_PROBECHAN) {
1370 				/*
1371 				 * Actively scanning a channel marked passive;
1372 				 * send a probe request now that we know there
1373 				 * is 802.11 traffic present.
1374 				 *
1375 				 * XXX check if the beacon we recv'd gives
1376 				 * us what we need and suppress the probe req
1377 				 */
1378 				ieee80211_probe_curchan(vap, 1);
1379 				ic->ic_flags_ext &= ~IEEE80211_FEXT_PROBECHAN;
1380 			}
1381 			ieee80211_add_scan(vap, &scan, wh,
1382 			    subtype, rssi, nf);
1383 			return;
1384 		}
1385 
1386 		/* The rest of this code assumes we are running */
1387 		if (vap->iv_state != IEEE80211_S_RUN)
1388 			return;
1389 		/*
1390 		 * Ignore non-mesh STAs.
1391 		 */
1392 		if ((scan.capinfo &
1393 		     (IEEE80211_CAPINFO_ESS|IEEE80211_CAPINFO_IBSS)) ||
1394 		    scan.meshid == NULL || scan.meshconf == NULL) {
1395 			IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
1396 			    wh, "beacon", "%s", "not a mesh sta");
1397 			vap->iv_stats.is_mesh_wrongmesh++;
1398 			return;
1399 		}
1400 		/*
1401 		 * Ignore STAs for other mesh networks.
1402 		 */
1403 		if (memcmp(scan.meshid+2, ms->ms_id, ms->ms_idlen) != 0 ||
1404 		    mesh_verify_meshconf(vap, scan.meshconf)) {
1405 			IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
1406 			    wh, "beacon", "%s", "not for our mesh");
1407 			vap->iv_stats.is_mesh_wrongmesh++;
1408 			return;
1409 		}
1410 		/*
1411 		 * Peer only based on the current ACL policy.
1412 		 */
1413 		if (vap->iv_acl != NULL && !vap->iv_acl->iac_check(vap, wh)) {
1414 			IEEE80211_DISCARD(vap, IEEE80211_MSG_ACL,
1415 			    wh, NULL, "%s", "disallowed by ACL");
1416 			vap->iv_stats.is_rx_acl++;
1417 			return;
1418 		}
1419 		/*
1420 		 * Do neighbor discovery.
1421 		 */
1422 		if (!IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_macaddr)) {
1423 			/*
1424 			 * Create a new entry in the neighbor table.
1425 			 */
1426 			ni = ieee80211_add_neighbor(vap, wh, &scan);
1427 		}
1428 		/*
1429 		 * Automatically peer with discovered nodes if possible.
1430 		 * XXX backoff on repeated failure
1431 		 */
1432 		if (ni != vap->iv_bss &&
1433 		    (ms->ms_flags & IEEE80211_MESHFLAGS_AP) &&
1434 		    ni->ni_mlstate == IEEE80211_NODE_MESH_IDLE) {
1435 			uint16_t args[1];
1436 
1437 			ni->ni_mlpid = mesh_generateid(vap);
1438 			if (ni->ni_mlpid == 0)
1439 				return;
1440 			mesh_linkchange(ni, IEEE80211_NODE_MESH_OPENSNT);
1441 			args[0] = ni->ni_mlpid;
1442 			ieee80211_send_action(ni,
1443 			    IEEE80211_ACTION_CAT_MESHPEERING,
1444 			    IEEE80211_ACTION_MESHPEERING_OPEN, args);
1445 			ni->ni_mlrcnt = 0;
1446 			mesh_peer_timeout_setup(ni);
1447 		}
1448 		break;
1449 	}
1450 	case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
1451 	{
1452 		uint8_t *ssid, *meshid, *rates, *xrates;
1453 		uint8_t *sfrm;
1454 
1455 		if (vap->iv_state != IEEE80211_S_RUN) {
1456 			IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
1457 			    wh, NULL, "wrong state %s",
1458 			    ieee80211_state_name[vap->iv_state]);
1459 			vap->iv_stats.is_rx_mgtdiscard++;
1460 			return;
1461 		}
1462 		if (IEEE80211_IS_MULTICAST(wh->i_addr2)) {
1463 			/* frame must be directed */
1464 			IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
1465 			    wh, NULL, "%s", "not unicast");
1466 			vap->iv_stats.is_rx_mgtdiscard++;	/* XXX stat */
1467 			return;
1468 		}
1469 		/*
1470 		 * prreq frame format
1471 		 *      [tlv] ssid
1472 		 *      [tlv] supported rates
1473 		 *      [tlv] extended supported rates
1474 		 *	[tlv] mesh id
1475 		 */
1476 		ssid = meshid = rates = xrates = NULL;
1477 		sfrm = frm;
1478 		while (efrm - frm > 1) {
1479 			IEEE80211_VERIFY_LENGTH(efrm - frm, frm[1] + 2, return);
1480 			switch (*frm) {
1481 			case IEEE80211_ELEMID_SSID:
1482 				ssid = frm;
1483 				break;
1484 			case IEEE80211_ELEMID_RATES:
1485 				rates = frm;
1486 				break;
1487 			case IEEE80211_ELEMID_XRATES:
1488 				xrates = frm;
1489 				break;
1490 			case IEEE80211_ELEMID_MESHID:
1491 				meshid = frm;
1492 				break;
1493 			}
1494 			frm += frm[1] + 2;
1495 		}
1496 		IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN, return);
1497 		IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE, return);
1498 		if (xrates != NULL)
1499 			IEEE80211_VERIFY_ELEMENT(xrates,
1500 			    IEEE80211_RATE_MAXSIZE - rates[1], return);
1501 		if (meshid != NULL) {
1502 			IEEE80211_VERIFY_ELEMENT(meshid,
1503 			    IEEE80211_MESHID_LEN, return);
1504 			/* NB: meshid, not ssid */
1505 			IEEE80211_VERIFY_SSID(vap->iv_bss, meshid, return);
1506 		}
1507 
1508 		/* XXX find a better class or define it's own */
1509 		IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_INPUT, wh->i_addr2,
1510 		    "%s", "recv probe req");
1511 		/*
1512 		 * Some legacy 11b clients cannot hack a complete
1513 		 * probe response frame.  When the request includes
1514 		 * only a bare-bones rate set, communicate this to
1515 		 * the transmit side.
1516 		 */
1517 		ieee80211_send_proberesp(vap, wh->i_addr2, 0);
1518 		break;
1519 	}
1520 
1521 	case IEEE80211_FC0_SUBTYPE_ACTION:
1522 	case IEEE80211_FC0_SUBTYPE_ACTION_NOACK:
1523 		if (ni == vap->iv_bss) {
1524 			IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
1525 			    wh, NULL, "%s", "unknown node");
1526 			vap->iv_stats.is_rx_mgtdiscard++;
1527 		} else if (!IEEE80211_ADDR_EQ(vap->iv_myaddr, wh->i_addr1) &&
1528 		    !IEEE80211_IS_MULTICAST(wh->i_addr1)) {
1529 			IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
1530 			    wh, NULL, "%s", "not for us");
1531 			vap->iv_stats.is_rx_mgtdiscard++;
1532 		} else if (vap->iv_state != IEEE80211_S_RUN) {
1533 			IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
1534 			    wh, NULL, "wrong state %s",
1535 			    ieee80211_state_name[vap->iv_state]);
1536 			vap->iv_stats.is_rx_mgtdiscard++;
1537 		} else {
1538 			if (ieee80211_parse_action(ni, m0) == 0)
1539 				(void)ic->ic_recv_action(ni, wh, frm, efrm);
1540 		}
1541 		break;
1542 
1543 	case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
1544 	case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
1545 	case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
1546 	case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
1547 	case IEEE80211_FC0_SUBTYPE_ATIM:
1548 	case IEEE80211_FC0_SUBTYPE_DISASSOC:
1549 	case IEEE80211_FC0_SUBTYPE_AUTH:
1550 	case IEEE80211_FC0_SUBTYPE_DEAUTH:
1551 		IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
1552 		    wh, NULL, "%s", "not handled");
1553 		vap->iv_stats.is_rx_mgtdiscard++;
1554 		break;
1555 
1556 	default:
1557 		IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
1558 		    wh, "mgt", "subtype 0x%x not handled", subtype);
1559 		vap->iv_stats.is_rx_badsubtype++;
1560 		break;
1561 	}
1562 }
1563 
1564 static void
1565 mesh_recv_ctl(struct ieee80211_node *ni, struct mbuf *m, int subtype)
1566 {
1567 
1568 	switch (subtype) {
1569 	case IEEE80211_FC0_SUBTYPE_BAR:
1570 		ieee80211_recv_bar(ni, m);
1571 		break;
1572 	}
1573 }
1574 
1575 /*
1576  * Parse meshpeering action ie's for open+confirm frames; the
1577  * important bits are returned in the supplied structure.
1578  */
1579 static const struct ieee80211_meshpeer_ie *
1580 mesh_parse_meshpeering_action(struct ieee80211_node *ni,
1581 	const struct ieee80211_frame *wh,	/* XXX for VERIFY_LENGTH */
1582 	const uint8_t *frm, const uint8_t *efrm,
1583 	struct ieee80211_meshpeer_ie *mp, uint8_t subtype)
1584 {
1585 	struct ieee80211vap *vap = ni->ni_vap;
1586 	const struct ieee80211_meshpeer_ie *mpie;
1587 	const uint8_t *meshid, *meshconf, *meshpeer;
1588 
1589 	meshid = meshconf = meshpeer = NULL;
1590 	while (efrm - frm > 1) {
1591 		IEEE80211_VERIFY_LENGTH(efrm - frm, frm[1] + 2, return NULL);
1592 		switch (*frm) {
1593 		case IEEE80211_ELEMID_MESHID:
1594 			meshid = frm;
1595 			break;
1596 		case IEEE80211_ELEMID_MESHCONF:
1597 			meshconf = frm;
1598 			break;
1599 		case IEEE80211_ELEMID_MESHPEER:
1600 			meshpeer = frm;
1601 			mpie = (const struct ieee80211_meshpeer_ie *) frm;
1602 			memset(mp, 0, sizeof(*mp));
1603 			mp->peer_llinkid = LE_READ_2(&mpie->peer_llinkid);
1604 			/* NB: peer link ID is optional on these frames */
1605 			if (subtype == IEEE80211_MESH_PEER_LINK_CLOSE &&
1606 			    mpie->peer_len == 8) {
1607 				mp->peer_linkid = 0;
1608 				mp->peer_rcode = LE_READ_2(&mpie->peer_linkid);
1609 			} else {
1610 				mp->peer_linkid = LE_READ_2(&mpie->peer_linkid);
1611 				mp->peer_rcode = LE_READ_2(&mpie->peer_rcode);
1612 			}
1613 			break;
1614 		}
1615 		frm += frm[1] + 2;
1616 	}
1617 
1618 	/*
1619 	 * Verify the contents of the frame. Action frames with
1620 	 * close subtype don't have a Mesh Configuration IE.
1621 	 * If if fails validation, close the peer link.
1622 	 */
1623 	KASSERT(meshpeer != NULL &&
1624 	    subtype != IEEE80211_ACTION_MESHPEERING_CLOSE,
1625 	    ("parsing close action"));
1626 
1627 	if (mesh_verify_meshid(vap, meshid) ||
1628 	    mesh_verify_meshpeer(vap, subtype, meshpeer) ||
1629 	    mesh_verify_meshconf(vap, meshconf)) {
1630 		uint16_t args[3];
1631 
1632 		IEEE80211_DISCARD(vap,
1633 		    IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
1634 		    wh, NULL, "%s", "not for our mesh");
1635 		vap->iv_stats.is_rx_mgtdiscard++;
1636 		switch (ni->ni_mlstate) {
1637 		case IEEE80211_NODE_MESH_IDLE:
1638 		case IEEE80211_NODE_MESH_ESTABLISHED:
1639 		case IEEE80211_NODE_MESH_HOLDING:
1640 			/* ignore */
1641 			break;
1642 		case IEEE80211_NODE_MESH_OPENSNT:
1643 		case IEEE80211_NODE_MESH_OPENRCV:
1644 		case IEEE80211_NODE_MESH_CONFIRMRCV:
1645 			args[0] = ni->ni_mlpid;
1646 			args[1] = ni->ni_mllid;
1647 			args[2] = IEEE80211_REASON_PEER_LINK_CANCELED;
1648 			ieee80211_send_action(ni,
1649 			    IEEE80211_ACTION_CAT_MESHPEERING,
1650 			    IEEE80211_ACTION_MESHPEERING_CLOSE,
1651 			    args);
1652 			mesh_linkchange(ni, IEEE80211_NODE_MESH_HOLDING);
1653 			mesh_peer_timeout_setup(ni);
1654 			break;
1655 		}
1656 		return NULL;
1657 	}
1658 	return (const struct ieee80211_meshpeer_ie *) mp;
1659 }
1660 
1661 static int
1662 mesh_recv_action_meshpeering_open(struct ieee80211_node *ni,
1663 	const struct ieee80211_frame *wh,
1664 	const uint8_t *frm, const uint8_t *efrm)
1665 {
1666 	struct ieee80211vap *vap = ni->ni_vap;
1667 	struct ieee80211_meshpeer_ie ie;
1668 	const struct ieee80211_meshpeer_ie *meshpeer;
1669 	uint16_t args[3];
1670 
1671 	/* +2+2 for action + code + capabilites */
1672 	meshpeer = mesh_parse_meshpeering_action(ni, wh, frm+2+2, efrm, &ie,
1673 	    IEEE80211_ACTION_MESHPEERING_OPEN);
1674 	if (meshpeer == NULL) {
1675 		return 0;
1676 	}
1677 
1678 	/* XXX move up */
1679 	IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni,
1680 	    "recv PEER OPEN, lid 0x%x", meshpeer->peer_llinkid);
1681 
1682 	switch (ni->ni_mlstate) {
1683 	case IEEE80211_NODE_MESH_IDLE:
1684 		mesh_linkchange(ni, IEEE80211_NODE_MESH_OPENRCV);
1685 		ni->ni_mllid = meshpeer->peer_llinkid;
1686 		ni->ni_mlpid = mesh_generateid(vap);
1687 		if (ni->ni_mlpid == 0)
1688 			return 0;		/* XXX */
1689 		args[0] = ni->ni_mlpid;
1690 		/* Announce we're open too... */
1691 		ieee80211_send_action(ni,
1692 		    IEEE80211_ACTION_CAT_MESHPEERING,
1693 		    IEEE80211_ACTION_MESHPEERING_OPEN, args);
1694 		/* ...and confirm the link. */
1695 		args[0] = ni->ni_mlpid;
1696 		args[1] = ni->ni_mllid;
1697 		ieee80211_send_action(ni,
1698 		    IEEE80211_ACTION_CAT_MESHPEERING,
1699 		    IEEE80211_ACTION_MESHPEERING_CONFIRM,
1700 		    args);
1701 		mesh_peer_timeout_setup(ni);
1702 		break;
1703 	case IEEE80211_NODE_MESH_OPENRCV:
1704 		/* Wrong Link ID */
1705 		if (ni->ni_mllid != meshpeer->peer_llinkid) {
1706 			args[0] = ni->ni_mllid;
1707 			args[1] = ni->ni_mlpid;
1708 			args[2] = IEEE80211_REASON_PEER_LINK_CANCELED;
1709 			ieee80211_send_action(ni,
1710 			    IEEE80211_ACTION_CAT_MESHPEERING,
1711 			    IEEE80211_ACTION_MESHPEERING_CLOSE,
1712 			    args);
1713 			mesh_linkchange(ni, IEEE80211_NODE_MESH_HOLDING);
1714 			mesh_peer_timeout_setup(ni);
1715 			break;
1716 		}
1717 		/* Duplicate open, confirm again. */
1718 		args[0] = ni->ni_mlpid;
1719 		args[1] = ni->ni_mllid;
1720 		ieee80211_send_action(ni,
1721 		    IEEE80211_ACTION_CAT_MESHPEERING,
1722 		    IEEE80211_ACTION_MESHPEERING_CONFIRM,
1723 		    args);
1724 		break;
1725 	case IEEE80211_NODE_MESH_OPENSNT:
1726 		ni->ni_mllid = meshpeer->peer_llinkid;
1727 		mesh_linkchange(ni, IEEE80211_NODE_MESH_OPENRCV);
1728 		args[0] = ni->ni_mlpid;
1729 		args[1] = ni->ni_mllid;
1730 		ieee80211_send_action(ni,
1731 		    IEEE80211_ACTION_CAT_MESHPEERING,
1732 		    IEEE80211_ACTION_MESHPEERING_CONFIRM,
1733 		    args);
1734 		/* NB: don't setup/clear any timeout */
1735 		break;
1736 	case IEEE80211_NODE_MESH_CONFIRMRCV:
1737 		if (ni->ni_mlpid != meshpeer->peer_linkid ||
1738 		    ni->ni_mllid != meshpeer->peer_llinkid) {
1739 			args[0] = ni->ni_mlpid;
1740 			args[1] = ni->ni_mllid;
1741 			args[2] = IEEE80211_REASON_PEER_LINK_CANCELED;
1742 			ieee80211_send_action(ni,
1743 			    IEEE80211_ACTION_CAT_MESHPEERING,
1744 			    IEEE80211_ACTION_MESHPEERING_CLOSE,
1745 			    args);
1746 			mesh_linkchange(ni,
1747 			    IEEE80211_NODE_MESH_HOLDING);
1748 			mesh_peer_timeout_setup(ni);
1749 			break;
1750 		}
1751 		mesh_linkchange(ni, IEEE80211_NODE_MESH_ESTABLISHED);
1752 		ni->ni_mllid = meshpeer->peer_llinkid;
1753 		args[0] = ni->ni_mlpid;
1754 		args[1] = ni->ni_mllid;
1755 		ieee80211_send_action(ni,
1756 		    IEEE80211_ACTION_CAT_MESHPEERING,
1757 		    IEEE80211_ACTION_MESHPEERING_CONFIRM,
1758 		    args);
1759 		mesh_peer_timeout_stop(ni);
1760 		break;
1761 	case IEEE80211_NODE_MESH_ESTABLISHED:
1762 		if (ni->ni_mllid != meshpeer->peer_llinkid) {
1763 			args[0] = ni->ni_mllid;
1764 			args[1] = ni->ni_mlpid;
1765 			args[2] = IEEE80211_REASON_PEER_LINK_CANCELED;
1766 			ieee80211_send_action(ni,
1767 			    IEEE80211_ACTION_CAT_MESHPEERING,
1768 			    IEEE80211_ACTION_MESHPEERING_CLOSE,
1769 			    args);
1770 			mesh_linkchange(ni, IEEE80211_NODE_MESH_HOLDING);
1771 			mesh_peer_timeout_setup(ni);
1772 			break;
1773 		}
1774 		args[0] = ni->ni_mlpid;
1775 		args[1] = ni->ni_mllid;
1776 		ieee80211_send_action(ni,
1777 		    IEEE80211_ACTION_CAT_MESHPEERING,
1778 		    IEEE80211_ACTION_MESHPEERING_CONFIRM,
1779 		    args);
1780 		break;
1781 	case IEEE80211_NODE_MESH_HOLDING:
1782 		args[0] = ni->ni_mlpid;
1783 		args[1] = meshpeer->peer_llinkid;
1784 		args[2] = IEEE80211_REASON_MESH_MAX_RETRIES;
1785 		ieee80211_send_action(ni,
1786 		    IEEE80211_ACTION_CAT_MESHPEERING,
1787 		    IEEE80211_ACTION_MESHPEERING_CLOSE,
1788 		    args);
1789 		break;
1790 	}
1791 	return 0;
1792 }
1793 
1794 static int
1795 mesh_recv_action_meshpeering_confirm(struct ieee80211_node *ni,
1796 	const struct ieee80211_frame *wh,
1797 	const uint8_t *frm, const uint8_t *efrm)
1798 {
1799 	struct ieee80211vap *vap = ni->ni_vap;
1800 	struct ieee80211_meshpeer_ie ie;
1801 	const struct ieee80211_meshpeer_ie *meshpeer;
1802 	uint16_t args[3];
1803 
1804 	/* +2+2+2+2 for action + code + capabilites + status code + AID */
1805 	meshpeer = mesh_parse_meshpeering_action(ni, wh, frm+2+2+2+2, efrm, &ie,
1806 	    IEEE80211_ACTION_MESHPEERING_CONFIRM);
1807 	if (meshpeer == NULL) {
1808 		return 0;
1809 	}
1810 
1811 	IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni,
1812 	    "recv PEER CONFIRM, local id 0x%x, peer id 0x%x",
1813 	    meshpeer->peer_llinkid, meshpeer->peer_linkid);
1814 
1815 	switch (ni->ni_mlstate) {
1816 	case IEEE80211_NODE_MESH_OPENRCV:
1817 		mesh_linkchange(ni, IEEE80211_NODE_MESH_ESTABLISHED);
1818 		mesh_peer_timeout_stop(ni);
1819 		break;
1820 	case IEEE80211_NODE_MESH_OPENSNT:
1821 		mesh_linkchange(ni, IEEE80211_NODE_MESH_CONFIRMRCV);
1822 		break;
1823 	case IEEE80211_NODE_MESH_HOLDING:
1824 		args[0] = ni->ni_mlpid;
1825 		args[1] = meshpeer->peer_llinkid;
1826 		args[2] = IEEE80211_REASON_MESH_MAX_RETRIES;
1827 		ieee80211_send_action(ni,
1828 		    IEEE80211_ACTION_CAT_MESHPEERING,
1829 		    IEEE80211_ACTION_MESHPEERING_CLOSE,
1830 		    args);
1831 		break;
1832 	case IEEE80211_NODE_MESH_CONFIRMRCV:
1833 		if (ni->ni_mllid != meshpeer->peer_llinkid) {
1834 			args[0] = ni->ni_mlpid;
1835 			args[1] = ni->ni_mllid;
1836 			args[2] = IEEE80211_REASON_PEER_LINK_CANCELED;
1837 			ieee80211_send_action(ni,
1838 			    IEEE80211_ACTION_CAT_MESHPEERING,
1839 			    IEEE80211_ACTION_MESHPEERING_CLOSE,
1840 			    args);
1841 			mesh_linkchange(ni, IEEE80211_NODE_MESH_HOLDING);
1842 			mesh_peer_timeout_setup(ni);
1843 		}
1844 		break;
1845 	default:
1846 		IEEE80211_DISCARD(vap,
1847 		    IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
1848 		    wh, NULL, "received confirm in invalid state %d",
1849 		    ni->ni_mlstate);
1850 		vap->iv_stats.is_rx_mgtdiscard++;
1851 		break;
1852 	}
1853 	return 0;
1854 }
1855 
1856 static int
1857 mesh_recv_action_meshpeering_close(struct ieee80211_node *ni,
1858 	const struct ieee80211_frame *wh,
1859 	const uint8_t *frm, const uint8_t *efrm)
1860 {
1861 	uint16_t args[3];
1862 
1863 	IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
1864 	    ni, "%s", "recv PEER CLOSE");
1865 
1866 	switch (ni->ni_mlstate) {
1867 	case IEEE80211_NODE_MESH_IDLE:
1868 		/* ignore */
1869 		break;
1870 	case IEEE80211_NODE_MESH_OPENRCV:
1871 	case IEEE80211_NODE_MESH_OPENSNT:
1872 	case IEEE80211_NODE_MESH_CONFIRMRCV:
1873 	case IEEE80211_NODE_MESH_ESTABLISHED:
1874 		args[0] = ni->ni_mlpid;
1875 		args[1] = ni->ni_mllid;
1876 		args[2] = IEEE80211_REASON_MESH_CLOSE_RCVD;
1877 		ieee80211_send_action(ni,
1878 		    IEEE80211_ACTION_CAT_MESHPEERING,
1879 		    IEEE80211_ACTION_MESHPEERING_CLOSE,
1880 		    args);
1881 		mesh_linkchange(ni, IEEE80211_NODE_MESH_HOLDING);
1882 		mesh_peer_timeout_setup(ni);
1883 		break;
1884 	case IEEE80211_NODE_MESH_HOLDING:
1885 		mesh_linkchange(ni, IEEE80211_NODE_MESH_IDLE);
1886 		mesh_peer_timeout_setup(ni);
1887 		break;
1888 	}
1889 	return 0;
1890 }
1891 
1892 /*
1893  * Link Metric handling.
1894  */
1895 static int
1896 mesh_recv_action_meshlmetric(struct ieee80211_node *ni,
1897 	const struct ieee80211_frame *wh,
1898 	const uint8_t *frm, const uint8_t *efrm)
1899 {
1900 	const struct ieee80211_meshlmetric_ie *ie =
1901 	    (const struct ieee80211_meshlmetric_ie *)
1902 	    (frm+2); /* action + code */
1903 	struct ieee80211_meshlmetric_ie lm_rep;
1904 
1905 	if (ie->lm_flags & IEEE80211_MESH_LMETRIC_FLAGS_REQ) {
1906 		lm_rep.lm_flags = 0;
1907 		lm_rep.lm_metric = mesh_airtime_calc(ni);
1908 		ieee80211_send_action(ni,
1909 		    IEEE80211_ACTION_CAT_MESH,
1910 		    IEEE80211_ACTION_MESH_LMETRIC,
1911 		    &lm_rep);
1912 	}
1913 	/* XXX: else do nothing for now */
1914 	return 0;
1915 }
1916 
1917 static int
1918 mesh_send_action(struct ieee80211_node *ni, struct mbuf *m)
1919 {
1920 	struct ieee80211_bpf_params params;
1921 
1922 	memset(&params, 0, sizeof(params));
1923 	params.ibp_pri = WME_AC_VO;
1924 	params.ibp_rate0 = ni->ni_txparms->mgmtrate;
1925 	/* XXX ucast/mcast */
1926 	params.ibp_try0 = ni->ni_txparms->maxretry;
1927 	params.ibp_power = ni->ni_txpower;
1928 	return ieee80211_mgmt_output(ni, m, IEEE80211_FC0_SUBTYPE_ACTION,
1929 	     &params);
1930 }
1931 
1932 #define	ADDSHORT(frm, v) do {			\
1933 	frm[0] = (v) & 0xff;			\
1934 	frm[1] = (v) >> 8;			\
1935 	frm += 2;				\
1936 } while (0)
1937 #define	ADDWORD(frm, v) do {			\
1938 	frm[0] = (v) & 0xff;			\
1939 	frm[1] = ((v) >> 8) & 0xff;		\
1940 	frm[2] = ((v) >> 16) & 0xff;		\
1941 	frm[3] = ((v) >> 24) & 0xff;		\
1942 	frm += 4;				\
1943 } while (0)
1944 
1945 static int
1946 mesh_send_action_meshpeering_open(struct ieee80211_node *ni,
1947 	int category, int action, void *args0)
1948 {
1949 	struct ieee80211vap *vap = ni->ni_vap;
1950 	struct ieee80211com *ic = ni->ni_ic;
1951 	uint16_t *args = args0;
1952 	const struct ieee80211_rateset *rs;
1953 	struct mbuf *m;
1954 	uint8_t *frm;
1955 
1956 	IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni,
1957 	    "send PEER OPEN action: localid 0x%x", args[0]);
1958 
1959 	IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
1960 	    "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__,
1961 	    ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)+1);
1962 	ieee80211_ref_node(ni);
1963 
1964 	m = ieee80211_getmgtframe(&frm,
1965 	    ic->ic_headroom + sizeof(struct ieee80211_frame),
1966 	    sizeof(uint16_t)	/* action+category */
1967 	    + sizeof(uint16_t)	/* capabilites */
1968 	    + 2 + IEEE80211_RATE_SIZE
1969 	    + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)
1970 	    + 2 + IEEE80211_MESHID_LEN
1971 	    + sizeof(struct ieee80211_meshconf_ie)
1972 	    + sizeof(struct ieee80211_meshpeer_ie)
1973 	);
1974 	if (m != NULL) {
1975 		/*
1976 		 * mesh peer open action frame format:
1977 		 *   [1] category
1978 		 *   [1] action
1979 		 *   [2] capabilities
1980 		 *   [tlv] rates
1981 		 *   [tlv] xrates
1982 		 *   [tlv] mesh id
1983 		 *   [tlv] mesh conf
1984 		 *   [tlv] mesh peer link mgmt
1985 		 */
1986 		*frm++ = category;
1987 		*frm++ = action;
1988 		ADDSHORT(frm, ieee80211_getcapinfo(vap, ni->ni_chan));
1989 		rs = ieee80211_get_suprates(ic, ic->ic_curchan);
1990 		frm = ieee80211_add_rates(frm, rs);
1991 		frm = ieee80211_add_xrates(frm, rs);
1992 		frm = ieee80211_add_meshid(frm, vap);
1993 		frm = ieee80211_add_meshconf(frm, vap);
1994 		frm = ieee80211_add_meshpeer(frm, IEEE80211_MESH_PEER_LINK_OPEN,
1995 		    args[0], 0, 0);
1996 		m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
1997 		return mesh_send_action(ni, m);
1998 	} else {
1999 		vap->iv_stats.is_tx_nobuf++;
2000 		ieee80211_free_node(ni);
2001 		return ENOMEM;
2002 	}
2003 }
2004 
2005 static int
2006 mesh_send_action_meshpeering_confirm(struct ieee80211_node *ni,
2007 	int category, int action, void *args0)
2008 {
2009 	struct ieee80211vap *vap = ni->ni_vap;
2010 	struct ieee80211com *ic = ni->ni_ic;
2011 	uint16_t *args = args0;
2012 	const struct ieee80211_rateset *rs;
2013 	struct mbuf *m;
2014 	uint8_t *frm;
2015 
2016 	IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni,
2017 	    "send PEER CONFIRM action: localid 0x%x, peerid 0x%x",
2018 	    args[0], args[1]);
2019 
2020 	IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
2021 	    "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__,
2022 	    ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)+1);
2023 	ieee80211_ref_node(ni);
2024 
2025 	m = ieee80211_getmgtframe(&frm,
2026 	    ic->ic_headroom + sizeof(struct ieee80211_frame),
2027 	    sizeof(uint16_t)	/* action+category */
2028 	    + sizeof(uint16_t)	/* capabilites */
2029 	    + sizeof(uint16_t)	/* status code */
2030 	    + sizeof(uint16_t)	/* AID */
2031 	    + 2 + IEEE80211_RATE_SIZE
2032 	    + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)
2033 	    + 2 + IEEE80211_MESHID_LEN
2034 	    + sizeof(struct ieee80211_meshconf_ie)
2035 	    + sizeof(struct ieee80211_meshpeer_ie)
2036 	);
2037 	if (m != NULL) {
2038 		/*
2039 		 * mesh peer confirm action frame format:
2040 		 *   [1] category
2041 		 *   [1] action
2042 		 *   [2] capabilities
2043 		 *   [2] status code
2044 		 *   [2] association id (peer ID)
2045 		 *   [tlv] rates
2046 		 *   [tlv] xrates
2047 		 *   [tlv] mesh id
2048 		 *   [tlv] mesh conf
2049 		 *   [tlv] mesh peer link mgmt
2050 		 */
2051 		*frm++ = category;
2052 		*frm++ = action;
2053 		ADDSHORT(frm, ieee80211_getcapinfo(vap, ni->ni_chan));
2054 		ADDSHORT(frm, 0);		/* status code */
2055 		ADDSHORT(frm, args[1]);		/* AID */
2056 		rs = ieee80211_get_suprates(ic, ic->ic_curchan);
2057 		frm = ieee80211_add_rates(frm, rs);
2058 		frm = ieee80211_add_xrates(frm, rs);
2059 		frm = ieee80211_add_meshid(frm, vap);
2060 		frm = ieee80211_add_meshconf(frm, vap);
2061 		frm = ieee80211_add_meshpeer(frm,
2062 		    IEEE80211_MESH_PEER_LINK_CONFIRM,
2063 		    args[0], args[1], 0);
2064 		m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
2065 		return mesh_send_action(ni, m);
2066 	} else {
2067 		vap->iv_stats.is_tx_nobuf++;
2068 		ieee80211_free_node(ni);
2069 		return ENOMEM;
2070 	}
2071 }
2072 
2073 static int
2074 mesh_send_action_meshpeering_close(struct ieee80211_node *ni,
2075 	int category, int action, void *args0)
2076 {
2077 	struct ieee80211vap *vap = ni->ni_vap;
2078 	struct ieee80211com *ic = ni->ni_ic;
2079 	uint16_t *args = args0;
2080 	struct mbuf *m;
2081 	uint8_t *frm;
2082 
2083 	IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni,
2084 	    "send PEER CLOSE action: localid 0x%x, peerid 0x%x reason %d",
2085 	    args[0], args[1], args[2]);
2086 
2087 	IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
2088 	    "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__,
2089 	    ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)+1);
2090 	ieee80211_ref_node(ni);
2091 
2092 	m = ieee80211_getmgtframe(&frm,
2093 	    ic->ic_headroom + sizeof(struct ieee80211_frame),
2094 	    sizeof(uint16_t)	/* action+category */
2095 	    + sizeof(uint16_t)	/* reason code */
2096 	    + 2 + IEEE80211_MESHID_LEN
2097 	    + sizeof(struct ieee80211_meshpeer_ie)
2098 	);
2099 	if (m != NULL) {
2100 		/*
2101 		 * mesh peer close action frame format:
2102 		 *   [1] category
2103 		 *   [1] action
2104 		 *   [2] reason code
2105 		 *   [tlv] mesh id
2106 		 *   [tlv] mesh peer link mgmt
2107 		 */
2108 		*frm++ = category;
2109 		*frm++ = action;
2110 		ADDSHORT(frm, args[2]);		/* reason code */
2111 		frm = ieee80211_add_meshid(frm, vap);
2112 		frm = ieee80211_add_meshpeer(frm,
2113 		    IEEE80211_MESH_PEER_LINK_CLOSE,
2114 		    args[0], args[1], args[2]);
2115 		m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
2116 		return mesh_send_action(ni, m);
2117 	} else {
2118 		vap->iv_stats.is_tx_nobuf++;
2119 		ieee80211_free_node(ni);
2120 		return ENOMEM;
2121 	}
2122 }
2123 
2124 static int
2125 mesh_send_action_meshlmetric(struct ieee80211_node *ni,
2126 	int category, int action, void *arg0)
2127 {
2128 	struct ieee80211vap *vap = ni->ni_vap;
2129 	struct ieee80211com *ic = ni->ni_ic;
2130 	struct ieee80211_meshlmetric_ie *ie = arg0;
2131 	struct mbuf *m;
2132 	uint8_t *frm;
2133 
2134 	if (ie->lm_flags & IEEE80211_MESH_LMETRIC_FLAGS_REQ) {
2135 		IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
2136 		    ni, "%s", "send LINK METRIC REQUEST action");
2137 	} else {
2138 		IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
2139 		    ni, "send LINK METRIC REPLY action: metric 0x%x",
2140 		    ie->lm_metric);
2141 	}
2142 	IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
2143 	    "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__,
2144 	    ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)+1);
2145 	ieee80211_ref_node(ni);
2146 
2147 	m = ieee80211_getmgtframe(&frm,
2148 	    ic->ic_headroom + sizeof(struct ieee80211_frame),
2149 	    sizeof(uint16_t) +	/* action+category */
2150 	    sizeof(struct ieee80211_meshlmetric_ie)
2151 	);
2152 	if (m != NULL) {
2153 		/*
2154 		 * mesh link metric
2155 		 *   [1] category
2156 		 *   [1] action
2157 		 *   [tlv] mesh link metric
2158 		 */
2159 		*frm++ = category;
2160 		*frm++ = action;
2161 		frm = ieee80211_add_meshlmetric(frm,
2162 		    ie->lm_flags, ie->lm_metric);
2163 		m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
2164 		return mesh_send_action(ni, m);
2165 	} else {
2166 		vap->iv_stats.is_tx_nobuf++;
2167 		ieee80211_free_node(ni);
2168 		return ENOMEM;
2169 	}
2170 }
2171 
2172 static void
2173 mesh_peer_timeout_setup(struct ieee80211_node *ni)
2174 {
2175 	switch (ni->ni_mlstate) {
2176 	case IEEE80211_NODE_MESH_HOLDING:
2177 		ni->ni_mltval = ieee80211_mesh_holdingtimeout;
2178 		break;
2179 	case IEEE80211_NODE_MESH_CONFIRMRCV:
2180 		ni->ni_mltval = ieee80211_mesh_confirmtimeout;
2181 		break;
2182 	case IEEE80211_NODE_MESH_IDLE:
2183 		ni->ni_mltval = 0;
2184 		break;
2185 	default:
2186 		ni->ni_mltval = ieee80211_mesh_retrytimeout;
2187 		break;
2188 	}
2189 	if (ni->ni_mltval)
2190 		callout_reset(&ni->ni_mltimer, ni->ni_mltval,
2191 		    mesh_peer_timeout_cb, ni);
2192 }
2193 
2194 /*
2195  * Same as above but backoffs timer statisically 50%.
2196  */
2197 static void
2198 mesh_peer_timeout_backoff(struct ieee80211_node *ni)
2199 {
2200 	uint32_t r;
2201 
2202 	r = arc4random();
2203 	ni->ni_mltval += r % ni->ni_mltval;
2204 	callout_reset(&ni->ni_mltimer, ni->ni_mltval, mesh_peer_timeout_cb,
2205 	    ni);
2206 }
2207 
2208 static __inline void
2209 mesh_peer_timeout_stop(struct ieee80211_node *ni)
2210 {
2211 	callout_drain(&ni->ni_mltimer);
2212 }
2213 
2214 /*
2215  * Mesh Peer Link Management FSM timeout handling.
2216  */
2217 static void
2218 mesh_peer_timeout_cb(void *arg)
2219 {
2220 	struct ieee80211_node *ni = (struct ieee80211_node *)arg;
2221 	uint16_t args[3];
2222 
2223 	IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_MESH,
2224 	    ni, "mesh link timeout, state %d, retry counter %d",
2225 	    ni->ni_mlstate, ni->ni_mlrcnt);
2226 
2227 	switch (ni->ni_mlstate) {
2228 	case IEEE80211_NODE_MESH_IDLE:
2229 	case IEEE80211_NODE_MESH_ESTABLISHED:
2230 		break;
2231 	case IEEE80211_NODE_MESH_OPENSNT:
2232 	case IEEE80211_NODE_MESH_OPENRCV:
2233 		if (ni->ni_mlrcnt == ieee80211_mesh_maxretries) {
2234 			args[0] = ni->ni_mlpid;
2235 			args[2] = IEEE80211_REASON_MESH_MAX_RETRIES;
2236 			ieee80211_send_action(ni,
2237 			    IEEE80211_ACTION_CAT_MESHPEERING,
2238 			    IEEE80211_ACTION_MESHPEERING_CLOSE, args);
2239 			ni->ni_mlrcnt = 0;
2240 			mesh_linkchange(ni, IEEE80211_NODE_MESH_HOLDING);
2241 			mesh_peer_timeout_setup(ni);
2242 		} else {
2243 			args[0] = ni->ni_mlpid;
2244 			ieee80211_send_action(ni,
2245 			    IEEE80211_ACTION_CAT_MESHPEERING,
2246 			    IEEE80211_ACTION_MESHPEERING_OPEN, args);
2247 			ni->ni_mlrcnt++;
2248 			mesh_peer_timeout_backoff(ni);
2249 		}
2250 		break;
2251 	case IEEE80211_NODE_MESH_CONFIRMRCV:
2252 		if (ni->ni_mlrcnt == ieee80211_mesh_maxretries) {
2253 			args[0] = ni->ni_mlpid;
2254 			args[2] = IEEE80211_REASON_MESH_CONFIRM_TIMEOUT;
2255 			ieee80211_send_action(ni,
2256 			    IEEE80211_ACTION_CAT_MESHPEERING,
2257 			    IEEE80211_ACTION_MESHPEERING_CLOSE, args);
2258 			ni->ni_mlrcnt = 0;
2259 			mesh_linkchange(ni, IEEE80211_NODE_MESH_HOLDING);
2260 			mesh_peer_timeout_setup(ni);
2261 		} else {
2262 			ni->ni_mlrcnt++;
2263 			mesh_peer_timeout_setup(ni);
2264 		}
2265 		break;
2266 	case IEEE80211_NODE_MESH_HOLDING:
2267 		mesh_linkchange(ni, IEEE80211_NODE_MESH_IDLE);
2268 		break;
2269 	}
2270 }
2271 
2272 static int
2273 mesh_verify_meshid(struct ieee80211vap *vap, const uint8_t *ie)
2274 {
2275 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
2276 
2277 	if (ie == NULL || ie[1] != ms->ms_idlen)
2278 		return 1;
2279 	return memcmp(ms->ms_id, ie + 2, ms->ms_idlen);
2280 }
2281 
2282 /*
2283  * Check if we are using the same algorithms for this mesh.
2284  */
2285 static int
2286 mesh_verify_meshconf(struct ieee80211vap *vap, const uint8_t *ie)
2287 {
2288 	const struct ieee80211_meshconf_ie *meshconf =
2289 	    (const struct ieee80211_meshconf_ie *) ie;
2290 	const struct ieee80211_mesh_state *ms = vap->iv_mesh;
2291 
2292 	if (meshconf == NULL)
2293 		return 1;
2294 	if (meshconf->conf_pselid != ms->ms_ppath->mpp_ie) {
2295 		IEEE80211_DPRINTF(vap, IEEE80211_MSG_MESH,
2296 		    "unknown path selection algorithm: 0x%x\n",
2297 		    meshconf->conf_pselid);
2298 		return 1;
2299 	}
2300 	if (meshconf->conf_pmetid != ms->ms_pmetric->mpm_ie) {
2301 		IEEE80211_DPRINTF(vap, IEEE80211_MSG_MESH,
2302 		    "unknown path metric algorithm: 0x%x\n",
2303 		    meshconf->conf_pmetid);
2304 		return 1;
2305 	}
2306 	if (meshconf->conf_ccid != 0) {
2307 		IEEE80211_DPRINTF(vap, IEEE80211_MSG_MESH,
2308 		    "unknown congestion control algorithm: 0x%x\n",
2309 		    meshconf->conf_ccid);
2310 		return 1;
2311 	}
2312 	if (meshconf->conf_syncid != IEEE80211_MESHCONF_SYNC_NEIGHOFF) {
2313 		IEEE80211_DPRINTF(vap, IEEE80211_MSG_MESH,
2314 		    "unknown sync algorithm: 0x%x\n",
2315 		    meshconf->conf_syncid);
2316 		return 1;
2317 	}
2318 	if (meshconf->conf_authid != 0) {
2319 		IEEE80211_DPRINTF(vap, IEEE80211_MSG_MESH,
2320 		    "unknown auth auth algorithm: 0x%x\n",
2321 		    meshconf->conf_pselid);
2322 		return 1;
2323 	}
2324 	/* Not accepting peers */
2325 	if (!(meshconf->conf_cap & IEEE80211_MESHCONF_CAP_AP)) {
2326 		IEEE80211_DPRINTF(vap, IEEE80211_MSG_MESH,
2327 		    "not accepting peers: 0x%x\n", meshconf->conf_cap);
2328 		return 1;
2329 	}
2330 	return 0;
2331 }
2332 
2333 static int
2334 mesh_verify_meshpeer(struct ieee80211vap *vap, uint8_t subtype,
2335     const uint8_t *ie)
2336 {
2337 	const struct ieee80211_meshpeer_ie *meshpeer =
2338 	    (const struct ieee80211_meshpeer_ie *) ie;
2339 
2340 	if (meshpeer == NULL || meshpeer->peer_len < 6 ||
2341 	    meshpeer->peer_len > 10)
2342 		return 1;
2343 	switch (subtype) {
2344 	case IEEE80211_MESH_PEER_LINK_OPEN:
2345 		if (meshpeer->peer_len != 6)
2346 			return 1;
2347 		break;
2348 	case IEEE80211_MESH_PEER_LINK_CONFIRM:
2349 		if (meshpeer->peer_len != 8)
2350 			return 1;
2351 		break;
2352 	case IEEE80211_MESH_PEER_LINK_CLOSE:
2353 		if (meshpeer->peer_len < 8)
2354 			return 1;
2355 		if (meshpeer->peer_len == 8 && meshpeer->peer_linkid != 0)
2356 			return 1;
2357 		if (meshpeer->peer_rcode == 0)
2358 			return 1;
2359 		break;
2360 	}
2361 	return 0;
2362 }
2363 
2364 /*
2365  * Add a Mesh ID IE to a frame.
2366  */
2367 uint8_t *
2368 ieee80211_add_meshid(uint8_t *frm, struct ieee80211vap *vap)
2369 {
2370 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
2371 
2372 	KASSERT(vap->iv_opmode == IEEE80211_M_MBSS, ("not a mbss vap"));
2373 
2374 	*frm++ = IEEE80211_ELEMID_MESHID;
2375 	*frm++ = ms->ms_idlen;
2376 	memcpy(frm, ms->ms_id, ms->ms_idlen);
2377 	return frm + ms->ms_idlen;
2378 }
2379 
2380 /*
2381  * Add a Mesh Configuration IE to a frame.
2382  * For now just use HWMP routing, Airtime link metric, Null Congestion
2383  * Signaling, Null Sync Protocol and Null Authentication.
2384  */
2385 uint8_t *
2386 ieee80211_add_meshconf(uint8_t *frm, struct ieee80211vap *vap)
2387 {
2388 	const struct ieee80211_mesh_state *ms = vap->iv_mesh;
2389 	uint16_t caps;
2390 
2391 	KASSERT(vap->iv_opmode == IEEE80211_M_MBSS, ("not a MBSS vap"));
2392 
2393 	*frm++ = IEEE80211_ELEMID_MESHCONF;
2394 	*frm++ = IEEE80211_MESH_CONF_SZ;
2395 	*frm++ = ms->ms_ppath->mpp_ie;		/* path selection */
2396 	*frm++ = ms->ms_pmetric->mpm_ie;	/* link metric */
2397 	*frm++ = IEEE80211_MESHCONF_CC_DISABLED;
2398 	*frm++ = IEEE80211_MESHCONF_SYNC_NEIGHOFF;
2399 	*frm++ = IEEE80211_MESHCONF_AUTH_DISABLED;
2400 	/* NB: set the number of neighbors before the rest */
2401 	*frm = (ms->ms_neighbors > 15 ? 15 : ms->ms_neighbors) << 1;
2402 	if (ms->ms_flags & IEEE80211_MESHFLAGS_PORTAL)
2403 		*frm |= IEEE80211_MESHCONF_FORM_MP;
2404 	frm += 1;
2405 	caps = 0;
2406 	if (ms->ms_flags & IEEE80211_MESHFLAGS_AP)
2407 		caps |= IEEE80211_MESHCONF_CAP_AP;
2408 	if (ms->ms_flags & IEEE80211_MESHFLAGS_FWD)
2409 		caps |= IEEE80211_MESHCONF_CAP_FWRD;
2410 	*frm++ = caps;
2411 	return frm;
2412 }
2413 
2414 /*
2415  * Add a Mesh Peer Management IE to a frame.
2416  */
2417 uint8_t *
2418 ieee80211_add_meshpeer(uint8_t *frm, uint8_t subtype, uint16_t localid,
2419     uint16_t peerid, uint16_t reason)
2420 {
2421 	/* XXX change for AH */
2422 	static const uint8_t meshpeerproto[4] = IEEE80211_MESH_PEER_PROTO;
2423 
2424 	KASSERT(localid != 0, ("localid == 0"));
2425 
2426 	*frm++ = IEEE80211_ELEMID_MESHPEER;
2427 	switch (subtype) {
2428 	case IEEE80211_MESH_PEER_LINK_OPEN:
2429 		*frm++ = 6;		/* length */
2430 		memcpy(frm, meshpeerproto, 4);
2431 		frm += 4;
2432 		ADDSHORT(frm, localid);	/* local ID */
2433 		break;
2434 	case IEEE80211_MESH_PEER_LINK_CONFIRM:
2435 		KASSERT(peerid != 0, ("sending peer confirm without peer id"));
2436 		*frm++ = 8;		/* length */
2437 		memcpy(frm, meshpeerproto, 4);
2438 		frm += 4;
2439 		ADDSHORT(frm, localid);	/* local ID */
2440 		ADDSHORT(frm, peerid);	/* peer ID */
2441 		break;
2442 	case IEEE80211_MESH_PEER_LINK_CLOSE:
2443 		if (peerid)
2444 			*frm++ = 10;	/* length */
2445 		else
2446 			*frm++ = 8;	/* length */
2447 		memcpy(frm, meshpeerproto, 4);
2448 		frm += 4;
2449 		ADDSHORT(frm, localid);	/* local ID */
2450 		if (peerid)
2451 			ADDSHORT(frm, peerid);	/* peer ID */
2452 		ADDSHORT(frm, reason);
2453 		break;
2454 	}
2455 	return frm;
2456 }
2457 
2458 /*
2459  * Compute an Airtime Link Metric for the link with this node.
2460  *
2461  * Based on Draft 3.0 spec (11B.10, p.149).
2462  */
2463 /*
2464  * Max 802.11s overhead.
2465  */
2466 #define IEEE80211_MESH_MAXOVERHEAD \
2467 	(sizeof(struct ieee80211_qosframe_addr4) \
2468 	 + sizeof(struct ieee80211_meshcntl_ae11) \
2469 	+ sizeof(struct llc) \
2470 	+ IEEE80211_ADDR_LEN \
2471 	+ IEEE80211_WEP_IVLEN \
2472 	+ IEEE80211_WEP_KIDLEN \
2473 	+ IEEE80211_WEP_CRCLEN \
2474 	+ IEEE80211_WEP_MICLEN \
2475 	+ IEEE80211_CRC_LEN)
2476 uint32_t
2477 mesh_airtime_calc(struct ieee80211_node *ni)
2478 {
2479 #define M_BITS 8
2480 #define S_FACTOR (2 * M_BITS)
2481 	struct ieee80211com *ic = ni->ni_ic;
2482 	struct ifnet *ifp = ni->ni_vap->iv_ifp;
2483 	const static int nbits = 8192 << M_BITS;
2484 	uint32_t overhead, rate, errrate;
2485 	uint64_t res;
2486 
2487 	/* Time to transmit a frame */
2488 	rate = ni->ni_txrate;
2489 	overhead = ieee80211_compute_duration(ic->ic_rt,
2490 	    ifp->if_mtu + IEEE80211_MESH_MAXOVERHEAD, rate, 0) << M_BITS;
2491 	/* Error rate in percentage */
2492 	/* XXX assuming small failures are ok */
2493 	errrate = (((ifp->if_oerrors +
2494 	    ifp->if_ierrors) / 100) << M_BITS) / 100;
2495 	res = (overhead + (nbits / rate)) *
2496 	    ((1 << S_FACTOR) / ((1 << M_BITS) - errrate));
2497 
2498 	return (uint32_t)(res >> S_FACTOR);
2499 #undef M_BITS
2500 #undef S_FACTOR
2501 }
2502 
2503 /*
2504  * Add a Mesh Link Metric report IE to a frame.
2505  */
2506 uint8_t *
2507 ieee80211_add_meshlmetric(uint8_t *frm, uint8_t flags, uint32_t metric)
2508 {
2509 	*frm++ = IEEE80211_ELEMID_MESHLINK;
2510 	*frm++ = 5;
2511 	*frm++ = flags;
2512 	ADDWORD(frm, metric);
2513 	return frm;
2514 }
2515 #undef ADDSHORT
2516 #undef ADDWORD
2517 
2518 /*
2519  * Initialize any mesh-specific node state.
2520  */
2521 void
2522 ieee80211_mesh_node_init(struct ieee80211vap *vap, struct ieee80211_node *ni)
2523 {
2524 	ni->ni_flags |= IEEE80211_NODE_QOS;
2525 	callout_init(&ni->ni_mltimer, CALLOUT_MPSAFE);
2526 }
2527 
2528 /*
2529  * Cleanup any mesh-specific node state.
2530  */
2531 void
2532 ieee80211_mesh_node_cleanup(struct ieee80211_node *ni)
2533 {
2534 	struct ieee80211vap *vap = ni->ni_vap;
2535 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
2536 
2537 	callout_drain(&ni->ni_mltimer);
2538 	/* NB: short-circuit callbacks after mesh_vdetach */
2539 	if (vap->iv_mesh != NULL)
2540 		ms->ms_ppath->mpp_peerdown(ni);
2541 }
2542 
2543 void
2544 ieee80211_parse_meshid(struct ieee80211_node *ni, const uint8_t *ie)
2545 {
2546 	ni->ni_meshidlen = ie[1];
2547 	memcpy(ni->ni_meshid, ie + 2, ie[1]);
2548 }
2549 
2550 /*
2551  * Setup mesh-specific node state on neighbor discovery.
2552  */
2553 void
2554 ieee80211_mesh_init_neighbor(struct ieee80211_node *ni,
2555 	const struct ieee80211_frame *wh,
2556 	const struct ieee80211_scanparams *sp)
2557 {
2558 	ieee80211_parse_meshid(ni, sp->meshid);
2559 }
2560 
2561 void
2562 ieee80211_mesh_update_beacon(struct ieee80211vap *vap,
2563 	struct ieee80211_beacon_offsets *bo)
2564 {
2565 	KASSERT(vap->iv_opmode == IEEE80211_M_MBSS, ("not a MBSS vap"));
2566 
2567 	if (isset(bo->bo_flags, IEEE80211_BEACON_MESHCONF)) {
2568 		(void)ieee80211_add_meshconf(bo->bo_meshconf, vap);
2569 		clrbit(bo->bo_flags, IEEE80211_BEACON_MESHCONF);
2570 	}
2571 }
2572 
2573 static int
2574 mesh_ioctl_get80211(struct ieee80211vap *vap, struct ieee80211req *ireq)
2575 {
2576 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
2577 	uint8_t tmpmeshid[IEEE80211_NWID_LEN];
2578 	struct ieee80211_mesh_route *rt;
2579 	struct ieee80211req_mesh_route *imr;
2580 	size_t len, off;
2581 	uint8_t *p;
2582 	int error;
2583 
2584 	if (vap->iv_opmode != IEEE80211_M_MBSS)
2585 		return ENOSYS;
2586 
2587 	error = 0;
2588 	switch (ireq->i_type) {
2589 	case IEEE80211_IOC_MESH_ID:
2590 		ireq->i_len = ms->ms_idlen;
2591 		memcpy(tmpmeshid, ms->ms_id, ireq->i_len);
2592 		error = copyout(tmpmeshid, ireq->i_data, ireq->i_len);
2593 		break;
2594 	case IEEE80211_IOC_MESH_AP:
2595 		ireq->i_val = (ms->ms_flags & IEEE80211_MESHFLAGS_AP) != 0;
2596 		break;
2597 	case IEEE80211_IOC_MESH_FWRD:
2598 		ireq->i_val = (ms->ms_flags & IEEE80211_MESHFLAGS_FWD) != 0;
2599 		break;
2600 	case IEEE80211_IOC_MESH_TTL:
2601 		ireq->i_val = ms->ms_ttl;
2602 		break;
2603 	case IEEE80211_IOC_MESH_RTCMD:
2604 		switch (ireq->i_val) {
2605 		case IEEE80211_MESH_RTCMD_LIST:
2606 			len = 0;
2607 			MESH_RT_LOCK(ms);
2608 			TAILQ_FOREACH(rt, &ms->ms_routes, rt_next) {
2609 				len += sizeof(*imr);
2610 			}
2611 			MESH_RT_UNLOCK(ms);
2612 			if (len > ireq->i_len || ireq->i_len < sizeof(*imr)) {
2613 				ireq->i_len = len;
2614 				return ENOMEM;
2615 			}
2616 			ireq->i_len = len;
2617 			/* XXX M_WAIT? */
2618 			p = malloc(len, M_TEMP, M_NOWAIT | M_ZERO);
2619 			if (p == NULL)
2620 				return ENOMEM;
2621 			off = 0;
2622 			MESH_RT_LOCK(ms);
2623 			TAILQ_FOREACH(rt, &ms->ms_routes, rt_next) {
2624 				if (off >= len)
2625 					break;
2626 				imr = (struct ieee80211req_mesh_route *)
2627 				    (p + off);
2628 				imr->imr_flags = rt->rt_flags;
2629 				IEEE80211_ADDR_COPY(imr->imr_dest,
2630 				    rt->rt_dest);
2631 				IEEE80211_ADDR_COPY(imr->imr_nexthop,
2632 				    rt->rt_nexthop);
2633 				imr->imr_metric = rt->rt_metric;
2634 				imr->imr_nhops = rt->rt_nhops;
2635 				imr->imr_lifetime = rt->rt_lifetime;
2636 				imr->imr_lastmseq = rt->rt_lastmseq;
2637 				off += sizeof(*imr);
2638 			}
2639 			MESH_RT_UNLOCK(ms);
2640 			error = copyout(p, (uint8_t *)ireq->i_data,
2641 			    ireq->i_len);
2642 			free(p, M_TEMP);
2643 			break;
2644 		case IEEE80211_MESH_RTCMD_FLUSH:
2645 		case IEEE80211_MESH_RTCMD_ADD:
2646 		case IEEE80211_MESH_RTCMD_DELETE:
2647 			return EINVAL;
2648 		default:
2649 			return ENOSYS;
2650 		}
2651 		break;
2652 	case IEEE80211_IOC_MESH_PR_METRIC:
2653 		len = strlen(ms->ms_pmetric->mpm_descr);
2654 		if (ireq->i_len < len)
2655 			return EINVAL;
2656 		ireq->i_len = len;
2657 		error = copyout(ms->ms_pmetric->mpm_descr,
2658 		    (uint8_t *)ireq->i_data, len);
2659 		break;
2660 	case IEEE80211_IOC_MESH_PR_PATH:
2661 		len = strlen(ms->ms_ppath->mpp_descr);
2662 		if (ireq->i_len < len)
2663 			return EINVAL;
2664 		ireq->i_len = len;
2665 		error = copyout(ms->ms_ppath->mpp_descr,
2666 		    (uint8_t *)ireq->i_data, len);
2667 		break;
2668 	default:
2669 		return ENOSYS;
2670 	}
2671 
2672 	return error;
2673 }
2674 IEEE80211_IOCTL_GET(mesh, mesh_ioctl_get80211);
2675 
2676 static int
2677 mesh_ioctl_set80211(struct ieee80211vap *vap, struct ieee80211req *ireq)
2678 {
2679 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
2680 	uint8_t tmpmeshid[IEEE80211_NWID_LEN];
2681 	uint8_t tmpaddr[IEEE80211_ADDR_LEN];
2682 	char tmpproto[IEEE80211_MESH_PROTO_DSZ];
2683 	int error;
2684 
2685 	if (vap->iv_opmode != IEEE80211_M_MBSS)
2686 		return ENOSYS;
2687 
2688 	error = 0;
2689 	switch (ireq->i_type) {
2690 	case IEEE80211_IOC_MESH_ID:
2691 		if (ireq->i_val != 0 || ireq->i_len > IEEE80211_MESHID_LEN)
2692 			return EINVAL;
2693 		error = copyin(ireq->i_data, tmpmeshid, ireq->i_len);
2694 		if (error != 0)
2695 			break;
2696 		memset(ms->ms_id, 0, IEEE80211_NWID_LEN);
2697 		ms->ms_idlen = ireq->i_len;
2698 		memcpy(ms->ms_id, tmpmeshid, ireq->i_len);
2699 		error = ENETRESET;
2700 		break;
2701 	case IEEE80211_IOC_MESH_AP:
2702 		if (ireq->i_val)
2703 			ms->ms_flags |= IEEE80211_MESHFLAGS_AP;
2704 		else
2705 			ms->ms_flags &= ~IEEE80211_MESHFLAGS_AP;
2706 		error = ENETRESET;
2707 		break;
2708 	case IEEE80211_IOC_MESH_FWRD:
2709 		if (ireq->i_val)
2710 			ms->ms_flags |= IEEE80211_MESHFLAGS_FWD;
2711 		else
2712 			ms->ms_flags &= ~IEEE80211_MESHFLAGS_FWD;
2713 		break;
2714 	case IEEE80211_IOC_MESH_TTL:
2715 		ms->ms_ttl = (uint8_t) ireq->i_val;
2716 		break;
2717 	case IEEE80211_IOC_MESH_RTCMD:
2718 		switch (ireq->i_val) {
2719 		case IEEE80211_MESH_RTCMD_LIST:
2720 			return EINVAL;
2721 		case IEEE80211_MESH_RTCMD_FLUSH:
2722 			ieee80211_mesh_rt_flush(vap);
2723 			break;
2724 		case IEEE80211_MESH_RTCMD_ADD:
2725 			if (IEEE80211_ADDR_EQ(vap->iv_myaddr, ireq->i_data) ||
2726 			    IEEE80211_ADDR_EQ(broadcastaddr, ireq->i_data))
2727 				return EINVAL;
2728 			error = copyin(ireq->i_data, &tmpaddr,
2729 			    IEEE80211_ADDR_LEN);
2730 			if (error == 0)
2731 				ieee80211_mesh_discover(vap, tmpaddr, NULL);
2732 			break;
2733 		case IEEE80211_MESH_RTCMD_DELETE:
2734 			ieee80211_mesh_rt_del(vap, ireq->i_data);
2735 			break;
2736 		default:
2737 			return ENOSYS;
2738 		}
2739 		break;
2740 	case IEEE80211_IOC_MESH_PR_METRIC:
2741 		error = copyin(ireq->i_data, tmpproto, sizeof(tmpproto));
2742 		if (error == 0) {
2743 			error = mesh_select_proto_metric(vap, tmpproto);
2744 			if (error == 0)
2745 				error = ENETRESET;
2746 		}
2747 		break;
2748 	case IEEE80211_IOC_MESH_PR_PATH:
2749 		error = copyin(ireq->i_data, tmpproto, sizeof(tmpproto));
2750 		if (error == 0) {
2751 			error = mesh_select_proto_path(vap, tmpproto);
2752 			if (error == 0)
2753 				error = ENETRESET;
2754 		}
2755 		break;
2756 	default:
2757 		return ENOSYS;
2758 	}
2759 	return error;
2760 }
2761 IEEE80211_IOCTL_SET(mesh, mesh_ioctl_set80211);
2762