2 * Copyright (c) 2003-2009 Sam Leffler, Errno Consulting
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
25 * $FreeBSD: head/sys/net80211/ieee80211_freebsd.c 202612 2010-01-19 05:00:57Z thompsa $
29 * IEEE 802.11 support (DragonFlyBSD-specific code)
33 #include <sys/param.h>
34 #include <sys/kernel.h>
35 #include <sys/systm.h>
36 #include <sys/linker.h>
38 #include <sys/module.h>
40 #include <sys/sysctl.h>
42 #include <sys/socket.h>
46 #include <net/if_dl.h>
47 #include <net/if_clone.h>
48 #include <net/if_media.h>
49 #include <net/if_types.h>
50 #include <net/ethernet.h>
51 #include <net/route.h>
52 #include <net/ifq_var.h>
54 #include <netproto/802_11/ieee80211_var.h>
55 #include <netproto/802_11/ieee80211_input.h>
57 SYSCTL_NODE(_net
, OID_AUTO
, wlan
, CTLFLAG_RD
, 0, "IEEE 80211 parameters");
59 #ifdef IEEE80211_DEBUG
60 int ieee80211_debug
= 0;
61 SYSCTL_INT(_net_wlan
, OID_AUTO
, debug
, CTLFLAG_RW
, &ieee80211_debug
,
62 0, "debugging printfs");
65 int ieee80211_force_swcrypto
= 0;
66 SYSCTL_INT(_net_wlan
, OID_AUTO
, force_swcrypto
, CTLFLAG_RW
,
67 &ieee80211_force_swcrypto
, 0, "force software crypto");
69 MALLOC_DEFINE(M_80211_COM
, "80211com", "802.11 com state");
72 static int wlan_clone_destroy(struct ifnet
*);
73 static int wlan_clone_create(struct if_clone
*, int, caddr_t
);
75 static struct if_clone wlan_cloner
=
76 IF_CLONE_INITIALIZER("wlan", wlan_clone_create
, wlan_clone_destroy
,
79 struct lwkt_serialize wlan_global_serializer
= LWKT_SERIALIZE_INITIALIZER
;
82 * Allocate/free com structure in conjunction with ifnet;
83 * these routines are registered with if_register_com_alloc
84 * below and are called automatically by the ifnet code
85 * when the ifnet of the parent device is created.
88 wlan_alloc(u_char type
, struct ifnet
*ifp
)
90 struct ieee80211com
*ic
;
92 ic
= kmalloc(sizeof(struct ieee80211com
), M_80211_COM
, M_WAITOK
|M_ZERO
);
99 wlan_free(void *ic
, u_char type
)
101 kfree(ic
, M_80211_COM
);
105 wlan_clone_create(struct if_clone
*ifc
, int unit
, caddr_t params
)
107 struct ieee80211_clone_params cp
;
108 struct ieee80211vap
*vap
;
109 struct ieee80211com
*ic
;
113 error
= copyin(params
, &cp
, sizeof(cp
));
116 ifp
= ifunit(cp
.icp_parent
);
119 /* XXX move printfs to DIAGNOSTIC before release */
120 if (ifp
->if_type
!= IFT_IEEE80211
) {
121 if_printf(ifp
, "%s: reject, not an 802.11 device\n", __func__
);
124 if (cp
.icp_opmode
>= IEEE80211_OPMODE_MAX
) {
125 if_printf(ifp
, "%s: invalid opmode %d\n",
126 __func__
, cp
.icp_opmode
);
130 if ((ic
->ic_caps
& ieee80211_opcap
[cp
.icp_opmode
]) == 0) {
131 if_printf(ifp
, "%s mode not supported\n",
132 ieee80211_opmode_name
[cp
.icp_opmode
]);
135 if ((cp
.icp_flags
& IEEE80211_CLONE_TDMA
) &&
136 #ifdef IEEE80211_SUPPORT_TDMA
137 (ic
->ic_caps
& IEEE80211_C_TDMA
) == 0
142 if_printf(ifp
, "TDMA not supported\n");
145 vap
= ic
->ic_vap_create(ic
, ifc
->ifc_name
, unit
,
146 cp
.icp_opmode
, cp
.icp_flags
, cp
.icp_bssid
,
147 cp
.icp_flags
& IEEE80211_CLONE_MACADDR
?
148 cp
.icp_macaddr
: (const uint8_t *)IF_LLADDR(ifp
));
149 return (vap
== NULL
? EIO
: 0);
153 wlan_clone_destroy(struct ifnet
*ifp
)
155 struct ieee80211vap
*vap
= ifp
->if_softc
;
156 struct ieee80211com
*ic
= vap
->iv_ic
;
158 wlan_serialize_enter(); /* WARNING must be global serializer */
159 ic
->ic_vap_delete(vap
);
160 wlan_serialize_exit();
165 const char *wlan_last_enter_func
;
166 const char *wlan_last_exit_func
;
168 * These serializer functions are used by wlan and all drivers.
171 _wlan_serialize_enter(const char *funcname
)
173 lwkt_serialize_enter(&wlan_global_serializer
);
174 wlan_last_enter_func
= funcname
;
178 _wlan_serialize_exit(const char *funcname
)
180 lwkt_serialize_exit(&wlan_global_serializer
);
181 wlan_last_exit_func
= funcname
;
185 wlan_serialize_sleep(void *ident
, int flags
, const char *wmesg
, int timo
)
187 return(zsleep(ident
, &wlan_global_serializer
, flags
, wmesg
, timo
));
191 * condition-var functions which interlock the ic lock (which is now
192 * just wlan_global_serializer)
195 wlan_cv_init(struct cv
*cv
, const char *desc
)
202 wlan_cv_timedwait(struct cv
*cv
, int ticks
)
207 error
= wlan_serialize_sleep(cv
, 0, cv
->cv_desc
, ticks
);
212 wlan_cv_wait(struct cv
*cv
)
215 wlan_serialize_sleep(cv
, 0, cv
->cv_desc
, 0);
219 wlan_cv_signal(struct cv
*cv
, int broadcast
)
221 if (cv
->cv_waiters
) {
236 ieee80211_vap_destroy(struct ieee80211vap
*vap
)
238 wlan_assert_serialized();
239 wlan_serialize_exit();
240 if_clone_destroy(vap
->iv_ifp
->if_xname
);
241 wlan_serialize_enter();
245 * NOTE: This handler is used generally to convert milliseconds
246 * to ticks for various simple sysctl variables and does not
247 * need to be serialized.
250 ieee80211_sysctl_msecs_ticks(SYSCTL_HANDLER_ARGS
)
252 int msecs
= ticks_to_msecs(*(int *)arg1
);
255 error
= sysctl_handle_int(oidp
, &msecs
, 0, req
);
256 if (error
== 0 && req
->newptr
) {
257 t
= msecs_to_ticks(msecs
);
258 *(int *)arg1
= (t
< 1) ? 1 : t
;
265 ieee80211_sysctl_inact(SYSCTL_HANDLER_ARGS
)
267 int inact
= (*(int *)arg1
) * IEEE80211_INACT_WAIT
;
270 error
= sysctl_handle_int(oidp
, &inact
, 0, req
);
271 wlan_serialize_enter();
272 if (error
== 0 && req
->newptr
)
273 *(int *)arg1
= inact
/ IEEE80211_INACT_WAIT
;
274 wlan_serialize_exit();
280 ieee80211_sysctl_parent(SYSCTL_HANDLER_ARGS
)
282 struct ieee80211com
*ic
= arg1
;
283 const char *name
= ic
->ic_ifp
->if_xname
;
285 return SYSCTL_OUT(req
, name
, strlen(name
));
289 ieee80211_sysctl_radar(SYSCTL_HANDLER_ARGS
)
291 struct ieee80211com
*ic
= arg1
;
294 error
= sysctl_handle_int(oidp
, &t
, 0, req
);
295 wlan_serialize_enter();
296 if (error
== 0 && req
->newptr
)
297 ieee80211_dfs_notify_radar(ic
, ic
->ic_curchan
);
298 wlan_serialize_exit();
304 ieee80211_sysctl_attach(struct ieee80211com
*ic
)
309 ieee80211_sysctl_detach(struct ieee80211com
*ic
)
314 ieee80211_sysctl_vattach(struct ieee80211vap
*vap
)
316 struct ifnet
*ifp
= vap
->iv_ifp
;
317 struct sysctl_ctx_list
*ctx
;
318 struct sysctl_oid
*oid
;
319 char num
[14]; /* sufficient for 32 bits */
321 ctx
= (struct sysctl_ctx_list
*) kmalloc(sizeof(struct sysctl_ctx_list
),
322 M_DEVBUF
, M_INTWAIT
| M_ZERO
);
324 if_printf(ifp
, "%s: cannot allocate sysctl context!\n",
328 sysctl_ctx_init(ctx
);
329 ksnprintf(num
, sizeof(num
), "%u", ifp
->if_dunit
);
330 oid
= SYSCTL_ADD_NODE(ctx
, &SYSCTL_NODE_CHILDREN(_net
, wlan
),
331 OID_AUTO
, num
, CTLFLAG_RD
, NULL
, "");
332 SYSCTL_ADD_PROC(ctx
, SYSCTL_CHILDREN(oid
), OID_AUTO
,
333 "%parent", CTLFLAG_RD
, vap
->iv_ic
, 0,
334 ieee80211_sysctl_parent
, "A", "parent device");
335 SYSCTL_ADD_INT(ctx
, SYSCTL_CHILDREN(oid
), OID_AUTO
,
336 "driver_caps", CTLFLAG_RW
, &vap
->iv_caps
, 0,
337 "driver capabilities");
338 #ifdef IEEE80211_DEBUG
339 vap
->iv_debug
= ieee80211_debug
;
340 SYSCTL_ADD_INT(ctx
, SYSCTL_CHILDREN(oid
), OID_AUTO
,
341 "debug", CTLFLAG_RW
, &vap
->iv_debug
, 0,
342 "control debugging printfs");
344 SYSCTL_ADD_INT(ctx
, SYSCTL_CHILDREN(oid
), OID_AUTO
,
345 "bmiss_max", CTLFLAG_RW
, &vap
->iv_bmiss_max
, 0,
346 "consecutive beacon misses before scanning");
347 /* XXX inherit from tunables */
348 SYSCTL_ADD_PROC(ctx
, SYSCTL_CHILDREN(oid
), OID_AUTO
,
349 "inact_run", CTLTYPE_INT
| CTLFLAG_RW
, &vap
->iv_inact_run
, 0,
350 ieee80211_sysctl_inact
, "I",
351 "station inactivity timeout (sec)");
352 SYSCTL_ADD_PROC(ctx
, SYSCTL_CHILDREN(oid
), OID_AUTO
,
353 "inact_probe", CTLTYPE_INT
| CTLFLAG_RW
, &vap
->iv_inact_probe
, 0,
354 ieee80211_sysctl_inact
, "I",
355 "station inactivity probe timeout (sec)");
356 SYSCTL_ADD_PROC(ctx
, SYSCTL_CHILDREN(oid
), OID_AUTO
,
357 "inact_auth", CTLTYPE_INT
| CTLFLAG_RW
, &vap
->iv_inact_auth
, 0,
358 ieee80211_sysctl_inact
, "I",
359 "station authentication timeout (sec)");
360 SYSCTL_ADD_PROC(ctx
, SYSCTL_CHILDREN(oid
), OID_AUTO
,
361 "inact_init", CTLTYPE_INT
| CTLFLAG_RW
, &vap
->iv_inact_init
, 0,
362 ieee80211_sysctl_inact
, "I",
363 "station initial state timeout (sec)");
364 if (vap
->iv_htcaps
& IEEE80211_HTC_HT
) {
365 SYSCTL_ADD_INT(ctx
, SYSCTL_CHILDREN(oid
), OID_AUTO
,
366 "ampdu_mintraffic_bk", CTLFLAG_RW
,
367 &vap
->iv_ampdu_mintraffic
[WME_AC_BK
], 0,
368 "BK traffic tx aggr threshold (pps)");
369 SYSCTL_ADD_INT(ctx
, SYSCTL_CHILDREN(oid
), OID_AUTO
,
370 "ampdu_mintraffic_be", CTLFLAG_RW
,
371 &vap
->iv_ampdu_mintraffic
[WME_AC_BE
], 0,
372 "BE traffic tx aggr threshold (pps)");
373 SYSCTL_ADD_INT(ctx
, SYSCTL_CHILDREN(oid
), OID_AUTO
,
374 "ampdu_mintraffic_vo", CTLFLAG_RW
,
375 &vap
->iv_ampdu_mintraffic
[WME_AC_VO
], 0,
376 "VO traffic tx aggr threshold (pps)");
377 SYSCTL_ADD_INT(ctx
, SYSCTL_CHILDREN(oid
), OID_AUTO
,
378 "ampdu_mintraffic_vi", CTLFLAG_RW
,
379 &vap
->iv_ampdu_mintraffic
[WME_AC_VI
], 0,
380 "VI traffic tx aggr threshold (pps)");
382 if (vap
->iv_caps
& IEEE80211_C_DFS
) {
383 SYSCTL_ADD_PROC(ctx
, SYSCTL_CHILDREN(oid
), OID_AUTO
,
384 "radar", CTLTYPE_INT
| CTLFLAG_RW
, vap
->iv_ic
, 0,
385 ieee80211_sysctl_radar
, "I", "simulate radar event");
387 vap
->iv_sysctl
= ctx
;
392 ieee80211_sysctl_vdetach(struct ieee80211vap
*vap
)
395 if (vap
->iv_sysctl
!= NULL
) {
396 sysctl_ctx_free(vap
->iv_sysctl
);
397 kfree(vap
->iv_sysctl
, M_DEVBUF
);
398 vap
->iv_sysctl
= NULL
;
403 ieee80211_node_dectestref(struct ieee80211_node
*ni
)
405 /* XXX need equivalent of atomic_dec_and_test */
406 atomic_subtract_int(&ni
->ni_refcnt
, 1);
407 return atomic_cmpset_int(&ni
->ni_refcnt
, 0, 1);
411 ieee80211_drain_ifq(struct ifqueue
*ifq
)
413 struct ieee80211_node
*ni
;
416 wlan_assert_serialized();
422 ni
= (struct ieee80211_node
*)m
->m_pkthdr
.rcvif
;
423 KASSERT(ni
!= NULL
, ("frame w/o node"));
424 ieee80211_free_node(ni
);
425 m
->m_pkthdr
.rcvif
= NULL
;
432 ieee80211_flush_ifq(struct ifqueue
*ifq
, struct ieee80211vap
*vap
)
434 struct ieee80211_node
*ni
;
435 struct mbuf
*m
, **mprev
;
437 wlan_assert_serialized();
438 mprev
= &ifq
->ifq_head
;
439 while ((m
= *mprev
) != NULL
) {
440 ni
= (struct ieee80211_node
*)m
->m_pkthdr
.rcvif
;
441 if (ni
!= NULL
&& ni
->ni_vap
== vap
) {
442 *mprev
= m
->m_nextpkt
; /* remove from list */
446 ieee80211_free_node(ni
); /* reclaim ref */
448 mprev
= &m
->m_nextpkt
;
450 /* recalculate tail ptr */
452 for (; m
!= NULL
&& m
->m_nextpkt
!= NULL
; m
= m
->m_nextpkt
)
458 * As above, for mbufs allocated with m_gethdr/MGETHDR
459 * or initialized by M_COPY_PKTHDR.
461 #define MC_ALIGN(m, len) \
463 (m)->m_data += (MCLBYTES - (len)) &~ (sizeof(long) - 1); \
464 } while (/* CONSTCOND */ 0)
467 * Allocate and setup a management frame of the specified
468 * size. We return the mbuf and a pointer to the start
469 * of the contiguous data area that's been reserved based
470 * on the packet length. The data area is forced to 32-bit
471 * alignment and the buffer length to a multiple of 4 bytes.
472 * This is done mainly so beacon frames (that require this)
473 * can use this interface too.
476 ieee80211_getmgtframe(uint8_t **frm
, int headroom
, int pktlen
)
482 * NB: we know the mbuf routines will align the data area
483 * so we don't need to do anything special.
485 len
= roundup2(headroom
+ pktlen
, 4);
486 KASSERT(len
<= MCLBYTES
, ("802.11 mgt frame too large: %u", len
));
487 if (len
< MINCLSIZE
) {
488 m
= m_gethdr(MB_DONTWAIT
, MT_DATA
);
490 * Align the data in case additional headers are added.
491 * This should only happen when a WEP header is added
492 * which only happens for shared key authentication mgt
493 * frames which all fit in MHLEN.
498 m
= m_getcl(MB_DONTWAIT
, MT_DATA
, M_PKTHDR
);
503 m
->m_data
+= headroom
;
510 * Re-align the payload in the mbuf. This is mainly used (right now)
511 * to handle IP header alignment requirements on certain architectures.
514 ieee80211_realign(struct ieee80211vap
*vap
, struct mbuf
*m
, size_t align
)
517 struct mbuf
*n
= NULL
;
519 pktlen
= m
->m_pkthdr
.len
;
520 space
= pktlen
+ align
;
521 if (space
< MINCLSIZE
)
522 n
= m_gethdr(MB_DONTWAIT
, MT_DATA
);
525 n
= m_getjcl(MB_DONTWAIT
, MT_DATA
, M_PKTHDR
,
526 space
<= MCLBYTES
? MCLBYTES
:
527 #if MJUMPAGESIZE != MCLBYTES
528 space
<= MJUMPAGESIZE
? MJUMPAGESIZE
:
530 space
<= MJUM9BYTES
? MJUM9BYTES
: MJUM16BYTES
);
533 if (__predict_true(n
!= NULL
)) {
535 n
->m_data
= (caddr_t
)(ALIGN(n
->m_data
+ align
) - align
);
536 m_copydata(m
, 0, pktlen
, mtod(n
, caddr_t
));
539 IEEE80211_DISCARD(vap
, IEEE80211_MSG_ANY
,
540 mtod(m
, const struct ieee80211_frame
*), NULL
,
541 "%s", "no mbuf to realign");
542 vap
->iv_stats
.is_rx_badalign
++;
549 ieee80211_add_callback(struct mbuf
*m
,
550 void (*func
)(struct ieee80211_node
*, void *, int), void *arg
)
553 struct ieee80211_cb
*cb
;
555 mtag
= m_tag_alloc(MTAG_ABI_NET80211
, NET80211_TAG_CALLBACK
,
556 sizeof(struct ieee80211_cb
), M_INTWAIT
);
560 cb
= (struct ieee80211_cb
*)(mtag
+1);
563 m_tag_prepend(m
, mtag
);
564 m
->m_flags
|= M_TXCB
;
569 ieee80211_process_callback(struct ieee80211_node
*ni
,
570 struct mbuf
*m
, int status
)
574 mtag
= m_tag_locate(m
, MTAG_ABI_NET80211
, NET80211_TAG_CALLBACK
, NULL
);
576 struct ieee80211_cb
*cb
= (struct ieee80211_cb
*)(mtag
+1);
577 cb
->func(ni
, cb
->arg
, status
);
581 #include <sys/libkern.h>
584 get_random_bytes(void *p
, size_t n
)
589 uint32_t v
= karc4random();
590 size_t nb
= n
> sizeof(uint32_t) ? sizeof(uint32_t) : n
;
591 bcopy(&v
, dp
, n
> sizeof(uint32_t) ? sizeof(uint32_t) : n
);
592 dp
+= sizeof(uint32_t), n
-= nb
;
597 * Helper function for events that pass just a single mac address.
600 notify_macaddr(struct ifnet
*ifp
, int op
, const uint8_t mac
[IEEE80211_ADDR_LEN
])
602 struct ieee80211_join_event iev
;
604 memset(&iev
, 0, sizeof(iev
));
605 IEEE80211_ADDR_COPY(iev
.iev_addr
, mac
);
606 rt_ieee80211msg(ifp
, op
, &iev
, sizeof(iev
));
610 ieee80211_notify_node_join(struct ieee80211_node
*ni
, int newassoc
)
612 struct ieee80211vap
*vap
= ni
->ni_vap
;
613 struct ifnet
*ifp
= vap
->iv_ifp
;
615 IEEE80211_NOTE(vap
, IEEE80211_MSG_NODE
, ni
, "%snode join",
616 (ni
== vap
->iv_bss
) ? "bss " : "");
618 if (ni
== vap
->iv_bss
) {
619 notify_macaddr(ifp
, newassoc
?
620 RTM_IEEE80211_ASSOC
: RTM_IEEE80211_REASSOC
, ni
->ni_bssid
);
621 if_link_state_change(ifp
);
623 notify_macaddr(ifp
, newassoc
?
624 RTM_IEEE80211_JOIN
: RTM_IEEE80211_REJOIN
, ni
->ni_macaddr
);
629 ieee80211_notify_node_leave(struct ieee80211_node
*ni
)
631 struct ieee80211vap
*vap
= ni
->ni_vap
;
632 struct ifnet
*ifp
= vap
->iv_ifp
;
634 IEEE80211_NOTE(vap
, IEEE80211_MSG_NODE
, ni
, "%snode leave",
635 (ni
== vap
->iv_bss
) ? "bss " : "");
637 if (ni
== vap
->iv_bss
) {
638 rt_ieee80211msg(ifp
, RTM_IEEE80211_DISASSOC
, NULL
, 0);
639 if_link_state_change(ifp
);
641 /* fire off wireless event station leaving */
642 notify_macaddr(ifp
, RTM_IEEE80211_LEAVE
, ni
->ni_macaddr
);
647 ieee80211_notify_scan_done(struct ieee80211vap
*vap
)
649 struct ifnet
*ifp
= vap
->iv_ifp
;
651 IEEE80211_DPRINTF(vap
, IEEE80211_MSG_SCAN
, "%s\n", "notify scan done");
653 /* dispatch wireless event indicating scan completed */
654 rt_ieee80211msg(ifp
, RTM_IEEE80211_SCAN
, NULL
, 0);
658 ieee80211_notify_replay_failure(struct ieee80211vap
*vap
,
659 const struct ieee80211_frame
*wh
, const struct ieee80211_key
*k
,
660 u_int64_t rsc
, int tid
)
662 struct ifnet
*ifp
= vap
->iv_ifp
;
664 IEEE80211_NOTE_MAC(vap
, IEEE80211_MSG_CRYPTO
, wh
->i_addr2
,
665 "%s replay detected <rsc %ju, csc %ju, keyix %u rxkeyix %u>",
666 k
->wk_cipher
->ic_name
, (intmax_t) rsc
,
667 (intmax_t) k
->wk_keyrsc
[tid
],
668 k
->wk_keyix
, k
->wk_rxkeyix
);
670 if (ifp
!= NULL
) { /* NB: for cipher test modules */
671 struct ieee80211_replay_event iev
;
673 IEEE80211_ADDR_COPY(iev
.iev_dst
, wh
->i_addr1
);
674 IEEE80211_ADDR_COPY(iev
.iev_src
, wh
->i_addr2
);
675 iev
.iev_cipher
= k
->wk_cipher
->ic_cipher
;
676 if (k
->wk_rxkeyix
!= IEEE80211_KEYIX_NONE
)
677 iev
.iev_keyix
= k
->wk_rxkeyix
;
679 iev
.iev_keyix
= k
->wk_keyix
;
680 iev
.iev_keyrsc
= k
->wk_keyrsc
[tid
];
682 rt_ieee80211msg(ifp
, RTM_IEEE80211_REPLAY
, &iev
, sizeof(iev
));
687 ieee80211_notify_michael_failure(struct ieee80211vap
*vap
,
688 const struct ieee80211_frame
*wh
, u_int keyix
)
690 struct ifnet
*ifp
= vap
->iv_ifp
;
692 IEEE80211_NOTE_MAC(vap
, IEEE80211_MSG_CRYPTO
, wh
->i_addr2
,
693 "michael MIC verification failed <keyix %u>", keyix
);
694 vap
->iv_stats
.is_rx_tkipmic
++;
696 if (ifp
!= NULL
) { /* NB: for cipher test modules */
697 struct ieee80211_michael_event iev
;
699 IEEE80211_ADDR_COPY(iev
.iev_dst
, wh
->i_addr1
);
700 IEEE80211_ADDR_COPY(iev
.iev_src
, wh
->i_addr2
);
701 iev
.iev_cipher
= IEEE80211_CIPHER_TKIP
;
702 iev
.iev_keyix
= keyix
;
703 rt_ieee80211msg(ifp
, RTM_IEEE80211_MICHAEL
, &iev
, sizeof(iev
));
708 ieee80211_notify_wds_discover(struct ieee80211_node
*ni
)
710 struct ieee80211vap
*vap
= ni
->ni_vap
;
711 struct ifnet
*ifp
= vap
->iv_ifp
;
713 notify_macaddr(ifp
, RTM_IEEE80211_WDS
, ni
->ni_macaddr
);
717 ieee80211_notify_csa(struct ieee80211com
*ic
,
718 const struct ieee80211_channel
*c
, int mode
, int count
)
720 struct ifnet
*ifp
= ic
->ic_ifp
;
721 struct ieee80211_csa_event iev
;
723 memset(&iev
, 0, sizeof(iev
));
724 iev
.iev_flags
= c
->ic_flags
;
725 iev
.iev_freq
= c
->ic_freq
;
726 iev
.iev_ieee
= c
->ic_ieee
;
728 iev
.iev_count
= count
;
729 rt_ieee80211msg(ifp
, RTM_IEEE80211_CSA
, &iev
, sizeof(iev
));
733 ieee80211_notify_radar(struct ieee80211com
*ic
,
734 const struct ieee80211_channel
*c
)
736 struct ifnet
*ifp
= ic
->ic_ifp
;
737 struct ieee80211_radar_event iev
;
739 memset(&iev
, 0, sizeof(iev
));
740 iev
.iev_flags
= c
->ic_flags
;
741 iev
.iev_freq
= c
->ic_freq
;
742 iev
.iev_ieee
= c
->ic_ieee
;
743 rt_ieee80211msg(ifp
, RTM_IEEE80211_RADAR
, &iev
, sizeof(iev
));
747 ieee80211_notify_cac(struct ieee80211com
*ic
,
748 const struct ieee80211_channel
*c
, enum ieee80211_notify_cac_event type
)
750 struct ifnet
*ifp
= ic
->ic_ifp
;
751 struct ieee80211_cac_event iev
;
753 memset(&iev
, 0, sizeof(iev
));
754 iev
.iev_flags
= c
->ic_flags
;
755 iev
.iev_freq
= c
->ic_freq
;
756 iev
.iev_ieee
= c
->ic_ieee
;
758 rt_ieee80211msg(ifp
, RTM_IEEE80211_CAC
, &iev
, sizeof(iev
));
762 ieee80211_notify_node_deauth(struct ieee80211_node
*ni
)
764 struct ieee80211vap
*vap
= ni
->ni_vap
;
765 struct ifnet
*ifp
= vap
->iv_ifp
;
767 IEEE80211_NOTE(vap
, IEEE80211_MSG_NODE
, ni
, "%s", "node deauth");
769 notify_macaddr(ifp
, RTM_IEEE80211_DEAUTH
, ni
->ni_macaddr
);
773 ieee80211_notify_node_auth(struct ieee80211_node
*ni
)
775 struct ieee80211vap
*vap
= ni
->ni_vap
;
776 struct ifnet
*ifp
= vap
->iv_ifp
;
778 IEEE80211_NOTE(vap
, IEEE80211_MSG_NODE
, ni
, "%s", "node auth");
780 notify_macaddr(ifp
, RTM_IEEE80211_AUTH
, ni
->ni_macaddr
);
784 ieee80211_notify_country(struct ieee80211vap
*vap
,
785 const uint8_t bssid
[IEEE80211_ADDR_LEN
], const uint8_t cc
[2])
787 struct ifnet
*ifp
= vap
->iv_ifp
;
788 struct ieee80211_country_event iev
;
790 memset(&iev
, 0, sizeof(iev
));
791 IEEE80211_ADDR_COPY(iev
.iev_addr
, bssid
);
792 iev
.iev_cc
[0] = cc
[0];
793 iev
.iev_cc
[1] = cc
[1];
794 rt_ieee80211msg(ifp
, RTM_IEEE80211_COUNTRY
, &iev
, sizeof(iev
));
798 ieee80211_notify_radio(struct ieee80211com
*ic
, int state
)
800 struct ifnet
*ifp
= ic
->ic_ifp
;
801 struct ieee80211_radio_event iev
;
803 memset(&iev
, 0, sizeof(iev
));
804 iev
.iev_state
= state
;
805 rt_ieee80211msg(ifp
, RTM_IEEE80211_RADIO
, &iev
, sizeof(iev
));
809 ieee80211_handoff(struct ifnet
*dst_ifp
, struct mbuf
*m
)
813 /* We may be sending a fragment so traverse the mbuf */
814 wlan_assert_serialized();
815 wlan_serialize_exit();
817 struct altq_pktattr pktattr
;
822 if (ifq_is_enabled(&dst_ifp
->if_snd
))
823 altq_etherclassify(&dst_ifp
->if_snd
, m
, &pktattr
);
825 ifq_dispatch(dst_ifp
, m
, &pktattr
);
827 wlan_serialize_enter();
832 /* IEEE Std 802.11a-1999, page 9, table 79 */
833 #define IEEE80211_OFDM_SYM_TIME 4
834 #define IEEE80211_OFDM_PREAMBLE_TIME 16
835 #define IEEE80211_OFDM_SIGNAL_TIME 4
836 /* IEEE Std 802.11g-2003, page 44 */
837 #define IEEE80211_OFDM_SIGNAL_EXT_TIME 6
839 /* IEEE Std 802.11a-1999, page 7, figure 107 */
840 #define IEEE80211_OFDM_PLCP_SERVICE_NBITS 16
841 #define IEEE80211_OFDM_TAIL_NBITS 6
843 #define IEEE80211_OFDM_NBITS(frmlen) \
844 (IEEE80211_OFDM_PLCP_SERVICE_NBITS + \
845 ((frmlen) * NBBY) + \
846 IEEE80211_OFDM_TAIL_NBITS)
848 #define IEEE80211_OFDM_NBITS_PER_SYM(kbps) \
849 (((kbps) * IEEE80211_OFDM_SYM_TIME) / 1000)
851 #define IEEE80211_OFDM_NSYMS(kbps, frmlen) \
852 howmany(IEEE80211_OFDM_NBITS((frmlen)), \
853 IEEE80211_OFDM_NBITS_PER_SYM((kbps)))
855 #define IEEE80211_OFDM_TXTIME(kbps, frmlen) \
856 (IEEE80211_OFDM_PREAMBLE_TIME + \
857 IEEE80211_OFDM_SIGNAL_TIME + \
858 (IEEE80211_OFDM_NSYMS((kbps), (frmlen)) * IEEE80211_OFDM_SYM_TIME))
860 /* IEEE Std 802.11b-1999, page 28, subclause 18.3.4 */
861 #define IEEE80211_CCK_PREAMBLE_LEN 144
862 #define IEEE80211_CCK_PLCP_HDR_TIME 48
863 #define IEEE80211_CCK_SHPREAMBLE_LEN 72
864 #define IEEE80211_CCK_SHPLCP_HDR_TIME 24
866 #define IEEE80211_CCK_NBITS(frmlen) ((frmlen) * NBBY)
867 #define IEEE80211_CCK_TXTIME(kbps, frmlen) \
868 (((IEEE80211_CCK_NBITS((frmlen)) * 1000) + (kbps) - 1) / (kbps))
871 ieee80211_txtime(struct ieee80211_node
*ni
, u_int len
, uint8_t rs_rate
,
874 struct ieee80211vap
*vap
= ni
->ni_vap
;
878 rs_rate
&= IEEE80211_RATE_VAL
;
879 rate
= rs_rate
* 500; /* ieee80211 rate -> kbps */
881 if (vap
->iv_ic
->ic_phytype
== IEEE80211_T_OFDM
) {
883 * IEEE Std 802.11a-1999, page 37, equation (29)
884 * IEEE Std 802.11g-2003, page 44, equation (42)
886 txtime
= IEEE80211_OFDM_TXTIME(rate
, len
);
887 if (vap
->iv_ic
->ic_curmode
== IEEE80211_MODE_11G
)
888 txtime
+= IEEE80211_OFDM_SIGNAL_EXT_TIME
;
891 * IEEE Std 802.11b-1999, page 28, subclause 18.3.4
892 * IEEE Std 802.11g-2003, page 45, equation (43)
894 if (vap
->iv_ic
->ic_phytype
== IEEE80211_T_OFDM_QUARTER
+1)
896 txtime
= IEEE80211_CCK_TXTIME(rate
, len
);
899 * Short preamble is not applicable for DS 1Mbits/s
901 if (rs_rate
!= 2 && (flags
& IEEE80211_F_SHPREAMBLE
)) {
902 txtime
+= IEEE80211_CCK_SHPREAMBLE_LEN
+
903 IEEE80211_CCK_SHPLCP_HDR_TIME
;
905 txtime
+= IEEE80211_CCK_PREAMBLE_LEN
+
906 IEEE80211_CCK_PLCP_HDR_TIME
;
913 ieee80211_load_module(const char *modname
)
917 (void)kern_kldload(curthread
, modname
, NULL
);
919 kprintf("%s: load the %s module by hand for now.\n", __func__
, modname
);
923 static eventhandler_tag wlan_bpfevent
;
924 static eventhandler_tag wlan_ifllevent
;
927 bpf_track_event(void *arg
, struct ifnet
*ifp
, int dlt
, int attach
)
929 /* NB: identify vap's by if_start */
931 wlan_serialize_enter();
932 if (dlt
== DLT_IEEE802_11_RADIO
&& ifp
->if_start
== ieee80211_start
) {
933 struct ieee80211vap
*vap
= ifp
->if_softc
;
935 * Track bpf radiotap listener state. We mark the vap
936 * to indicate if any listener is present and the com
937 * to indicate if any listener exists on any associated
938 * vap. This flag is used by drivers to prepare radiotap
939 * state only when needed.
942 ieee80211_syncflag_ext(vap
, IEEE80211_FEXT_BPF
);
943 if (vap
->iv_opmode
== IEEE80211_M_MONITOR
)
944 atomic_add_int(&vap
->iv_ic
->ic_montaps
, 1);
945 } else if (!vap
->iv_rawbpf
) {
946 ieee80211_syncflag_ext(vap
, -IEEE80211_FEXT_BPF
);
947 if (vap
->iv_opmode
== IEEE80211_M_MONITOR
)
948 atomic_subtract_int(&vap
->iv_ic
->ic_montaps
, 1);
951 wlan_serialize_exit();
955 wlan_iflladdr_event(void *arg __unused
, struct ifnet
*ifp
)
957 struct ieee80211com
*ic
= ifp
->if_l2com
;
958 struct ieee80211vap
*vap
, *next
;
960 wlan_serialize_enter();
961 if (ifp
->if_type
!= IFT_IEEE80211
|| ic
== NULL
) {
962 wlan_serialize_exit();
966 TAILQ_FOREACH_MUTABLE(vap
, &ic
->ic_vaps
, iv_next
, next
) {
968 * If the MAC address has changed on the parent and it was
969 * copied to the vap on creation then re-sync.
971 if (vap
->iv_ic
== ic
&&
972 (vap
->iv_flags_ext
& IEEE80211_FEXT_UNIQMAC
) == 0) {
973 IEEE80211_ADDR_COPY(vap
->iv_myaddr
, IF_LLADDR(ifp
));
974 wlan_serialize_exit();
975 if_setlladdr(vap
->iv_ifp
, IF_LLADDR(ifp
),
977 wlan_serialize_enter();
980 wlan_serialize_exit();
986 * NB: the module name is "wlan" for compatibility with NetBSD.
989 wlan_modevent(module_t mod
, int type
, void *unused
)
993 wlan_serialize_enter();
998 kprintf("wlan: <802.11 Link Layer>\n");
999 wlan_bpfevent
= EVENTHANDLER_REGISTER(bpf_track
,
1001 EVENTHANDLER_PRI_ANY
);
1002 if (wlan_bpfevent
== NULL
) {
1006 wlan_ifllevent
= EVENTHANDLER_REGISTER(iflladdr_event
,
1007 wlan_iflladdr_event
, NULL
,
1008 EVENTHANDLER_PRI_ANY
);
1009 if (wlan_ifllevent
== NULL
) {
1010 EVENTHANDLER_DEREGISTER(bpf_track
, wlan_bpfevent
);
1014 if_clone_attach(&wlan_cloner
);
1015 if_register_com_alloc(IFT_IEEE80211
, wlan_alloc
, wlan_free
);
1019 if_deregister_com_alloc(IFT_IEEE80211
);
1020 if_clone_detach(&wlan_cloner
);
1021 EVENTHANDLER_DEREGISTER(bpf_track
, wlan_bpfevent
);
1022 EVENTHANDLER_DEREGISTER(iflladdr_event
, wlan_ifllevent
);
1029 wlan_serialize_exit();
1034 static moduledata_t wlan_mod
= {
1039 DECLARE_MODULE(wlan
, wlan_mod
, SI_SUB_DRIVERS
, SI_ORDER_FIRST
);
1040 MODULE_VERSION(wlan
, 1);
1041 MODULE_DEPEND(wlan
, ether
, 1, 1, 1);