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