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