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