2 * Copyright (c) 2007-2008 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.
26 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
32 * IEEE 802.11 WDS mode support.
37 #include <sys/param.h>
38 #include <sys/systm.h>
40 #include <sys/malloc.h>
41 #include <sys/kernel.h>
43 #include <sys/socket.h>
44 #include <sys/sockio.h>
45 #include <sys/endian.h>
46 #include <sys/errno.h>
48 #include <sys/sysctl.h>
51 #include <net/if_var.h>
52 #include <net/if_media.h>
53 #include <net/if_llc.h>
54 #include <net/ethernet.h>
58 #include <netproto/802_11/ieee80211_var.h>
59 #include <netproto/802_11/ieee80211_wds.h>
60 #include <netproto/802_11/ieee80211_input.h>
61 #ifdef IEEE80211_SUPPORT_SUPERG
62 #include <netproto/802_11/ieee80211_superg.h>
65 static void wds_vattach(struct ieee80211vap
*);
66 static int wds_newstate(struct ieee80211vap
*, enum ieee80211_state
, int);
67 static int wds_input(struct ieee80211_node
*ni
, struct mbuf
*m
,
68 const struct ieee80211_rx_stats
*rxs
, int, int);
69 static void wds_recv_mgmt(struct ieee80211_node
*, struct mbuf
*, int subtype
,
70 const struct ieee80211_rx_stats
*, int, int);
73 ieee80211_wds_attach(struct ieee80211com
*ic
)
75 ic
->ic_vattach
[IEEE80211_M_WDS
] = wds_vattach
;
79 ieee80211_wds_detach(struct ieee80211com
*ic
)
84 wds_vdetach(struct ieee80211vap
*vap
)
86 if (vap
->iv_bss
!= NULL
) {
88 if (vap
->iv_bss
->ni_wdsvap
== vap
)
89 vap
->iv_bss
->ni_wdsvap
= NULL
;
94 wds_vattach(struct ieee80211vap
*vap
)
96 vap
->iv_newstate
= wds_newstate
;
97 vap
->iv_input
= wds_input
;
98 vap
->iv_recv_mgmt
= wds_recv_mgmt
;
99 vap
->iv_opdetach
= wds_vdetach
;
103 wds_flush(struct ieee80211_node
*ni
)
105 struct ieee80211com
*ic
= ni
->ni_ic
;
106 struct mbuf
*m
, *next
;
109 m
= ieee80211_ageq_remove(&ic
->ic_stageq
,
110 (void *)(uintptr_t) ieee80211_mac_hash(ic
, ni
->ni_macaddr
));
114 IEEE80211_NOTE(ni
->ni_vap
, IEEE80211_MSG_WDS
, ni
,
115 "%s", "flush wds queue");
116 ic
->ic_node_getsignal(ni
, &rssi
, &nf
);
117 for (; m
!= NULL
; m
= next
) {
120 ieee80211_input(ni
, m
, rssi
, nf
);
125 ieee80211_create_wds(struct ieee80211vap
*vap
, struct ieee80211_channel
*chan
)
127 struct ieee80211com
*ic
= vap
->iv_ic
;
128 struct ieee80211_node_table
*nt
= &ic
->ic_sta
;
129 struct ieee80211_node
*ni
, *obss
;
131 IEEE80211_DPRINTF(vap
, IEEE80211_MSG_WDS
,
132 "%s: creating link to %s on channel %u\n", __func__
,
133 ether_sprintf(vap
->iv_des_bssid
), ieee80211_chan2ieee(ic
, chan
));
135 /* NB: vap create must specify the bssid for the link */
136 KASSERT(vap
->iv_flags
& IEEE80211_F_DESBSSID
, ("no bssid"));
137 /* NB: we should only be called on RUN transition */
138 KASSERT(vap
->iv_state
== IEEE80211_S_RUN
, ("!RUN state"));
140 if ((vap
->iv_flags_ext
& IEEE80211_FEXT_WDSLEGACY
) == 0) {
142 * Dynamic/non-legacy WDS. Reference the associated
143 * station specified by the desired bssid setup at vap
144 * create. Point ni_wdsvap at the WDS vap so 4-address
145 * frames received through the associated AP vap will
146 * be dispatched upward (e.g. to a bridge) as though
147 * they arrived on the WDS vap.
149 IEEE80211_NODE_LOCK(nt
);
151 ni
= ieee80211_find_node_locked(&ic
->ic_sta
, vap
->iv_des_bssid
);
154 * Node went away before we could hookup. This
155 * should be ok; no traffic will flow and a leave
156 * event will be dispatched that should cause
157 * the vap to be destroyed.
159 IEEE80211_DPRINTF(vap
, IEEE80211_MSG_WDS
,
160 "%s: station %s went away\n",
161 __func__
, ether_sprintf(vap
->iv_des_bssid
));
163 } else if (ni
->ni_wdsvap
!= NULL
) {
165 * Node already setup with a WDS vap; we cannot
166 * allow multiple references so disallow. If
167 * ni_wdsvap points at us that's ok; we should
170 /* XXX printf instead? */
171 IEEE80211_DPRINTF(vap
, IEEE80211_MSG_WDS
,
172 "%s: station %s in use with %s\n",
173 __func__
, ether_sprintf(vap
->iv_des_bssid
),
174 ni
->ni_wdsvap
->iv_ifp
->if_xname
);
178 * Committed to new node, setup state.
184 IEEE80211_NODE_UNLOCK(nt
);
186 /* NB: deferred to avoid recursive lock */
187 ieee80211_free_node(obss
);
191 * Legacy WDS vap setup.
194 * The far end does not associate so we just create
195 * create a new node and install it as the vap's
196 * bss node. We must simulate an association and
197 * authorize the port for traffic to flow.
198 * XXX check if node already in sta table?
200 ni
= ieee80211_node_create_wds(vap
, vap
->iv_des_bssid
, chan
);
203 vap
->iv_bss
= ieee80211_ref_node(ni
);
204 ni
->ni_flags
|= IEEE80211_NODE_AREF
;
206 ieee80211_free_node(obss
);
207 /* give driver a chance to setup state like ni_txrate */
208 if (ic
->ic_newassoc
!= NULL
)
209 ic
->ic_newassoc(ni
, 1);
210 /* tell the authenticator about new station */
211 if (vap
->iv_auth
->ia_node_join
!= NULL
)
212 vap
->iv_auth
->ia_node_join(ni
);
213 if (ni
->ni_authmode
!= IEEE80211_AUTH_8021X
)
214 ieee80211_node_authorize(ni
);
216 ieee80211_notify_node_join(ni
, 1 /*newassoc*/);
217 /* XXX inject l2uf frame */
222 * Flush any pending frames now that were setup.
226 return (ni
== NULL
? ENOENT
: 0);
230 * Propagate multicast frames of an ap vap to all DWDS links.
231 * The caller is assumed to have verified this frame is multicast.
234 ieee80211_dwds_mcast(struct ieee80211vap
*vap0
, struct mbuf
*m
)
236 struct ieee80211com
*ic
= vap0
->iv_ic
;
237 const struct ether_header
*eh
= mtod(m
, const struct ether_header
*);
238 struct ieee80211_node
*ni
;
239 struct ieee80211vap
*vap
;
244 KASSERT(ETHER_IS_MULTICAST(eh
->ether_dhost
),
245 ("%s not mcast", ether_sprintf(eh
->ether_dhost
)));
248 TAILQ_FOREACH(vap
, &ic
->ic_vaps
, iv_next
) {
249 /* only DWDS vaps are interesting */
250 if (vap
->iv_opmode
!= IEEE80211_M_WDS
||
251 (vap
->iv_flags_ext
& IEEE80211_FEXT_WDSLEGACY
))
253 /* if it came in this interface, don't send it back out */
255 if (ifp
== m
->m_pkthdr
.rcvif
)
258 * Duplicate the frame and send it.
260 mcopy
= m_copypacket(m
, M_NOWAIT
);
262 if_inc_counter(ifp
, IFCOUNTER_OERRORS
, 1);
266 ni
= ieee80211_find_txnode(vap
, eh
->ether_dhost
);
268 /* NB: ieee80211_find_txnode does stat+msg */
269 if_inc_counter(ifp
, IFCOUNTER_OERRORS
, 1);
273 /* calculate priority so drivers can find the tx queue */
274 if (ieee80211_classify(ni
, mcopy
)) {
275 IEEE80211_DISCARD_MAC(vap
,
276 IEEE80211_MSG_OUTPUT
| IEEE80211_MSG_WDS
,
277 eh
->ether_dhost
, NULL
,
278 "%s", "classification failure");
279 vap
->iv_stats
.is_tx_classify
++;
280 if_inc_counter(ifp
, IFCOUNTER_OERRORS
, 1);
282 ieee80211_free_node(ni
);
286 BPF_MTAP(ifp
, m
); /* 802.3 tx */
289 * Encapsulate the packet in prep for transmission.
291 IEEE80211_TX_LOCK(ic
);
292 mcopy
= ieee80211_encap(vap
, ni
, mcopy
);
294 /* NB: stat+msg handled in ieee80211_encap */
295 IEEE80211_TX_UNLOCK(ic
);
296 ieee80211_free_node(ni
);
299 mcopy
->m_flags
|= M_MCAST
;
300 mcopy
->m_pkthdr
.rcvif
= (void *) ni
;
302 err
= ieee80211_parent_xmitpkt(ic
, mcopy
);
303 IEEE80211_TX_UNLOCK(ic
);
305 if_inc_counter(ifp
, IFCOUNTER_OPACKETS
, 1);
306 if_inc_counter(ifp
, IFCOUNTER_OMCASTS
, 1);
307 if_inc_counter(ifp
, IFCOUNTER_OBYTES
,
314 * Handle DWDS discovery on receipt of a 4-address frame in
315 * ap mode. Queue the frame and post an event for someone
316 * to plumb the necessary WDS vap for this station. Frames
317 * received prior to the vap set running will then be reprocessed
318 * as if they were just received.
321 ieee80211_dwds_discover(struct ieee80211_node
*ni
, struct mbuf
*m
)
323 struct ieee80211com
*ic
= ni
->ni_ic
;
326 * Save the frame with an aging interval 4 times
327 * the listen interval specified by the station.
328 * Frames that sit around too long are reclaimed
329 * using this information.
330 * XXX handle overflow?
331 * XXX per/vap beacon interval?
333 m
->m_pkthdr
.rcvif
= (void *)(uintptr_t)
334 ieee80211_mac_hash(ic
, ni
->ni_macaddr
);
335 (void) ieee80211_ageq_append(&ic
->ic_stageq
, m
,
336 ((ni
->ni_intval
* ic
->ic_lintval
) << 2) / 1024);
337 ieee80211_notify_wds_discover(ni
);
341 * IEEE80211_M_WDS vap state machine handler.
344 wds_newstate(struct ieee80211vap
*vap
, enum ieee80211_state nstate
, int arg
)
346 struct ieee80211com
*ic
= vap
->iv_ic
;
347 struct ieee80211_node
*ni
;
348 enum ieee80211_state ostate
;
351 IEEE80211_LOCK_ASSERT(ic
);
353 ostate
= vap
->iv_state
;
354 IEEE80211_DPRINTF(vap
, IEEE80211_MSG_STATE
, "%s: %s -> %s\n", __func__
,
355 ieee80211_state_name
[ostate
], ieee80211_state_name
[nstate
]);
356 vap
->iv_state
= nstate
; /* state transition */
357 callout_stop(&vap
->iv_mgtsend
); /* XXX callout_drain */
358 if (ostate
!= IEEE80211_S_SCAN
)
359 ieee80211_cancel_scan(vap
); /* background scan */
360 ni
= vap
->iv_bss
; /* NB: no reference held */
363 case IEEE80211_S_INIT
:
365 case IEEE80211_S_SCAN
:
366 ieee80211_cancel_scan(vap
);
371 if (ostate
!= IEEE80211_S_INIT
) {
372 /* NB: optimize INIT -> INIT case */
373 ieee80211_reset_bss(vap
);
376 case IEEE80211_S_SCAN
:
378 case IEEE80211_S_INIT
:
379 ieee80211_check_scan_current(vap
);
385 case IEEE80211_S_RUN
:
386 if (ostate
== IEEE80211_S_INIT
) {
388 * Already have a channel; bypass the scan
389 * and startup immediately.
391 error
= ieee80211_create_wds(vap
, ic
->ic_curchan
);
401 * Process a received frame. The node associated with the sender
402 * should be supplied. If nothing was found in the node table then
403 * the caller is assumed to supply a reference to iv_bss instead.
404 * The RSSI and a timestamp are also supplied. The RSSI data is used
405 * during AP scanning to select a AP to associate with; it can have
406 * any units so long as values have consistent units and higher values
407 * mean ``better signal''. The receive timestamp is currently not used
408 * by the 802.11 layer.
411 wds_input(struct ieee80211_node
*ni
, struct mbuf
*m
,
412 const struct ieee80211_rx_stats
*rxs
, int rssi
, int nf
)
414 struct ieee80211vap
*vap
= ni
->ni_vap
;
415 struct ieee80211com
*ic
= ni
->ni_ic
;
416 struct ifnet
*ifp
= vap
->iv_ifp
;
417 struct ieee80211_frame
*wh
;
418 struct ieee80211_key
*key
;
419 struct ether_header
*eh
;
420 int hdrspace
, need_tap
= 1; /* mbuf need to be tapped. */
421 uint8_t dir
, type
, subtype
, qos
;
423 if (m
->m_flags
& M_AMPDU_MPDU
) {
425 * Fastpath for A-MPDU reorder q resubmission. Frames
426 * w/ M_AMPDU_MPDU marked have already passed through
427 * here but were received out of order and been held on
428 * the reorder queue. When resubmitted they are marked
429 * with the M_AMPDU_MPDU flag and we can bypass most of
430 * the normal processing.
432 wh
= mtod(m
, struct ieee80211_frame
*);
433 type
= IEEE80211_FC0_TYPE_DATA
;
434 dir
= wh
->i_fc
[1] & IEEE80211_FC1_DIR_MASK
;
435 subtype
= IEEE80211_FC0_SUBTYPE_QOS
;
436 hdrspace
= ieee80211_hdrspace(ic
, wh
); /* XXX optimize? */
440 KASSERT(ni
!= NULL
, ("null node"));
442 type
= -1; /* undefined */
444 if (m
->m_pkthdr
.len
< sizeof(struct ieee80211_frame_min
)) {
445 IEEE80211_DISCARD_MAC(vap
, IEEE80211_MSG_ANY
,
446 ni
->ni_macaddr
, NULL
,
447 "too short (1): len %u", m
->m_pkthdr
.len
);
448 vap
->iv_stats
.is_rx_tooshort
++;
452 * Bit of a cheat here, we use a pointer for a 3-address
453 * frame format but don't reference fields past outside
454 * ieee80211_frame_min w/o first validating the data is
457 wh
= mtod(m
, struct ieee80211_frame
*);
459 if (!IEEE80211_IS_MULTICAST(wh
->i_addr1
))
460 ni
->ni_inact
= ni
->ni_inact_reload
;
462 if ((wh
->i_fc
[0] & IEEE80211_FC0_VERSION_MASK
) !=
463 IEEE80211_FC0_VERSION_0
) {
464 IEEE80211_DISCARD_MAC(vap
, IEEE80211_MSG_ANY
,
465 ni
->ni_macaddr
, NULL
, "wrong version, fc %02x:%02x",
466 wh
->i_fc
[0], wh
->i_fc
[1]);
467 vap
->iv_stats
.is_rx_badversion
++;
471 dir
= wh
->i_fc
[1] & IEEE80211_FC1_DIR_MASK
;
472 type
= wh
->i_fc
[0] & IEEE80211_FC0_TYPE_MASK
;
473 subtype
= wh
->i_fc
[0] & IEEE80211_FC0_SUBTYPE_MASK
;
475 /* NB: WDS vap's do not scan */
476 if (m
->m_pkthdr
.len
< sizeof(struct ieee80211_frame_addr4
)) {
477 IEEE80211_DISCARD_MAC(vap
,
478 IEEE80211_MSG_ANY
, ni
->ni_macaddr
, NULL
,
479 "too short (3): len %u", m
->m_pkthdr
.len
);
480 vap
->iv_stats
.is_rx_tooshort
++;
483 /* NB: the TA is implicitly verified by finding the wds peer node */
484 if (!IEEE80211_ADDR_EQ(wh
->i_addr1
, vap
->iv_myaddr
) &&
485 !IEEE80211_ADDR_EQ(wh
->i_addr1
, ifp
->if_broadcastaddr
)) {
486 /* not interested in */
487 IEEE80211_DISCARD_MAC(vap
, IEEE80211_MSG_INPUT
,
488 wh
->i_addr1
, NULL
, "%s", "not to bss");
489 vap
->iv_stats
.is_rx_wrongbss
++;
492 IEEE80211_RSSI_LPF(ni
->ni_avgrssi
, rssi
);
494 if (IEEE80211_HAS_SEQ(type
, subtype
)) {
495 uint8_t tid
= ieee80211_gettid(wh
);
496 if (IEEE80211_QOS_HAS_SEQ(wh
) &&
497 TID_TO_WME_AC(tid
) >= WME_AC_VI
)
498 ic
->ic_wme
.wme_hipri_traffic
++;
499 if (! ieee80211_check_rxseq(ni
, wh
, wh
->i_addr1
))
503 case IEEE80211_FC0_TYPE_DATA
:
504 hdrspace
= ieee80211_hdrspace(ic
, wh
);
505 if (m
->m_len
< hdrspace
&&
506 (m
= m_pullup(m
, hdrspace
)) == NULL
) {
507 IEEE80211_DISCARD_MAC(vap
, IEEE80211_MSG_ANY
,
508 ni
->ni_macaddr
, NULL
,
509 "data too short: expecting %u", hdrspace
);
510 vap
->iv_stats
.is_rx_tooshort
++;
513 if (dir
!= IEEE80211_FC1_DIR_DSTODS
) {
514 IEEE80211_DISCARD(vap
, IEEE80211_MSG_INPUT
,
515 wh
, "data", "incorrect dir 0x%x", dir
);
516 vap
->iv_stats
.is_rx_wrongdir
++;
520 * Only legacy WDS traffic should take this path.
522 if ((vap
->iv_flags_ext
& IEEE80211_FEXT_WDSLEGACY
) == 0) {
523 IEEE80211_DISCARD(vap
, IEEE80211_MSG_INPUT
,
524 wh
, "data", "%s", "not legacy wds");
525 vap
->iv_stats
.is_rx_wrongdir
++;/*XXX*/
529 * Handle A-MPDU re-ordering. If the frame is to be
530 * processed directly then ieee80211_ampdu_reorder
531 * will return 0; otherwise it has consumed the mbuf
532 * and we should do nothing more with it.
534 if ((m
->m_flags
& M_AMPDU
) &&
535 ieee80211_ampdu_reorder(ni
, m
) != 0) {
542 * Handle privacy requirements. Note that we
543 * must not be preempted from here until after
544 * we (potentially) call ieee80211_crypto_demic;
545 * otherwise we may violate assumptions in the
546 * crypto cipher modules used to do delayed update
547 * of replay sequence numbers.
549 if (wh
->i_fc
[1] & IEEE80211_FC1_PROTECTED
) {
550 if ((vap
->iv_flags
& IEEE80211_F_PRIVACY
) == 0) {
552 * Discard encrypted frames when privacy is off.
554 IEEE80211_DISCARD(vap
, IEEE80211_MSG_INPUT
,
555 wh
, "WEP", "%s", "PRIVACY off");
556 vap
->iv_stats
.is_rx_noprivacy
++;
557 IEEE80211_NODE_STAT(ni
, rx_noprivacy
);
560 key
= ieee80211_crypto_decap(ni
, m
, hdrspace
);
562 /* NB: stats+msgs handled in crypto_decap */
563 IEEE80211_NODE_STAT(ni
, rx_wepfail
);
566 wh
= mtod(m
, struct ieee80211_frame
*);
567 wh
->i_fc
[1] &= ~IEEE80211_FC1_PROTECTED
;
569 /* XXX M_WEP and IEEE80211_F_PRIVACY */
574 * Save QoS bits for use below--before we strip the header.
576 if (subtype
== IEEE80211_FC0_SUBTYPE_QOS
) {
577 qos
= (dir
== IEEE80211_FC1_DIR_DSTODS
) ?
578 ((struct ieee80211_qosframe_addr4
*)wh
)->i_qos
[0] :
579 ((struct ieee80211_qosframe
*)wh
)->i_qos
[0];
584 * Next up, any fragmentation.
586 if (!IEEE80211_IS_MULTICAST(wh
->i_addr1
)) {
587 m
= ieee80211_defrag(ni
, m
, hdrspace
);
589 /* Fragment dropped or frame not complete yet */
593 wh
= NULL
; /* no longer valid, catch any uses */
596 * Next strip any MSDU crypto bits.
598 if (key
!= NULL
&& !ieee80211_crypto_demic(vap
, key
, m
, 0)) {
599 IEEE80211_DISCARD_MAC(vap
, IEEE80211_MSG_INPUT
,
600 ni
->ni_macaddr
, "data", "%s", "demic error");
601 vap
->iv_stats
.is_rx_demicfail
++;
602 IEEE80211_NODE_STAT(ni
, rx_demicfail
);
606 /* copy to listener after decrypt */
607 if (ieee80211_radiotap_active_vap(vap
))
608 ieee80211_radiotap_rx(vap
, m
);
612 * Finally, strip the 802.11 header.
614 m
= ieee80211_decap(vap
, m
, hdrspace
);
616 /* XXX mask bit to check for both */
617 /* don't count Null data frames as errors */
618 if (subtype
== IEEE80211_FC0_SUBTYPE_NODATA
||
619 subtype
== IEEE80211_FC0_SUBTYPE_QOS_NULL
)
621 IEEE80211_DISCARD_MAC(vap
, IEEE80211_MSG_INPUT
,
622 ni
->ni_macaddr
, "data", "%s", "decap error");
623 vap
->iv_stats
.is_rx_decap
++;
624 IEEE80211_NODE_STAT(ni
, rx_decap
);
627 eh
= mtod(m
, struct ether_header
*);
628 if (!ieee80211_node_is_authorized(ni
)) {
630 * Deny any non-PAE frames received prior to
631 * authorization. For open/shared-key
632 * authentication the port is mark authorized
633 * after authentication completes. For 802.1x
634 * the port is not marked authorized by the
635 * authenticator until the handshake has completed.
637 if (eh
->ether_type
!= htons(ETHERTYPE_PAE
)) {
638 IEEE80211_DISCARD_MAC(vap
, IEEE80211_MSG_INPUT
,
639 eh
->ether_shost
, "data",
640 "unauthorized port: ether type 0x%x len %u",
641 eh
->ether_type
, m
->m_pkthdr
.len
);
642 vap
->iv_stats
.is_rx_unauth
++;
643 IEEE80211_NODE_STAT(ni
, rx_unauth
);
648 * When denying unencrypted frames, discard
649 * any non-PAE frames received without encryption.
651 if ((vap
->iv_flags
& IEEE80211_F_DROPUNENC
) &&
652 (key
== NULL
&& (m
->m_flags
& M_WEP
) == 0) &&
653 eh
->ether_type
!= htons(ETHERTYPE_PAE
)) {
655 * Drop unencrypted frames.
657 vap
->iv_stats
.is_rx_unencrypted
++;
658 IEEE80211_NODE_STAT(ni
, rx_unencrypted
);
662 /* XXX require HT? */
663 if (qos
& IEEE80211_QOS_AMSDU
) {
664 m
= ieee80211_decap_amsdu(ni
, m
);
666 return IEEE80211_FC0_TYPE_DATA
;
668 #ifdef IEEE80211_SUPPORT_SUPERG
669 m
= ieee80211_decap_fastframe(vap
, ni
, m
);
671 return IEEE80211_FC0_TYPE_DATA
;
674 ieee80211_deliver_data(vap
, ni
, m
);
675 return IEEE80211_FC0_TYPE_DATA
;
677 case IEEE80211_FC0_TYPE_MGT
:
678 vap
->iv_stats
.is_rx_mgmt
++;
679 IEEE80211_NODE_STAT(ni
, rx_mgmt
);
680 if (dir
!= IEEE80211_FC1_DIR_NODS
) {
681 IEEE80211_DISCARD(vap
, IEEE80211_MSG_INPUT
,
682 wh
, "data", "incorrect dir 0x%x", dir
);
683 vap
->iv_stats
.is_rx_wrongdir
++;
686 if (m
->m_pkthdr
.len
< sizeof(struct ieee80211_frame
)) {
687 IEEE80211_DISCARD_MAC(vap
, IEEE80211_MSG_ANY
,
688 ni
->ni_macaddr
, "mgt", "too short: len %u",
690 vap
->iv_stats
.is_rx_tooshort
++;
693 #ifdef IEEE80211_DEBUG
694 if (ieee80211_msg_debug(vap
) || ieee80211_msg_dumppkts(vap
)) {
695 if_printf(ifp
, "received %s from %s rssi %d\n",
696 ieee80211_mgt_subtype_name(subtype
),
697 ether_sprintf(wh
->i_addr2
), rssi
);
700 if (wh
->i_fc
[1] & IEEE80211_FC1_PROTECTED
) {
701 IEEE80211_DISCARD(vap
, IEEE80211_MSG_INPUT
,
702 wh
, NULL
, "%s", "WEP set but not permitted");
703 vap
->iv_stats
.is_rx_mgtdiscard
++; /* XXX */
706 vap
->iv_recv_mgmt(ni
, m
, subtype
, rxs
, rssi
, nf
);
709 case IEEE80211_FC0_TYPE_CTL
:
710 vap
->iv_stats
.is_rx_ctl
++;
711 IEEE80211_NODE_STAT(ni
, rx_ctrl
);
715 IEEE80211_DISCARD(vap
, IEEE80211_MSG_ANY
,
716 wh
, "bad", "frame type 0x%x", type
);
717 /* should not come here */
721 if_inc_counter(ifp
, IFCOUNTER_IERRORS
, 1);
724 if (need_tap
&& ieee80211_radiotap_active_vap(vap
))
725 ieee80211_radiotap_rx(vap
, m
);
732 wds_recv_mgmt(struct ieee80211_node
*ni
, struct mbuf
*m0
, int subtype
,
733 const struct ieee80211_rx_stats
*rxs
, int rssi
, int nf
)
735 struct ieee80211vap
*vap
= ni
->ni_vap
;
736 struct ieee80211com
*ic
= ni
->ni_ic
;
737 struct ieee80211_frame
*wh
;
738 u_int8_t
*frm
, *efrm
;
740 wh
= mtod(m0
, struct ieee80211_frame
*);
741 frm
= (u_int8_t
*)&wh
[1];
742 efrm
= mtod(m0
, u_int8_t
*) + m0
->m_len
;
744 case IEEE80211_FC0_SUBTYPE_ACTION
:
745 case IEEE80211_FC0_SUBTYPE_ACTION_NOACK
:
746 if (ni
== vap
->iv_bss
) {
747 IEEE80211_DISCARD(vap
, IEEE80211_MSG_INPUT
,
748 wh
, NULL
, "%s", "unknown node");
749 vap
->iv_stats
.is_rx_mgtdiscard
++;
750 } else if (!IEEE80211_ADDR_EQ(vap
->iv_myaddr
, wh
->i_addr1
)) {
751 /* NB: not interested in multicast frames. */
752 IEEE80211_DISCARD(vap
, IEEE80211_MSG_INPUT
,
753 wh
, NULL
, "%s", "not for us");
754 vap
->iv_stats
.is_rx_mgtdiscard
++;
755 } else if (vap
->iv_state
!= IEEE80211_S_RUN
) {
756 IEEE80211_DISCARD(vap
, IEEE80211_MSG_INPUT
,
757 wh
, NULL
, "wrong state %s",
758 ieee80211_state_name
[vap
->iv_state
]);
759 vap
->iv_stats
.is_rx_mgtdiscard
++;
761 if (ieee80211_parse_action(ni
, m0
) == 0)
762 (void)ic
->ic_recv_action(ni
, wh
, frm
, efrm
);
766 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ
:
767 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP
:
768 case IEEE80211_FC0_SUBTYPE_REASSOC_REQ
:
769 case IEEE80211_FC0_SUBTYPE_REASSOC_RESP
:
770 case IEEE80211_FC0_SUBTYPE_PROBE_REQ
:
771 case IEEE80211_FC0_SUBTYPE_PROBE_RESP
:
772 case IEEE80211_FC0_SUBTYPE_TIMING_ADV
:
773 case IEEE80211_FC0_SUBTYPE_BEACON
:
774 case IEEE80211_FC0_SUBTYPE_ATIM
:
775 case IEEE80211_FC0_SUBTYPE_DISASSOC
:
776 case IEEE80211_FC0_SUBTYPE_AUTH
:
777 case IEEE80211_FC0_SUBTYPE_DEAUTH
:
778 IEEE80211_DISCARD(vap
, IEEE80211_MSG_INPUT
,
779 wh
, NULL
, "%s", "not handled");
780 vap
->iv_stats
.is_rx_mgtdiscard
++;
784 IEEE80211_DISCARD(vap
, IEEE80211_MSG_ANY
,
785 wh
, "mgt", "subtype 0x%x not handled", subtype
);
786 vap
->iv_stats
.is_rx_badsubtype
++;