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