Fix remaining M_NOWAIT and use ieee80211_handoff instead of if_transmit.
[dragonfly.git] / sys / netproto / 802_11 / wlan / ieee80211_dragonfly.c
1 /*-
2  * Copyright (c) 2003-2009 Sam Leffler, Errno Consulting
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  * $FreeBSD: head/sys/net80211/ieee80211_freebsd.c 202612 2010-01-19 05:00:57Z thompsa $
26  * $DragonFly$
27  */
28
29 /*
30  * IEEE 802.11 support (DragonFlyBSD-specific code)
31  */
32 #include "opt_wlan.h"
33
34 #include <sys/param.h>
35 #include <sys/kernel.h>
36 #include <sys/systm.h> 
37 #include <sys/linker.h>
38 #include <sys/mbuf.h>   
39 #include <sys/module.h>
40 #include <sys/proc.h>
41 #include <sys/sysctl.h>
42
43 #include <sys/socket.h>
44
45 #include <net/bpf.h>
46 #include <net/if.h>
47 #include <net/if_dl.h>
48 #include <net/if_clone.h>
49 #include <net/if_media.h>
50 #include <net/if_types.h>
51 #include <net/ethernet.h>
52 #include <net/route.h>
53 #include <net/ifq_var.h>
54
55 #include <netproto/802_11/ieee80211_var.h>
56 #include <netproto/802_11/ieee80211_input.h>
57
58 SYSCTL_NODE(_net, OID_AUTO, wlan, CTLFLAG_RD, 0, "IEEE 80211 parameters");
59
60 #ifdef IEEE80211_DEBUG
61 int     ieee80211_debug = 0;
62 SYSCTL_INT(_net_wlan, OID_AUTO, debug, CTLFLAG_RW, &ieee80211_debug,
63             0, "debugging printfs");
64 #endif
65
66 MALLOC_DEFINE(M_80211_COM, "80211com", "802.11 com state");
67
68
69 static void     wlan_clone_destroy(struct ifnet *);
70 static int      wlan_clone_create(struct if_clone *, int, caddr_t);
71
72 static struct if_clone wlan_cloner = 
73         IF_CLONE_INITIALIZER("wlan", wlan_clone_create, wlan_clone_destroy,
74             0, IF_MAXUNIT);
75
76
77 /*
78  * Allocate/free com structure in conjunction with ifnet;
79  * these routines are registered with if_register_com_alloc
80  * below and are called automatically by the ifnet code
81  * when the ifnet of the parent device is created.
82  */
83 static void *
84 wlan_alloc(u_char type, struct ifnet *ifp)
85 {
86         struct ieee80211com *ic;
87
88         ic = kmalloc(sizeof(struct ieee80211com), M_80211_COM, M_WAITOK|M_ZERO);
89         ic->ic_ifp = ifp;
90
91         return (ic);
92 }
93
94 static void
95 wlan_free(void *ic, u_char type)
96 {
97         kfree(ic, M_80211_COM);
98 }
99
100 static int
101 wlan_clone_create(struct if_clone *ifc, int unit, caddr_t params)
102 {
103         struct ieee80211_clone_params cp;
104         struct ieee80211vap *vap;
105         struct ieee80211com *ic;
106         struct ifnet *ifp;
107         int error;
108
109         error = copyin(params, &cp, sizeof(cp));
110         if (error)
111                 return error;
112         ifp = ifunit(cp.icp_parent);
113         if (ifp == NULL)
114                 return ENXIO;
115         /* XXX move printfs to DIAGNOSTIC before release */
116         if (ifp->if_type != IFT_IEEE80211) {
117                 if_printf(ifp, "%s: reject, not an 802.11 device\n", __func__);
118                 return ENXIO;
119         }
120         if (cp.icp_opmode >= IEEE80211_OPMODE_MAX) {
121                 if_printf(ifp, "%s: invalid opmode %d\n",
122                     __func__, cp.icp_opmode);
123                 return EINVAL;
124         }
125         ic = ifp->if_l2com;
126         if ((ic->ic_caps & ieee80211_opcap[cp.icp_opmode]) == 0) {
127                 if_printf(ifp, "%s mode not supported\n",
128                     ieee80211_opmode_name[cp.icp_opmode]);
129                 return EOPNOTSUPP;
130         }
131         if ((cp.icp_flags & IEEE80211_CLONE_TDMA) &&
132 #ifdef IEEE80211_SUPPORT_TDMA
133             (ic->ic_caps & IEEE80211_C_TDMA) == 0
134 #else
135             (1)
136 #endif
137         ) {
138                 if_printf(ifp, "TDMA not supported\n");
139                 return EOPNOTSUPP;
140         }
141         vap = ic->ic_vap_create(ic, ifc->ifc_name, unit,
142                         cp.icp_opmode, cp.icp_flags, cp.icp_bssid,
143                         cp.icp_flags & IEEE80211_CLONE_MACADDR ?
144                             cp.icp_macaddr : (const uint8_t *)IF_LLADDR(ifp));
145         return (vap == NULL ? EIO : 0);
146 }
147
148 static void
149 wlan_clone_destroy(struct ifnet *ifp)
150 {
151         struct ieee80211vap *vap = ifp->if_softc;
152         struct ieee80211com *ic = vap->iv_ic;
153
154         ic->ic_vap_delete(vap);
155 }
156
157 void
158 ieee80211_vap_destroy(struct ieee80211vap *vap)
159 {
160 #ifdef __FreeBSD__
161         if_clone_destroyif(&wlan_cloner, vap->iv_ifp);
162 #endif
163 }
164
165 int
166 ieee80211_sysctl_msecs_ticks(SYSCTL_HANDLER_ARGS)
167 {
168         int msecs = ticks_to_msecs(*(int *)arg1);
169         int error, t;
170
171         error = sysctl_handle_int(oidp, &msecs, 0, req);
172         if (error || !req->newptr)
173                 return error;
174         t = msecs_to_ticks(msecs);
175         *(int *)arg1 = (t < 1) ? 1 : t;
176         return 0;
177 }
178
179 static int
180 ieee80211_sysctl_inact(SYSCTL_HANDLER_ARGS)
181 {
182         int inact = (*(int *)arg1) * IEEE80211_INACT_WAIT;
183         int error;
184
185         error = sysctl_handle_int(oidp, &inact, 0, req);
186         if (error || !req->newptr)
187                 return error;
188         *(int *)arg1 = inact / IEEE80211_INACT_WAIT;
189         return 0;
190 }
191
192 static int
193 ieee80211_sysctl_parent(SYSCTL_HANDLER_ARGS)
194 {
195         struct ieee80211com *ic = arg1;
196         const char *name = ic->ic_ifp->if_xname;
197
198         return SYSCTL_OUT(req, name, strlen(name));
199 }
200
201 static int
202 ieee80211_sysctl_radar(SYSCTL_HANDLER_ARGS)
203 {
204         struct ieee80211com *ic = arg1;
205         int t = 0, error;
206
207         error = sysctl_handle_int(oidp, &t, 0, req);
208         if (error || !req->newptr)
209                 return error;
210         IEEE80211_LOCK(ic);
211         ieee80211_dfs_notify_radar(ic, ic->ic_curchan);
212         IEEE80211_UNLOCK(ic);
213         return 0;
214 }
215
216 void
217 ieee80211_sysctl_attach(struct ieee80211com *ic)
218 {
219 }
220
221 void
222 ieee80211_sysctl_detach(struct ieee80211com *ic)
223 {
224 }
225
226 void
227 ieee80211_sysctl_vattach(struct ieee80211vap *vap)
228 {
229         struct ifnet *ifp = vap->iv_ifp;
230         struct sysctl_ctx_list *ctx;
231         struct sysctl_oid *oid;
232         char num[14];                   /* sufficient for 32 bits */
233
234         ctx = (struct sysctl_ctx_list *) kmalloc(sizeof(struct sysctl_ctx_list),
235                 M_DEVBUF, M_INTWAIT | M_ZERO);
236         if (ctx == NULL) {
237                 if_printf(ifp, "%s: cannot allocate sysctl context!\n",
238                         __func__);
239                 return;
240         }
241         sysctl_ctx_init(ctx);
242         ksnprintf(num, sizeof(num), "%u", ifp->if_dunit);
243         oid = SYSCTL_ADD_NODE(ctx, &SYSCTL_NODE_CHILDREN(_net, wlan),
244                 OID_AUTO, num, CTLFLAG_RD, NULL, "");
245         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
246                 "%parent", CTLFLAG_RD, vap->iv_ic, 0,
247                 ieee80211_sysctl_parent, "A", "parent device");
248         SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
249                 "driver_caps", CTLFLAG_RW, &vap->iv_caps, 0,
250                 "driver capabilities");
251 #ifdef IEEE80211_DEBUG
252         vap->iv_debug = ieee80211_debug;
253         SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
254                 "debug", CTLFLAG_RW, &vap->iv_debug, 0,
255                 "control debugging printfs");
256 #endif
257         SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
258                 "bmiss_max", CTLFLAG_RW, &vap->iv_bmiss_max, 0,
259                 "consecutive beacon misses before scanning");
260         /* XXX inherit from tunables */
261         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
262                 "inact_run", CTLTYPE_INT | CTLFLAG_RW, &vap->iv_inact_run, 0,
263                 ieee80211_sysctl_inact, "I",
264                 "station inactivity timeout (sec)");
265         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
266                 "inact_probe", CTLTYPE_INT | CTLFLAG_RW, &vap->iv_inact_probe, 0,
267                 ieee80211_sysctl_inact, "I",
268                 "station inactivity probe timeout (sec)");
269         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
270                 "inact_auth", CTLTYPE_INT | CTLFLAG_RW, &vap->iv_inact_auth, 0,
271                 ieee80211_sysctl_inact, "I",
272                 "station authentication timeout (sec)");
273         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
274                 "inact_init", CTLTYPE_INT | CTLFLAG_RW, &vap->iv_inact_init, 0,
275                 ieee80211_sysctl_inact, "I",
276                 "station initial state timeout (sec)");
277         if (vap->iv_htcaps & IEEE80211_HTC_HT) {
278                 SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
279                         "ampdu_mintraffic_bk", CTLFLAG_RW,
280                         &vap->iv_ampdu_mintraffic[WME_AC_BK], 0,
281                         "BK traffic tx aggr threshold (pps)");
282                 SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
283                         "ampdu_mintraffic_be", CTLFLAG_RW,
284                         &vap->iv_ampdu_mintraffic[WME_AC_BE], 0,
285                         "BE traffic tx aggr threshold (pps)");
286                 SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
287                         "ampdu_mintraffic_vo", CTLFLAG_RW,
288                         &vap->iv_ampdu_mintraffic[WME_AC_VO], 0,
289                         "VO traffic tx aggr threshold (pps)");
290                 SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
291                         "ampdu_mintraffic_vi", CTLFLAG_RW,
292                         &vap->iv_ampdu_mintraffic[WME_AC_VI], 0,
293                         "VI traffic tx aggr threshold (pps)");
294         }
295         if (vap->iv_caps & IEEE80211_C_DFS) {
296                 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
297                         "radar", CTLTYPE_INT | CTLFLAG_RW, vap->iv_ic, 0,
298                         ieee80211_sysctl_radar, "I", "simulate radar event");
299         }
300         vap->iv_sysctl = ctx;
301         vap->iv_oid = oid;
302 }
303
304 void
305 ieee80211_sysctl_vdetach(struct ieee80211vap *vap)
306 {
307
308         if (vap->iv_sysctl != NULL) {
309                 sysctl_ctx_free(vap->iv_sysctl);
310                 kfree(vap->iv_sysctl, M_DEVBUF);
311                 vap->iv_sysctl = NULL;
312         }
313 }
314
315 int
316 ieee80211_node_dectestref(struct ieee80211_node *ni)
317 {
318         /* XXX need equivalent of atomic_dec_and_test */
319         atomic_subtract_int(&ni->ni_refcnt, 1);
320         return atomic_cmpset_int(&ni->ni_refcnt, 0, 1);
321 }
322
323 void
324 ieee80211_drain_ifq(struct ifqueue *ifq)
325 {
326         struct ieee80211_node *ni;
327         struct mbuf *m;
328
329         for (;;) {
330                 IF_DEQUEUE(ifq, m);
331                 if (m == NULL)
332                         break;
333
334                 ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
335                 KASSERT(ni != NULL, ("frame w/o node"));
336                 ieee80211_free_node(ni);
337                 m->m_pkthdr.rcvif = NULL;
338
339                 m_freem(m);
340         }
341 }
342
343 void
344 ieee80211_flush_ifq(struct ifqueue *ifq, struct ieee80211vap *vap)
345 {
346         struct ieee80211_node *ni;
347         struct mbuf *m, **mprev;
348
349         IF_LOCK(ifq);
350         mprev = &ifq->ifq_head;
351         while ((m = *mprev) != NULL) {
352                 ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
353                 if (ni != NULL && ni->ni_vap == vap) {
354                         *mprev = m->m_nextpkt;          /* remove from list */
355                         ifq->ifq_len--;
356
357                         m_freem(m);
358                         ieee80211_free_node(ni);        /* reclaim ref */
359                 } else
360                         mprev = &m->m_nextpkt;
361         }
362         /* recalculate tail ptr */
363         m = ifq->ifq_head;
364         for (; m != NULL && m->m_nextpkt != NULL; m = m->m_nextpkt)
365                 ;
366         ifq->ifq_tail = m;
367         IF_UNLOCK(ifq);
368 }
369
370 /*
371  * As above, for mbufs allocated with m_gethdr/MGETHDR
372  * or initialized by M_COPY_PKTHDR.
373  */
374 #define MC_ALIGN(m, len)                                                \
375 do {                                                                    \
376         (m)->m_data += (MCLBYTES - (len)) &~ (sizeof(long) - 1);        \
377 } while (/* CONSTCOND */ 0)
378
379 /*
380  * Allocate and setup a management frame of the specified
381  * size.  We return the mbuf and a pointer to the start
382  * of the contiguous data area that's been reserved based
383  * on the packet length.  The data area is forced to 32-bit
384  * alignment and the buffer length to a multiple of 4 bytes.
385  * This is done mainly so beacon frames (that require this)
386  * can use this interface too.
387  */
388 struct mbuf *
389 ieee80211_getmgtframe(uint8_t **frm, int headroom, int pktlen)
390 {
391         struct mbuf *m;
392         u_int len;
393
394         /*
395          * NB: we know the mbuf routines will align the data area
396          *     so we don't need to do anything special.
397          */
398         len = roundup2(headroom + pktlen, 4);
399         KASSERT(len <= MCLBYTES, ("802.11 mgt frame too large: %u", len));
400         if (len < MINCLSIZE) {
401                 m = m_gethdr(M_INTWAIT, MT_DATA);
402                 /*
403                  * Align the data in case additional headers are added.
404                  * This should only happen when a WEP header is added
405                  * which only happens for shared key authentication mgt
406                  * frames which all fit in MHLEN.
407                  */
408                 if (m != NULL)
409                         MH_ALIGN(m, len);
410         } else {
411                 m = m_getcl(M_INTWAIT, MT_DATA, M_PKTHDR);
412                 if (m != NULL)
413                         MC_ALIGN(m, len);
414         }
415         if (m != NULL) {
416                 m->m_data += headroom;
417                 *frm = m->m_data;
418         }
419         return m;
420 }
421
422 /*
423  * Re-align the payload in the mbuf.  This is mainly used (right now)
424  * to handle IP header alignment requirements on certain architectures.
425  */
426 struct mbuf *
427 ieee80211_realign(struct ieee80211vap *vap, struct mbuf *m, size_t align)
428 {
429         int pktlen, space;
430         struct mbuf *n = NULL;
431
432         pktlen = m->m_pkthdr.len;
433         space = pktlen + align;
434         if (space < MINCLSIZE)
435                 n = m_gethdr(MB_DONTWAIT, MT_DATA);
436 #ifdef notyet
437         else {
438                 n = m_getjcl(MB_DONTWAIT, MT_DATA, M_PKTHDR,
439                     space <= MCLBYTES ?     MCLBYTES :
440 #if MJUMPAGESIZE != MCLBYTES
441                     space <= MJUMPAGESIZE ? MJUMPAGESIZE :
442 #endif
443                     space <= MJUM9BYTES ?   MJUM9BYTES : MJUM16BYTES);
444         }
445 #endif
446         if (__predict_true(n != NULL)) {
447                 m_move_pkthdr(n, m);
448                 n->m_data = (caddr_t)(ALIGN(n->m_data + align) - align);
449                 m_copydata(m, 0, pktlen, mtod(n, caddr_t));
450                 n->m_len = pktlen;
451         } else {
452                 IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
453                     mtod(m, const struct ieee80211_frame *), NULL,
454                     "%s", "no mbuf to realign");
455                 vap->iv_stats.is_rx_badalign++;
456         }
457         m_freem(m);
458         return n;
459 }
460
461 int
462 ieee80211_add_callback(struct mbuf *m,
463         void (*func)(struct ieee80211_node *, void *, int), void *arg)
464 {
465         struct m_tag *mtag;
466         struct ieee80211_cb *cb;
467
468         mtag = m_tag_alloc(MTAG_ABI_NET80211, NET80211_TAG_CALLBACK,
469                         sizeof(struct ieee80211_cb), M_INTWAIT);
470         if (mtag == NULL)
471                 return 0;
472
473         cb = (struct ieee80211_cb *)(mtag+1);
474         cb->func = func;
475         cb->arg = arg;
476         m_tag_prepend(m, mtag);
477         m->m_flags |= M_TXCB;
478         return 1;
479 }
480
481 void
482 ieee80211_process_callback(struct ieee80211_node *ni,
483         struct mbuf *m, int status)
484 {
485         struct m_tag *mtag;
486
487         mtag = m_tag_locate(m, MTAG_ABI_NET80211, NET80211_TAG_CALLBACK, NULL);
488         if (mtag != NULL) {
489                 struct ieee80211_cb *cb = (struct ieee80211_cb *)(mtag+1);
490                 cb->func(ni, cb->arg, status);
491         }
492 }
493
494 #include <sys/libkern.h>
495
496 void
497 get_random_bytes(void *p, size_t n)
498 {
499         uint8_t *dp = p;
500
501         while (n > 0) {
502                 uint32_t v = karc4random();
503                 size_t nb = n > sizeof(uint32_t) ? sizeof(uint32_t) : n;
504                 bcopy(&v, dp, n > sizeof(uint32_t) ? sizeof(uint32_t) : n);
505                 dp += sizeof(uint32_t), n -= nb;
506         }
507 }
508
509 /*
510  * Helper function for events that pass just a single mac address.
511  */
512 static void
513 notify_macaddr(struct ifnet *ifp, int op, const uint8_t mac[IEEE80211_ADDR_LEN])
514 {
515         struct ieee80211_join_event iev;
516
517         memset(&iev, 0, sizeof(iev));
518         IEEE80211_ADDR_COPY(iev.iev_addr, mac);
519         rt_ieee80211msg(ifp, op, &iev, sizeof(iev));
520 }
521
522 void
523 ieee80211_notify_node_join(struct ieee80211_node *ni, int newassoc)
524 {
525         struct ieee80211vap *vap = ni->ni_vap;
526         struct ifnet *ifp = vap->iv_ifp;
527
528         IEEE80211_NOTE(vap, IEEE80211_MSG_NODE, ni, "%snode join",
529             (ni == vap->iv_bss) ? "bss " : "");
530
531         if (ni == vap->iv_bss) {
532                 notify_macaddr(ifp, newassoc ?
533                     RTM_IEEE80211_ASSOC : RTM_IEEE80211_REASSOC, ni->ni_bssid);
534                 if_link_state_change(ifp);
535         } else {
536                 notify_macaddr(ifp, newassoc ?
537                     RTM_IEEE80211_JOIN : RTM_IEEE80211_REJOIN, ni->ni_macaddr);
538         }
539 }
540
541 void
542 ieee80211_notify_node_leave(struct ieee80211_node *ni)
543 {
544         struct ieee80211vap *vap = ni->ni_vap;
545         struct ifnet *ifp = vap->iv_ifp;
546
547         IEEE80211_NOTE(vap, IEEE80211_MSG_NODE, ni, "%snode leave",
548             (ni == vap->iv_bss) ? "bss " : "");
549
550         if (ni == vap->iv_bss) {
551                 rt_ieee80211msg(ifp, RTM_IEEE80211_DISASSOC, NULL, 0);
552                 if_link_state_change(ifp);
553         } else {
554                 /* fire off wireless event station leaving */
555                 notify_macaddr(ifp, RTM_IEEE80211_LEAVE, ni->ni_macaddr);
556         }
557 }
558
559 void
560 ieee80211_notify_scan_done(struct ieee80211vap *vap)
561 {
562         struct ifnet *ifp = vap->iv_ifp;
563
564         IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s\n", "notify scan done");
565
566         /* dispatch wireless event indicating scan completed */
567         rt_ieee80211msg(ifp, RTM_IEEE80211_SCAN, NULL, 0);
568 }
569
570 void
571 ieee80211_notify_replay_failure(struct ieee80211vap *vap,
572         const struct ieee80211_frame *wh, const struct ieee80211_key *k,
573         u_int64_t rsc, int tid)
574 {
575         struct ifnet *ifp = vap->iv_ifp;
576
577         IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2,
578             "%s replay detected <rsc %ju, csc %ju, keyix %u rxkeyix %u>",
579             k->wk_cipher->ic_name, (intmax_t) rsc,
580             (intmax_t) k->wk_keyrsc[tid],
581             k->wk_keyix, k->wk_rxkeyix);
582
583         if (ifp != NULL) {              /* NB: for cipher test modules */
584                 struct ieee80211_replay_event iev;
585
586                 IEEE80211_ADDR_COPY(iev.iev_dst, wh->i_addr1);
587                 IEEE80211_ADDR_COPY(iev.iev_src, wh->i_addr2);
588                 iev.iev_cipher = k->wk_cipher->ic_cipher;
589                 if (k->wk_rxkeyix != IEEE80211_KEYIX_NONE)
590                         iev.iev_keyix = k->wk_rxkeyix;
591                 else
592                         iev.iev_keyix = k->wk_keyix;
593                 iev.iev_keyrsc = k->wk_keyrsc[tid];
594                 iev.iev_rsc = rsc;
595                 rt_ieee80211msg(ifp, RTM_IEEE80211_REPLAY, &iev, sizeof(iev));
596         }
597 }
598
599 void
600 ieee80211_notify_michael_failure(struct ieee80211vap *vap,
601         const struct ieee80211_frame *wh, u_int keyix)
602 {
603         struct ifnet *ifp = vap->iv_ifp;
604
605         IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2,
606             "michael MIC verification failed <keyix %u>", keyix);
607         vap->iv_stats.is_rx_tkipmic++;
608
609         if (ifp != NULL) {              /* NB: for cipher test modules */
610                 struct ieee80211_michael_event iev;
611
612                 IEEE80211_ADDR_COPY(iev.iev_dst, wh->i_addr1);
613                 IEEE80211_ADDR_COPY(iev.iev_src, wh->i_addr2);
614                 iev.iev_cipher = IEEE80211_CIPHER_TKIP;
615                 iev.iev_keyix = keyix;
616                 rt_ieee80211msg(ifp, RTM_IEEE80211_MICHAEL, &iev, sizeof(iev));
617         }
618 }
619
620 void
621 ieee80211_notify_wds_discover(struct ieee80211_node *ni)
622 {
623         struct ieee80211vap *vap = ni->ni_vap;
624         struct ifnet *ifp = vap->iv_ifp;
625
626         notify_macaddr(ifp, RTM_IEEE80211_WDS, ni->ni_macaddr);
627 }
628
629 void
630 ieee80211_notify_csa(struct ieee80211com *ic,
631         const struct ieee80211_channel *c, int mode, int count)
632 {
633         struct ifnet *ifp = ic->ic_ifp;
634         struct ieee80211_csa_event iev;
635
636         memset(&iev, 0, sizeof(iev));
637         iev.iev_flags = c->ic_flags;
638         iev.iev_freq = c->ic_freq;
639         iev.iev_ieee = c->ic_ieee;
640         iev.iev_mode = mode;
641         iev.iev_count = count;
642         rt_ieee80211msg(ifp, RTM_IEEE80211_CSA, &iev, sizeof(iev));
643 }
644
645 void
646 ieee80211_notify_radar(struct ieee80211com *ic,
647         const struct ieee80211_channel *c)
648 {
649         struct ifnet *ifp = ic->ic_ifp;
650         struct ieee80211_radar_event iev;
651
652         memset(&iev, 0, sizeof(iev));
653         iev.iev_flags = c->ic_flags;
654         iev.iev_freq = c->ic_freq;
655         iev.iev_ieee = c->ic_ieee;
656         rt_ieee80211msg(ifp, RTM_IEEE80211_RADAR, &iev, sizeof(iev));
657 }
658
659 void
660 ieee80211_notify_cac(struct ieee80211com *ic,
661         const struct ieee80211_channel *c, enum ieee80211_notify_cac_event type)
662 {
663         struct ifnet *ifp = ic->ic_ifp;
664         struct ieee80211_cac_event iev;
665
666         memset(&iev, 0, sizeof(iev));
667         iev.iev_flags = c->ic_flags;
668         iev.iev_freq = c->ic_freq;
669         iev.iev_ieee = c->ic_ieee;
670         iev.iev_type = type;
671         rt_ieee80211msg(ifp, RTM_IEEE80211_CAC, &iev, sizeof(iev));
672 }
673
674 void
675 ieee80211_notify_node_deauth(struct ieee80211_node *ni)
676 {
677         struct ieee80211vap *vap = ni->ni_vap;
678         struct ifnet *ifp = vap->iv_ifp;
679
680         IEEE80211_NOTE(vap, IEEE80211_MSG_NODE, ni, "%s", "node deauth");
681
682         notify_macaddr(ifp, RTM_IEEE80211_DEAUTH, ni->ni_macaddr);
683 }
684
685 void
686 ieee80211_notify_node_auth(struct ieee80211_node *ni)
687 {
688         struct ieee80211vap *vap = ni->ni_vap;
689         struct ifnet *ifp = vap->iv_ifp;
690
691         IEEE80211_NOTE(vap, IEEE80211_MSG_NODE, ni, "%s", "node auth");
692
693         notify_macaddr(ifp, RTM_IEEE80211_AUTH, ni->ni_macaddr);
694 }
695
696 void
697 ieee80211_notify_country(struct ieee80211vap *vap,
698         const uint8_t bssid[IEEE80211_ADDR_LEN], const uint8_t cc[2])
699 {
700         struct ifnet *ifp = vap->iv_ifp;
701         struct ieee80211_country_event iev;
702
703         memset(&iev, 0, sizeof(iev));
704         IEEE80211_ADDR_COPY(iev.iev_addr, bssid);
705         iev.iev_cc[0] = cc[0];
706         iev.iev_cc[1] = cc[1];
707         rt_ieee80211msg(ifp, RTM_IEEE80211_COUNTRY, &iev, sizeof(iev));
708 }
709
710 void
711 ieee80211_notify_radio(struct ieee80211com *ic, int state)
712 {
713         struct ifnet *ifp = ic->ic_ifp;
714         struct ieee80211_radio_event iev;
715
716         memset(&iev, 0, sizeof(iev));
717         iev.iev_state = state;
718         rt_ieee80211msg(ifp, RTM_IEEE80211_RADIO, &iev, sizeof(iev));
719 }
720
721 int
722 ieee80211_handoff(struct ifnet *dst_ifp, struct mbuf *m)
723 {
724         struct mbuf *m0;
725
726         /* We may be sending a fragment so traverse the mbuf */
727         for (; m; m = m0) {
728                 struct altq_pktattr pktattr;
729
730                 m0 = m->m_nextpkt;
731                 m->m_nextpkt = NULL;
732
733                 if (ifq_is_enabled(&dst_ifp->if_snd))
734                         altq_etherclassify(&dst_ifp->if_snd, m, &pktattr);
735
736                 ifq_dispatch(dst_ifp, m, &pktattr);
737         }
738
739         return (0);
740 }
741
742 void
743 ieee80211_load_module(const char *modname)
744 {
745
746 #ifdef notyet
747         (void)kern_kldload(curthread, modname, NULL);
748 #else
749         kprintf("%s: load the %s module by hand for now.\n", __func__, modname);
750 #endif
751 }
752
753 static eventhandler_tag wlan_bpfevent;
754 static eventhandler_tag wlan_ifllevent;
755
756 static void
757 bpf_track(void *arg, struct ifnet *ifp, int dlt, int attach)
758 {
759         /* NB: identify vap's by if_start */
760         if (dlt == DLT_IEEE802_11_RADIO && ifp->if_start == ieee80211_start) {
761 #ifdef notyet
762                 struct ieee80211vap *vap = ifp->if_softc;
763 #endif
764                 /*
765                  * Track bpf radiotap listener state.  We mark the vap
766                  * to indicate if any listener is present and the com
767                  * to indicate if any listener exists on any associated
768                  * vap.  This flag is used by drivers to prepare radiotap
769                  * state only when needed.
770                  */
771 #ifdef notyet
772                 if (attach) {
773                         ieee80211_syncflag_ext(vap, IEEE80211_FEXT_BPF);
774                         if (vap->iv_opmode == IEEE80211_M_MONITOR)
775                                 atomic_add_int(&vap->iv_ic->ic_montaps, 1);
776                 } else if (!bpf_peers_present(vap->iv_rawbpf)) {
777                         ieee80211_syncflag_ext(vap, -IEEE80211_FEXT_BPF);
778                         if (vap->iv_opmode == IEEE80211_M_MONITOR)
779                                 atomic_subtract_int(&vap->iv_ic->ic_montaps, 1);
780                 }
781 #endif
782         }
783 }
784
785 static void
786 wlan_iflladdr(void *arg __unused, struct ifnet *ifp)
787 {
788         struct ieee80211com *ic = ifp->if_l2com;
789         struct ieee80211vap *vap, *next;
790
791         if (ifp->if_type != IFT_IEEE80211 || ic == NULL)
792                 return;
793
794         IEEE80211_LOCK(ic);
795         TAILQ_FOREACH_MUTABLE(vap, &ic->ic_vaps, iv_next, next) {
796                 /*
797                  * If the MAC address has changed on the parent and it was
798                  * copied to the vap on creation then re-sync.
799                  */
800                 if (vap->iv_ic == ic &&
801                     (vap->iv_flags_ext & IEEE80211_FEXT_UNIQMAC) == 0) {
802                         IEEE80211_ADDR_COPY(vap->iv_myaddr, IF_LLADDR(ifp));
803                         IEEE80211_UNLOCK(ic);
804                         if_setlladdr(vap->iv_ifp, IF_LLADDR(ifp),
805                             IEEE80211_ADDR_LEN);
806                         IEEE80211_LOCK(ic);
807                 }
808         }
809         IEEE80211_UNLOCK(ic);
810 }
811
812 /*
813  * Module glue.
814  *
815  * NB: the module name is "wlan" for compatibility with NetBSD.
816  */
817 static int
818 wlan_modevent(module_t mod, int type, void *unused)
819 {
820         switch (type) {
821         case MOD_LOAD:
822                 if (bootverbose)
823                         kprintf("wlan: <802.11 Link Layer>\n");
824                 wlan_bpfevent = EVENTHANDLER_REGISTER(bpf_track,
825                     bpf_track, 0, EVENTHANDLER_PRI_ANY);
826                 if (wlan_bpfevent == NULL)
827                         return ENOMEM;
828                 wlan_ifllevent = EVENTHANDLER_REGISTER(iflladdr_event,
829                     wlan_iflladdr, NULL, EVENTHANDLER_PRI_ANY);
830                 if (wlan_ifllevent == NULL) {
831                         EVENTHANDLER_DEREGISTER(bpf_track, wlan_bpfevent);
832                         return ENOMEM;
833                 }
834                 if_clone_attach(&wlan_cloner);
835                 if_register_com_alloc(IFT_IEEE80211, wlan_alloc, wlan_free);
836                 return 0;
837         case MOD_UNLOAD:
838                 if_deregister_com_alloc(IFT_IEEE80211);
839                 if_clone_detach(&wlan_cloner);
840                 EVENTHANDLER_DEREGISTER(bpf_track, wlan_bpfevent);
841                 EVENTHANDLER_DEREGISTER(iflladdr_event, wlan_ifllevent);
842                 return 0;
843         }
844         return EINVAL;
845 }
846
847 static moduledata_t wlan_mod = {
848         "wlan",
849         wlan_modevent,
850         0
851 };
852 DECLARE_MODULE(wlan, wlan_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
853 MODULE_VERSION(wlan, 1);
854 MODULE_DEPEND(wlan, ether, 1, 1, 1);