1mod context;
6mod frame_writer;
7mod infra_bss;
8mod remote_client;
9
10use crate::ddk_converter;
11use crate::device::{self, DeviceOps};
12use crate::error::Error;
13use fdf::ArenaStaticBox;
14use ieee80211::{Bssid, MacAddr, Ssid};
15use log::{debug, error, info, trace, warn};
16use std::fmt;
17use wlan_common::mac::{self, CapabilityInfo};
18use wlan_common::timer::Timer;
19use wlan_common::TimeUnit;
20use zerocopy::SplitByteSlice;
21use {
22 fidl_fuchsia_wlan_common as fidl_common, fidl_fuchsia_wlan_minstrel as fidl_minstrel,
23 fidl_fuchsia_wlan_mlme as fidl_mlme, fidl_fuchsia_wlan_softmac as fidl_softmac,
24 fuchsia_trace as trace, wlan_trace as wtrace,
25};
26
27use context::*;
28use infra_bss::*;
29use remote_client::*;
30
31#[derive(Debug)]
32struct BufferedFrame {
33 buffer: ArenaStaticBox<[u8]>,
34 tx_flags: fidl_softmac::WlanTxInfoFlags,
35 async_id: trace::Id,
36}
37
38#[derive(Debug)]
40pub enum Rejection {
41 OtherBss,
43
44 BadDsBits,
48
49 FrameMalformed,
53
54 NoSrcAddr,
56
57 NoSuchClient(MacAddr),
59
60 Client(MacAddr, ClientRejection),
62
63 Error(anyhow::Error),
65}
66
67impl Rejection {
68 fn log_level(&self) -> log::Level {
69 match self {
70 Self::NoSrcAddr | Self::FrameMalformed => log::Level::Error,
71 Self::Client(_, e) => e.log_level(),
72 _ => log::Level::Trace,
73 }
74 }
75 fn log(&self, msg: &str) {
76 match self.log_level() {
77 log::Level::Trace => trace!("{}: {}", msg, self),
78 log::Level::Debug => debug!("{}: {}", msg, self),
79 log::Level::Info => info!("{}: {}", msg, self),
80 log::Level::Warn => warn!("{}: {}", msg, self),
81 log::Level::Error => error!("{}: {}", msg, self),
82 }
83 }
84}
85
86impl fmt::Display for Rejection {
87 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88 match self {
89 Self::Client(addr, e) => write!(f, "client {:02X?}: {:?}", addr, e),
90 _ => fmt::Debug::fmt(self, f),
91 }
92 }
93}
94
95impl From<anyhow::Error> for Rejection {
96 fn from(e: anyhow::Error) -> Rejection {
97 Self::Error(e)
98 }
99}
100
101#[derive(Debug)]
102pub enum TimedEvent {
103 ClientEvent(MacAddr, ClientEvent),
105}
106
107pub struct Ap<D> {
108 ctx: Context<D>,
109 bss: Option<InfraBss>,
110}
111
112trait BssOptionExt<T: std::borrow::Borrow<InfraBss>> {
115 fn ok_or_bss_err(self) -> Result<T, Error>;
116}
117
118impl<T: std::borrow::Borrow<InfraBss>> BssOptionExt<T> for Option<T> {
119 fn ok_or_bss_err(self) -> Result<T, Error> {
120 self.ok_or(Error::Status(format!("BSS not started"), zx::Status::BAD_STATE))
121 }
122}
123
124impl<D: DeviceOps> crate::MlmeImpl for Ap<D> {
125 type Config = Bssid;
126 type Device = D;
127 type TimerEvent = TimedEvent;
128
129 async fn new(
130 config: Self::Config,
131 device: D,
132 timer: Timer<TimedEvent>,
133 ) -> Result<Self, anyhow::Error>
134 where
135 Self: Sized,
136 {
137 Ok(Self::new(device, timer, config))
138 }
139 async fn handle_mlme_request(
140 &mut self,
141 req: wlan_sme::MlmeRequest,
142 ) -> Result<(), anyhow::Error> {
143 Self::handle_mlme_req(self, req).await.map_err(|e| e.into())
144 }
145 async fn handle_mac_frame_rx(
146 &mut self,
147 frame: &[u8],
148 rx_info: fidl_softmac::WlanRxInfo,
149 async_id: trace::Id,
150 ) {
151 Self::handle_mac_frame_rx(self, frame, rx_info, async_id).await
152 }
153 fn handle_eth_frame_tx(
154 &mut self,
155 bytes: &[u8],
156 async_id: trace::Id,
157 ) -> Result<(), anyhow::Error> {
158 Self::handle_eth_frame_tx(self, bytes, async_id);
159 Ok(())
160 }
161 async fn handle_scan_complete(&mut self, _status: zx::Status, _scan_id: u64) {
162 warn!("Unexpected ScanComplete for AP MLME.");
163 return;
164 }
165 async fn handle_timeout(&mut self, event: TimedEvent) {
166 Self::handle_timed_event(self, event).await
167 }
168 fn access_device(&mut self) -> &mut Self::Device {
169 &mut self.ctx.device
170 }
171}
172
173impl<D> Ap<D> {
174 pub fn new(device: D, timer: Timer<TimedEvent>, bssid: Bssid) -> Self {
175 Self { ctx: Context::new(device, timer, bssid), bss: None }
176 }
177
178 fn handle_sme_list_minstrel_peers(
179 &self,
180 responder: wlan_sme::responder::Responder<fidl_mlme::MinstrelListResponse>,
181 ) -> Result<(), Error> {
182 error!("ListMinstrelPeers is not supported.");
184 let peers = fidl_minstrel::Peers { addrs: vec![] };
185 let resp = fidl_mlme::MinstrelListResponse { peers };
186 responder.respond(resp);
187 Ok(())
188 }
189
190 fn handle_sme_get_minstrel_stats(
191 &self,
192 responder: wlan_sme::responder::Responder<fidl_mlme::MinstrelStatsResponse>,
193 _addr: &MacAddr,
194 ) -> Result<(), Error> {
195 error!("GetMinstrelStats is not supported.");
197 let resp = fidl_mlme::MinstrelStatsResponse { peer: None };
198 responder.respond(resp);
199 Ok(())
200 }
201}
202
203impl<D: DeviceOps> Ap<D> {
204 pub async fn handle_timed_event(&mut self, event: TimedEvent) {
206 let bss = match self.bss.as_mut() {
207 Some(bss) => bss,
208 None => {
209 error!("received timed event but BSS was not started yet");
210 return;
211 }
212 };
213
214 if let Err(e) = bss.handle_timed_event(&mut self.ctx, event).await {
215 error!("failed to handle timed event frame: {}", e)
216 }
217 }
218
219 async fn handle_mlme_start_req(&mut self, req: fidl_mlme::StartRequest) -> Result<(), Error> {
223 if self.bss.is_some() {
224 info!("MLME-START.request: BSS already started");
225 self.ctx.send_mlme_start_conf(fidl_mlme::StartResultCode::BssAlreadyStartedOrJoined)?;
226 return Ok(());
227 }
228
229 if req.bss_type != fidl_common::BssType::Infrastructure {
230 info!("MLME-START.request: BSS type {:?} not supported", req.bss_type);
231 self.ctx.send_mlme_start_conf(fidl_mlme::StartResultCode::NotSupported)?;
232 return Ok(());
233 }
234
235 self.bss.replace(
236 InfraBss::new(
237 &mut self.ctx,
238 Ssid::from_bytes_unchecked(req.ssid),
239 TimeUnit(req.beacon_period),
240 req.dtim_period,
241 CapabilityInfo(req.capability_info),
242 req.rates,
243 req.channel,
244 req.rsne,
245 )
246 .await?,
247 );
248
249 self.ctx.send_mlme_start_conf(fidl_mlme::StartResultCode::Success)?;
250
251 info!("MLME-START.request: OK");
252 Ok(())
253 }
254
255 async fn handle_mlme_stop_req(&mut self, _req: fidl_mlme::StopRequest) -> Result<(), Error> {
257 match self.bss.take() {
258 Some(bss) => match bss.stop(&mut self.ctx).await {
259 Ok(_) => self.ctx.send_mlme_stop_conf(fidl_mlme::StopResultCode::Success)?,
260 Err(e) => {
261 self.ctx.send_mlme_stop_conf(fidl_mlme::StopResultCode::InternalError)?;
262 return Err(e);
263 }
264 },
265 None => {
266 info!("MLME-STOP.request: BSS not started");
267 self.ctx.send_mlme_stop_conf(fidl_mlme::StopResultCode::BssAlreadyStopped)?;
268 }
269 }
270 info!("MLME-STOP.request: OK");
271 Ok(())
272 }
273
274 pub async fn handle_mlme_setkeys_req(
278 &mut self,
279 req: fidl_mlme::SetKeysRequest,
280 ) -> Result<(), Error> {
281 if let Some(bss) = self.bss.as_mut() {
282 bss.handle_mlme_setkeys_req(&mut self.ctx, req.keylist).await
283 } else {
284 Err(Error::Status(format!("cannot set keys on unstarted BSS"), zx::Status::BAD_STATE))
285 }
286 }
287
288 pub async fn handle_mlme_query_device_info(
289 &mut self,
290 responder: wlan_sme::responder::Responder<fidl_mlme::DeviceInfo>,
291 ) -> Result<(), Error> {
292 let info = ddk_converter::mlme_device_info_from_softmac(
293 device::try_query(&mut self.ctx.device).await?,
294 )?;
295 responder.respond(info);
296 Ok(())
297 }
298
299 pub async fn handle_mlme_query_mac_sublayer_support(
300 &mut self,
301 responder: wlan_sme::responder::Responder<fidl_common::MacSublayerSupport>,
302 ) -> Result<(), Error> {
303 let support = device::try_query_mac_sublayer_support(&mut self.ctx.device).await?;
304 responder.respond(support);
305 Ok(())
306 }
307
308 pub async fn handle_mlme_query_security_support(
309 &mut self,
310 responder: wlan_sme::responder::Responder<fidl_common::SecuritySupport>,
311 ) -> Result<(), Error> {
312 let support = device::try_query_security_support(&mut self.ctx.device).await?;
313 responder.respond(support);
314 Ok(())
315 }
316
317 pub async fn handle_mlme_query_spectrum_management_support(
318 &mut self,
319 responder: wlan_sme::responder::Responder<fidl_common::SpectrumManagementSupport>,
320 ) -> Result<(), Error> {
321 let support = device::try_query_spectrum_management_support(&mut self.ctx.device).await?;
322 responder.respond(support);
323 Ok(())
324 }
325
326 pub async fn handle_mlme_req(&mut self, req: wlan_sme::MlmeRequest) -> Result<(), Error> {
327 use wlan_sme::MlmeRequest as Req;
328 match req {
329 Req::Start(req) => self.handle_mlme_start_req(req).await,
330 Req::Stop(req) => self.handle_mlme_stop_req(req).await,
331 Req::SetKeys(req) => self.handle_mlme_setkeys_req(req).await,
332 Req::QueryDeviceInfo(responder) => self.handle_mlme_query_device_info(responder).await,
333 Req::QueryMacSublayerSupport(responder) => {
334 self.handle_mlme_query_mac_sublayer_support(responder).await
335 }
336 Req::QuerySecuritySupport(responder) => {
337 self.handle_mlme_query_security_support(responder).await
338 }
339 Req::QuerySpectrumManagementSupport(responder) => {
340 self.handle_mlme_query_spectrum_management_support(responder).await
341 }
342 Req::ListMinstrelPeers(responder) => self.handle_sme_list_minstrel_peers(responder),
343 Req::GetMinstrelStats(req, responder) => {
344 self.handle_sme_get_minstrel_stats(responder, &req.peer_addr.into())
345 }
346 Req::AuthResponse(resp) => {
347 info!("Handling MLME auth resp. self.bss.is_some()?: {}", self.bss.is_some());
349 self.bss.as_mut().ok_or_bss_err()?.handle_mlme_auth_resp(&mut self.ctx, resp).await
350 }
351 Req::Deauthenticate(req) => {
352 self.bss.as_mut().ok_or_bss_err()?.handle_mlme_deauth_req(&mut self.ctx, req).await
353 }
354 Req::AssocResponse(resp) => {
355 self.bss.as_mut().ok_or_bss_err()?.handle_mlme_assoc_resp(&mut self.ctx, resp).await
356 }
357 Req::Disassociate(req) => {
358 self.bss
359 .as_mut()
360 .ok_or_bss_err()?
361 .handle_mlme_disassoc_req(&mut self.ctx, req)
362 .await
363 }
364 Req::SetCtrlPort(req) => {
365 self.bss.as_mut().ok_or_bss_err()?.handle_mlme_set_controlled_port_req(req)
366 }
367 Req::Eapol(req) => {
368 self.bss.as_mut().ok_or_bss_err()?.handle_mlme_eapol_req(&mut self.ctx, req)
369 }
370 _ => Err(Error::Status(format!("not supported"), zx::Status::NOT_SUPPORTED)),
371 }
372 .map_err(|e| {
373 error!("error handling MLME message: {}", e);
374 e
375 })
376 }
377
378 pub fn handle_eth_frame_tx(&mut self, frame: &[u8], async_id: trace::Id) {
379 let bss = match self.bss.as_mut() {
380 Some(bss) => bss,
381 None => {
382 error!("received Ethernet frame but BSS was not started yet");
383 return;
384 }
385 };
386
387 let mac::EthernetFrame { hdr, body } =
388 match mac::EthernetFrame::parse(frame).ok_or_else(|| Rejection::FrameMalformed) {
389 Ok(eth_frame) => eth_frame,
390 Err(e) => {
391 error!("failed to parse Ethernet frame: {}", e);
392 return;
393 }
394 };
395
396 if let Err(e) = bss.handle_eth_frame(&mut self.ctx, *hdr, body, async_id) {
397 e.log("failed to handle Ethernet frame")
398 }
399 }
400
401 pub async fn handle_mac_frame_rx<B: SplitByteSlice>(
402 &mut self,
403 bytes: B,
404 rx_info: fidl_softmac::WlanRxInfo,
405 async_id: trace::Id,
406 ) {
407 let bss = match self.bss.as_mut() {
408 Some(bss) => bss,
409 None => {
410 error!("received WLAN frame but BSS was not started yet");
411 wtrace::async_end_wlansoftmac_rx(async_id, "BSS not started");
412 return;
413 }
414 };
415
416 if rx_info.channel.primary != bss.channel {
418 wtrace::async_end_wlansoftmac_rx(async_id, "frame from wrong channel");
419 return;
420 }
421
422 let body_aligned = (rx_info.rx_flags & fidl_softmac::WlanRxInfoFlags::FRAME_BODY_PADDING_4)
423 != fidl_softmac::WlanRxInfoFlags::empty();
424
425 let mac_frame = match mac::MacFrame::parse(bytes, body_aligned) {
426 Some(mac_frame) => mac_frame,
427 None => {
428 error!("failed to parse MAC frame");
429 wtrace::async_end_wlansoftmac_rx(async_id, "failed to parse frame");
430 return;
431 }
432 };
433
434 if let Err(e) = match mac_frame {
435 mac::MacFrame::Mgmt(mgmt) => bss.handle_mgmt_frame(&mut self.ctx, mgmt).await,
436 mac::MacFrame::Data(data_frame) => bss.handle_data_frame(&mut self.ctx, data_frame),
437 mac::MacFrame::Ctrl(ctrl_frame) => bss.handle_ctrl_frame(&mut self.ctx, ctrl_frame),
438 mac::MacFrame::Unsupported { frame_ctrl } => {
439 error!("received unsupported MAC frame: frame_ctrl = {:?}", frame_ctrl);
440 wtrace::async_end_wlansoftmac_rx(async_id, "received unsupported frame");
441 return;
442 }
443 } {
444 wtrace::async_end_wlansoftmac_rx(async_id, "failed to handle frame");
445 e.log("failed to handle MAC frame")
446 } else {
447 wtrace::async_end_wlansoftmac_rx(async_id, "successfully handled frame");
448 }
449 }
450}
451
452#[cfg(test)]
453mod tests {
454 use super::*;
455 use crate::device::{test_utils, FakeDevice, FakeDeviceConfig, FakeDeviceState, LinkStatus};
456 use crate::test_utils::MockWlanRxInfo;
457 use fuchsia_sync::Mutex;
458 use ieee80211::MacAddrBytes;
459 use lazy_static::lazy_static;
460 use std::sync::Arc;
461 use wlan_common::big_endian::BigEndianU16;
462 use wlan_common::test_utils::fake_frames::fake_wpa2_rsne;
463 use wlan_common::{assert_variant, timer};
464 use wlan_frame_writer::write_frame_to_vec;
465 use wlan_sme::responder::Responder;
466 use {
467 fidl_fuchsia_wlan_common as fidl_common, fidl_fuchsia_wlan_ieee80211 as fidl_ieee80211,
468 fidl_fuchsia_wlan_softmac as fidl_softmac,
469 };
470
471 lazy_static! {
472 static ref CLIENT_ADDR: MacAddr = [4u8; 6].into();
473 static ref BSSID: Bssid = [2u8; 6].into();
474 static ref CLIENT_ADDR2: MacAddr = [6u8; 6].into();
475 }
476
477 fn make_eth_frame(
478 dst_addr: MacAddr,
479 src_addr: MacAddr,
480 protocol_id: u16,
481 body: &[u8],
482 ) -> Vec<u8> {
483 write_frame_to_vec!({
484 headers: {
485 mac::EthernetIIHdr: &mac::EthernetIIHdr {
486 da: dst_addr,
487 sa: src_addr,
488 ether_type: BigEndianU16::from_native(protocol_id),
489 },
490 },
491 payload: body,
492 })
493 .unwrap() }
495
496 async fn make_ap(
500 ) -> (Ap<FakeDevice>, Arc<Mutex<FakeDeviceState>>, timer::EventStream<TimedEvent>) {
501 let (timer, time_stream) = timer::create_timer();
502 let (fake_device, fake_device_state) = FakeDevice::new_with_config(
503 FakeDeviceConfig::default()
504 .with_mock_mac_role(fidl_common::WlanMacRole::Ap)
505 .with_mock_sta_addr((*BSSID).to_array()),
506 )
507 .await;
508 (Ap::new(fake_device, timer, *BSSID), fake_device_state, time_stream)
509 }
510
511 #[fuchsia::test(allow_stalls = false)]
512 async fn ap_handle_eth_frame() {
513 let (mut ap, fake_device_state, _) = make_ap().await;
514 ap.bss.replace(
515 InfraBss::new(
516 &mut ap.ctx,
517 Ssid::try_from("coolnet").unwrap(),
518 TimeUnit::DEFAULT_BEACON_INTERVAL,
519 2,
520 CapabilityInfo(0),
521 vec![0b11111000],
522 1,
523 None,
524 )
525 .await
526 .expect("expected InfraBss::new ok"),
527 );
528 ap.bss.as_mut().unwrap().clients.insert(*CLIENT_ADDR, RemoteClient::new(*CLIENT_ADDR));
529
530 let client = ap.bss.as_mut().unwrap().clients.get_mut(&CLIENT_ADDR).unwrap();
531 client
532 .handle_mlme_auth_resp(&mut ap.ctx, fidl_mlme::AuthenticateResultCode::Success)
533 .await
534 .expect("expected OK");
535 client
536 .handle_mlme_assoc_resp(
537 &mut ap.ctx,
538 false,
539 1,
540 mac::CapabilityInfo(0),
541 fidl_mlme::AssociateResultCode::Success,
542 1,
543 &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10][..],
544 )
545 .await
546 .expect("expected OK");
547 fake_device_state.lock().wlan_queue.clear();
548
549 ap.handle_eth_frame_tx(
550 &make_eth_frame(*CLIENT_ADDR, *CLIENT_ADDR2, 0x1234, &[1, 2, 3, 4, 5][..]),
551 0.into(),
552 );
553
554 assert_eq!(fake_device_state.lock().wlan_queue.len(), 1);
555 assert_eq!(
556 &fake_device_state.lock().wlan_queue[0].0[..],
557 &[
558 0b00001000, 0b00000010, 0, 0, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 0x30, 0, 0xAA, 0xAA, 0x03, 0, 0, 0, 0x12, 0x34, 1, 2, 3, 4, 5,
570 ][..]
571 );
572 }
573
574 #[fuchsia::test(allow_stalls = false)]
575 async fn ap_handle_eth_frame_no_such_client() {
576 let (mut ap, _, _) = make_ap().await;
577 ap.bss.replace(
578 InfraBss::new(
579 &mut ap.ctx,
580 Ssid::try_from("coolnet").unwrap(),
581 TimeUnit::DEFAULT_BEACON_INTERVAL,
582 2,
583 CapabilityInfo(0),
584 vec![0b11111000],
585 1,
586 None,
587 )
588 .await
589 .expect("expected InfraBss::new ok"),
590 );
591 ap.handle_eth_frame_tx(
592 &make_eth_frame(*CLIENT_ADDR2, *CLIENT_ADDR, 0x1234, &[1, 2, 3, 4, 5][..]),
593 0.into(),
594 );
595 }
596
597 fn mock_rx_info(ap: &Ap<FakeDevice>) -> fidl_softmac::WlanRxInfo {
598 let channel = fidl_common::WlanChannel {
599 primary: ap.bss.as_ref().unwrap().channel,
600 cbw: fidl_common::ChannelBandwidth::Cbw20,
601 secondary80: 0,
602 };
603 MockWlanRxInfo::with_channel(channel).into()
604 }
605
606 #[fuchsia::test(allow_stalls = false)]
607 async fn ap_handle_mac_frame() {
608 let (mut ap, fake_device_state, _) = make_ap().await;
609 ap.bss.replace(
610 InfraBss::new(
611 &mut ap.ctx,
612 Ssid::try_from("coolnet").unwrap(),
613 TimeUnit::DEFAULT_BEACON_INTERVAL,
614 2,
615 CapabilityInfo(0),
616 vec![0b11111000],
617 1,
618 None,
619 )
620 .await
621 .expect("expected InfraBss::new ok"),
622 );
623 ap.handle_mac_frame_rx(
624 &[
625 0b10110000, 0b00000000, 0, 0, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 0x10, 0, 0, 0, 1, 0, 0, 0, ][..],
637 mock_rx_info(&ap),
638 0.into(),
639 )
640 .await;
641
642 assert_eq!(ap.bss.as_mut().unwrap().clients.contains_key(&CLIENT_ADDR), true);
643
644 let msg = fake_device_state
645 .lock()
646 .next_mlme_msg::<fidl_mlme::AuthenticateIndication>()
647 .expect("expected MLME message");
648 assert_eq!(
649 msg,
650 fidl_mlme::AuthenticateIndication {
651 peer_sta_address: CLIENT_ADDR.to_array(),
652 auth_type: fidl_mlme::AuthenticationTypes::OpenSystem,
653 },
654 );
655 }
656
657 #[fuchsia::test(allow_stalls = false)]
658 async fn ap_handle_mac_frame_ps_poll() {
659 let (mut ap, fake_device_state, _) = make_ap().await;
660 ap.bss.replace(
661 InfraBss::new(
662 &mut ap.ctx,
663 Ssid::try_from("coolnet").unwrap(),
664 TimeUnit::DEFAULT_BEACON_INTERVAL,
665 2,
666 CapabilityInfo(0),
667 vec![0b11111000],
668 1,
669 None,
670 )
671 .await
672 .expect("expected InfraBss::new ok"),
673 );
674 ap.bss.as_mut().unwrap().clients.insert(*CLIENT_ADDR, RemoteClient::new(*CLIENT_ADDR));
675
676 let client = ap.bss.as_mut().unwrap().clients.get_mut(&CLIENT_ADDR).unwrap();
677 client
678 .handle_mlme_auth_resp(&mut ap.ctx, fidl_mlme::AuthenticateResultCode::Success)
679 .await
680 .expect("expected OK");
681 client
682 .handle_mlme_assoc_resp(
683 &mut ap.ctx,
684 false,
685 1,
686 mac::CapabilityInfo(0),
687 fidl_mlme::AssociateResultCode::Success,
688 1,
689 &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10][..],
690 )
691 .await
692 .expect("expected OK");
693 fake_device_state.lock().wlan_queue.clear();
694
695 ap.handle_mac_frame_rx(
697 &[
698 0b01001000, 0b00010001, 0, 0, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 0x10, 0, ][..],
705 mock_rx_info(&ap),
706 0.into(),
707 )
708 .await;
709
710 ap.handle_eth_frame_tx(
711 &make_eth_frame(*CLIENT_ADDR, *CLIENT_ADDR2, 0x1234, &[1, 2, 3, 4, 5][..]),
712 0.into(),
713 );
714 assert_eq!(fake_device_state.lock().wlan_queue.len(), 0);
715
716 ap.handle_mac_frame_rx(
718 &[
719 0b10100100, 0b00000000, 0b00000001, 0b11000000, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, ][..],
725 mock_rx_info(&ap),
726 0.into(),
727 )
728 .await;
729
730 assert_eq!(fake_device_state.lock().wlan_queue.len(), 1);
731 assert_eq!(
732 &fake_device_state.lock().wlan_queue[0].0[..],
733 &[
734 0b00001000, 0b00000010, 0, 0, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 0x30, 0, 0xAA, 0xAA, 0x03, 0, 0, 0, 0x12, 0x34, 1, 2, 3, 4, 5,
746 ][..]
747 );
748 }
749
750 #[fuchsia::test(allow_stalls = false)]
751 async fn ap_handle_mac_frame_no_such_client() {
752 let (mut ap, _, _) = make_ap().await;
753 ap.bss.replace(
754 InfraBss::new(
755 &mut ap.ctx,
756 Ssid::try_from("coolnet").unwrap(),
757 TimeUnit::DEFAULT_BEACON_INTERVAL,
758 2,
759 CapabilityInfo(0),
760 vec![0b11111000],
761 1,
762 None,
763 )
764 .await
765 .expect("expected InfraBss::new ok"),
766 );
767 ap.handle_mac_frame_rx(
768 &[
769 0b10100000, 0b00000001, 0, 0, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 0x10, 0, 8, 0, ][..],
779 mock_rx_info(&ap),
780 0.into(),
781 )
782 .await;
783
784 assert_eq!(ap.bss.as_mut().unwrap().clients.contains_key(&CLIENT_ADDR), false);
785 }
786
787 #[fuchsia::test(allow_stalls = false)]
788 async fn ap_handle_mac_frame_bogus() {
789 let (mut ap, _, _) = make_ap().await;
790 ap.bss.replace(
791 InfraBss::new(
792 &mut ap.ctx,
793 Ssid::try_from("coolnet").unwrap(),
794 TimeUnit::DEFAULT_BEACON_INTERVAL,
795 2,
796 CapabilityInfo(0),
797 vec![0b11111000],
798 1,
799 None,
800 )
801 .await
802 .expect("expected InfraBss::new ok"),
803 );
804 ap.handle_mac_frame_rx(
805 &[0][..],
806 fidl_softmac::WlanRxInfo {
807 rx_flags: fidl_softmac::WlanRxInfoFlags::empty(),
808 valid_fields: fidl_softmac::WlanRxInfoValid::empty(),
809 phy: fidl_common::WlanPhyType::Dsss,
810 data_rate: 0,
811 channel: fidl_common::WlanChannel {
812 primary: 0,
813 cbw: fidl_common::ChannelBandwidth::Cbw20,
814 secondary80: 0,
815 },
816 mcs: 0,
817 rssi_dbm: 0,
818 snr_dbh: 0,
819 },
820 0.into(),
821 )
822 .await;
823 }
824
825 #[fuchsia::test(allow_stalls = false)]
826 async fn ap_handle_mac_frame_wrong_channel_drop() {
827 let (mut ap, fake_device_state, _) = make_ap().await;
828 ap.bss.replace(
829 InfraBss::new(
830 &mut ap.ctx,
831 Ssid::try_from("coolnet").unwrap(),
832 TimeUnit::DEFAULT_BEACON_INTERVAL,
833 2,
834 CapabilityInfo(0),
835 vec![0b11111000],
836 1,
837 None,
838 )
839 .await
840 .expect("expected InfraBss::new ok"),
841 );
842 let probe_req = [
843 0b01000000, 0b00000000, 0, 0, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 0x10, 0, 0, 7, 0x63, 0x6f, 0x6f, 0x6c, 0x6e, 0x65, 0x74, 0x0a,
852 ];
853 let rx_info_wrong_channel = fidl_softmac::WlanRxInfo {
854 rx_flags: fidl_softmac::WlanRxInfoFlags::empty(),
855 valid_fields: fidl_softmac::WlanRxInfoValid::empty(),
856 phy: fidl_common::WlanPhyType::Dsss,
857 data_rate: 0,
858 channel: fidl_common::WlanChannel {
859 primary: 0,
860 cbw: fidl_common::ChannelBandwidth::Cbw20,
861 secondary80: 0,
862 },
863 mcs: 0,
864 rssi_dbm: 0,
865 snr_dbh: 0,
866 };
867 ap.handle_mac_frame_rx(&probe_req[..], rx_info_wrong_channel.clone(), 0.into()).await;
868
869 assert_eq!(fake_device_state.lock().wlan_queue.len(), 0);
871
872 let rx_info_same_channel = fidl_softmac::WlanRxInfo {
874 channel: fidl_common::WlanChannel {
875 primary: 1,
876 cbw: fidl_common::ChannelBandwidth::Cbw20,
877 secondary80: 0,
878 },
879 ..rx_info_wrong_channel
880 };
881 fake_device_state.lock().wlan_queue.clear();
882 ap.handle_mac_frame_rx(&probe_req[..], rx_info_same_channel, 0.into()).await;
883 assert_eq!(fake_device_state.lock().wlan_queue.len(), 1);
884 }
885
886 #[fuchsia::test(allow_stalls = false)]
887 async fn ap_handle_mlme_start_req() {
888 let (mut ap, fake_device_state, _) = make_ap().await;
889 ap.handle_mlme_start_req(fidl_mlme::StartRequest {
890 ssid: Ssid::try_from("coolnet").unwrap().into(),
891 bss_type: fidl_common::BssType::Infrastructure,
892 beacon_period: 5,
893 dtim_period: 1,
894 channel: 2,
895 capability_info: CapabilityInfo(0).raw(),
896 rates: vec![0b11111000],
897 country: fidl_mlme::Country { alpha2: *b"xx", suffix: fidl_mlme::COUNTRY_ENVIRON_ALL },
898 mesh_id: vec![],
899 rsne: None,
900 phy: fidl_common::WlanPhyType::Erp,
901 channel_bandwidth: fidl_common::ChannelBandwidth::Cbw20,
902 })
903 .await
904 .expect("expected Ap::handle_mlme_start_request OK");
905
906 assert!(ap.bss.is_some());
907 assert_eq!(
908 fake_device_state.lock().wlan_channel,
909 fidl_common::WlanChannel {
910 primary: 2,
911 cbw: fidl_common::ChannelBandwidth::Cbw20,
913 secondary80: 0,
914 }
915 );
916 assert_eq!(fake_device_state.lock().link_status, LinkStatus::UP);
917
918 let msg = fake_device_state
919 .lock()
920 .next_mlme_msg::<fidl_mlme::StartConfirm>()
921 .expect("expected MLME message");
922 assert_eq!(
923 msg,
924 fidl_mlme::StartConfirm { result_code: fidl_mlme::StartResultCode::Success },
925 );
926 }
927
928 #[fuchsia::test(allow_stalls = false)]
929 async fn ap_handle_mlme_start_req_already_started() {
930 let (mut ap, fake_device_state, _) = make_ap().await;
931 ap.bss.replace(
932 InfraBss::new(
933 &mut ap.ctx,
934 Ssid::try_from("coolnet").unwrap(),
935 TimeUnit::DEFAULT_BEACON_INTERVAL,
936 2,
937 CapabilityInfo(0),
938 vec![0b11111000],
939 1,
940 None,
941 )
942 .await
943 .expect("expected InfraBss::new ok"),
944 );
945
946 ap.handle_mlme_start_req(fidl_mlme::StartRequest {
947 ssid: Ssid::try_from("coolnet").unwrap().into(),
948 bss_type: fidl_common::BssType::Infrastructure,
949 beacon_period: 5,
950 dtim_period: 1,
951 channel: 2,
952 capability_info: CapabilityInfo(0).raw(),
953 rates: vec![],
954 country: fidl_mlme::Country { alpha2: *b"xx", suffix: fidl_mlme::COUNTRY_ENVIRON_ALL },
955 mesh_id: vec![],
956 rsne: None,
957 phy: fidl_common::WlanPhyType::Erp,
958 channel_bandwidth: fidl_common::ChannelBandwidth::Cbw20,
959 })
960 .await
961 .expect("expected Ap::handle_mlme_start_request OK");
962
963 let msg = fake_device_state
964 .lock()
965 .next_mlme_msg::<fidl_mlme::StartConfirm>()
966 .expect("expected MLME message");
967 assert_eq!(
968 msg,
969 fidl_mlme::StartConfirm {
970 result_code: fidl_mlme::StartResultCode::BssAlreadyStartedOrJoined
971 },
972 );
973 }
974
975 #[fuchsia::test(allow_stalls = false)]
976 async fn ap_handle_mlme_stop_req() {
977 let (mut ap, fake_device_state, _) = make_ap().await;
978 ap.bss.replace(
979 InfraBss::new(
980 &mut ap.ctx,
981 Ssid::try_from("coolnet").unwrap(),
982 TimeUnit::DEFAULT_BEACON_INTERVAL,
983 2,
984 CapabilityInfo(0),
985 vec![0b11111000],
986 1,
987 None,
988 )
989 .await
990 .expect("expected InfraBss::new ok"),
991 );
992
993 ap.handle_mlme_stop_req(fidl_mlme::StopRequest {
994 ssid: Ssid::try_from("coolnet").unwrap().into(),
995 })
996 .await
997 .expect("expected Ap::handle_mlme_stop_request OK");
998 assert!(ap.bss.is_none());
999 assert_eq!(fake_device_state.lock().link_status, LinkStatus::DOWN);
1000
1001 let msg = fake_device_state
1002 .lock()
1003 .next_mlme_msg::<fidl_mlme::StopConfirm>()
1004 .expect("expected MLME message");
1005 assert_eq!(msg, fidl_mlme::StopConfirm { result_code: fidl_mlme::StopResultCode::Success },);
1006 }
1007
1008 #[fuchsia::test(allow_stalls = false)]
1009 async fn ap_handle_mlme_stop_req_already_stopped() {
1010 let (mut ap, fake_device_state, _) = make_ap().await;
1011
1012 ap.handle_mlme_stop_req(fidl_mlme::StopRequest {
1013 ssid: Ssid::try_from("coolnet").unwrap().into(),
1014 })
1015 .await
1016 .expect("expected Ap::handle_mlme_stop_request OK");
1017 assert!(ap.bss.is_none());
1018
1019 let msg = fake_device_state
1020 .lock()
1021 .next_mlme_msg::<fidl_mlme::StopConfirm>()
1022 .expect("expected MLME message");
1023 assert_eq!(
1024 msg,
1025 fidl_mlme::StopConfirm { result_code: fidl_mlme::StopResultCode::BssAlreadyStopped },
1026 );
1027 }
1028
1029 #[fuchsia::test(allow_stalls = false)]
1030 async fn ap_handle_mlme_setkeys_req() {
1031 let (mut ap, fake_device_state, _) = make_ap().await;
1032 ap.bss.replace(
1033 InfraBss::new(
1034 &mut ap.ctx,
1035 Ssid::try_from("coolnet").unwrap(),
1036 TimeUnit::DEFAULT_BEACON_INTERVAL,
1037 2,
1038 CapabilityInfo(0),
1039 vec![0b11111000],
1040 1,
1041 Some(fake_wpa2_rsne()),
1042 )
1043 .await
1044 .expect("expected InfraBss::new ok"),
1045 );
1046
1047 ap.handle_mlme_setkeys_req(fidl_mlme::SetKeysRequest {
1048 keylist: vec![fidl_mlme::SetKeyDescriptor {
1049 cipher_suite_oui: [1, 2, 3],
1050 cipher_suite_type: fidl_ieee80211::CipherSuiteType::from_primitive_allow_unknown(4),
1051 key_type: fidl_mlme::KeyType::Pairwise,
1052 address: [5; 6],
1053 key_id: 6,
1054 key: vec![1, 2, 3, 4, 5, 6, 7],
1055 rsc: 8,
1056 }],
1057 })
1058 .await
1059 .expect("expected Ap::handle_mlme_setkeys_req OK");
1060 assert_eq!(
1061 fake_device_state.lock().keys,
1062 vec![fidl_softmac::WlanKeyConfiguration {
1063 protection: Some(fidl_softmac::WlanProtection::RxTx),
1064 cipher_oui: Some([1, 2, 3]),
1065 cipher_type: Some(4),
1066 key_type: Some(fidl_ieee80211::KeyType::Pairwise),
1067 peer_addr: Some([5; 6]),
1068 key_idx: Some(6),
1069 key: Some(vec![1, 2, 3, 4, 5, 6, 7]),
1070 rsc: Some(8),
1071 ..Default::default()
1072 }]
1073 );
1074 }
1075
1076 #[fuchsia::test(allow_stalls = false)]
1077 async fn ap_handle_mlme_setkeys_req_no_bss() {
1078 let (mut ap, _, _) = make_ap().await;
1079 assert_variant!(
1080 ap.handle_mlme_setkeys_req(fidl_mlme::SetKeysRequest {
1081 keylist: vec![fidl_mlme::SetKeyDescriptor {
1082 cipher_suite_oui: [1, 2, 3],
1083 cipher_suite_type:
1084 fidl_ieee80211::CipherSuiteType::from_primitive_allow_unknown(4),
1085 key_type: fidl_mlme::KeyType::Pairwise,
1086 address: [5; 6],
1087 key_id: 6,
1088 key: vec![1, 2, 3, 4, 5, 6, 7],
1089 rsc: 8,
1090 }],
1091 })
1092 .await
1093 .expect_err("expected Ap::handle_mlme_setkeys_req error"),
1094 Error::Status(_, zx::Status::BAD_STATE)
1095 );
1096 }
1097
1098 #[fuchsia::test(allow_stalls = false)]
1099 async fn ap_handle_mlme_setkeys_req_bss_no_rsne() {
1100 let (mut ap, _, _) = make_ap().await;
1101 ap.bss.replace(
1102 InfraBss::new(
1103 &mut ap.ctx,
1104 Ssid::try_from("coolnet").unwrap(),
1105 TimeUnit::DEFAULT_BEACON_INTERVAL,
1106 2,
1107 CapabilityInfo(0),
1108 vec![0b11111000],
1109 1,
1110 None,
1111 )
1112 .await
1113 .expect("expected InfraBss::new ok"),
1114 );
1115
1116 assert_variant!(
1117 ap.handle_mlme_setkeys_req(fidl_mlme::SetKeysRequest {
1118 keylist: vec![fidl_mlme::SetKeyDescriptor {
1119 cipher_suite_oui: [1, 2, 3],
1120 cipher_suite_type:
1121 fidl_ieee80211::CipherSuiteType::from_primitive_allow_unknown(4),
1122 key_type: fidl_mlme::KeyType::Pairwise,
1123 address: [5; 6],
1124 key_id: 6,
1125 key: vec![1, 2, 3, 4, 5, 6, 7],
1126 rsc: 8,
1127 }],
1128 })
1129 .await
1130 .expect_err("expected Ap::handle_mlme_setkeys_req error"),
1131 Error::Status(_, zx::Status::BAD_STATE)
1132 );
1133 }
1134
1135 #[fuchsia::test(allow_stalls = false)]
1136 async fn ap_handle_mlme_req_handle_mlme_auth_resp() {
1137 let (mut ap, fake_device_state, _) = make_ap().await;
1138 ap.bss.replace(
1139 InfraBss::new(
1140 &mut ap.ctx,
1141 Ssid::try_from("coolnet").unwrap(),
1142 TimeUnit::DEFAULT_BEACON_INTERVAL,
1143 2,
1144 CapabilityInfo(0),
1145 vec![0b11111000],
1146 1,
1147 None,
1148 )
1149 .await
1150 .expect("expected InfraBss::new ok"),
1151 );
1152 ap.bss.as_mut().unwrap().clients.insert(*CLIENT_ADDR, RemoteClient::new(*CLIENT_ADDR));
1153
1154 ap.handle_mlme_req(wlan_sme::MlmeRequest::AuthResponse(fidl_mlme::AuthenticateResponse {
1155 peer_sta_address: CLIENT_ADDR.to_array(),
1156 result_code: fidl_mlme::AuthenticateResultCode::AntiCloggingTokenRequired,
1157 }))
1158 .await
1159 .expect("expected Ap::handle_mlme_msg(fidl_mlme::MlmeRequest::AuthenticateResp) ok");
1160 assert_eq!(fake_device_state.lock().wlan_queue.len(), 1);
1161 assert_eq!(
1162 &fake_device_state.lock().wlan_queue[0].0[..],
1163 &[
1164 0b10110000, 0, 0, 0, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0x10, 0, 0, 0, 2, 0, 76, 0, ][..]
1176 );
1177 }
1178
1179 #[fuchsia::test(allow_stalls = false)]
1180 async fn ap_handle_mlme_req_handle_mlme_auth_resp_no_bss() {
1181 let (mut ap, _, _) = make_ap().await;
1182
1183 assert_eq!(
1184 zx::Status::from(
1185 ap.handle_mlme_req(wlan_sme::MlmeRequest::AuthResponse(
1186 fidl_mlme::AuthenticateResponse {
1187 peer_sta_address: CLIENT_ADDR.to_array(),
1188 result_code: fidl_mlme::AuthenticateResultCode::AntiCloggingTokenRequired,
1189 }
1190 ))
1191 .await
1192 .expect_err(
1193 "expected Ap::handle_mlme_msg(fidl_mlme::MlmeRequest::AuthenticateResp) error"
1194 )
1195 ),
1196 zx::Status::BAD_STATE
1197 );
1198 }
1199
1200 #[fuchsia::test(allow_stalls = false)]
1201 async fn ap_handle_mlme_req_handle_mlme_auth_resp_no_such_client() {
1202 let (mut ap, _, _) = make_ap().await;
1203 ap.bss.replace(
1204 InfraBss::new(
1205 &mut ap.ctx,
1206 Ssid::try_from("coolnet").unwrap(),
1207 TimeUnit::DEFAULT_BEACON_INTERVAL,
1208 2,
1209 CapabilityInfo(0),
1210 vec![0b11111000],
1211 1,
1212 None,
1213 )
1214 .await
1215 .expect("expected InfraBss::new ok"),
1216 );
1217
1218 assert_eq!(
1219 zx::Status::from(
1220 ap.handle_mlme_req(wlan_sme::MlmeRequest::AuthResponse(
1221 fidl_mlme::AuthenticateResponse {
1222 peer_sta_address: CLIENT_ADDR.to_array(),
1223 result_code: fidl_mlme::AuthenticateResultCode::AntiCloggingTokenRequired,
1224 }
1225 ))
1226 .await
1227 .expect_err(
1228 "expected Ap::handle_mlme_msg(fidl_mlme::MlmeRequest::AuthenticateResp) error"
1229 )
1230 ),
1231 zx::Status::NOT_FOUND
1232 );
1233 }
1234
1235 #[fuchsia::test(allow_stalls = false)]
1236 async fn ap_handle_mlme_req_handle_mlme_deauth_req() {
1237 let (mut ap, fake_device_state, _) = make_ap().await;
1238 ap.bss.replace(
1239 InfraBss::new(
1240 &mut ap.ctx,
1241 Ssid::try_from("coolnet").unwrap(),
1242 TimeUnit::DEFAULT_BEACON_INTERVAL,
1243 2,
1244 CapabilityInfo(0),
1245 vec![0b11111000],
1246 1,
1247 None,
1248 )
1249 .await
1250 .expect("expected InfraBss::new ok"),
1251 );
1252 ap.bss.as_mut().unwrap().clients.insert(*CLIENT_ADDR, RemoteClient::new(*CLIENT_ADDR));
1253
1254 ap.handle_mlme_req(wlan_sme::MlmeRequest::Deauthenticate(
1255 fidl_mlme::DeauthenticateRequest {
1256 peer_sta_address: CLIENT_ADDR.to_array(),
1257 reason_code: fidl_ieee80211::ReasonCode::LeavingNetworkDeauth,
1258 },
1259 ))
1260 .await
1261 .expect("expected Ap::handle_mlme_msg(fidl_mlme::MlmeRequest::DeauthenticateReq) ok");
1262 assert_eq!(fake_device_state.lock().wlan_queue.len(), 1);
1263 assert_eq!(
1264 &fake_device_state.lock().wlan_queue[0].0[..],
1265 &[
1266 0b11000000, 0, 0, 0, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0x10, 0, 3, 0, ][..]
1276 );
1277 }
1278
1279 #[fuchsia::test(allow_stalls = false)]
1280 async fn ap_handle_mlme_req_handle_mlme_assoc_resp() {
1281 let (mut ap, fake_device_state, _) = make_ap().await;
1282 ap.bss.replace(
1283 InfraBss::new(
1284 &mut ap.ctx,
1285 Ssid::try_from("coolnet").unwrap(),
1286 TimeUnit::DEFAULT_BEACON_INTERVAL,
1287 2,
1288 CapabilityInfo(0),
1289 vec![0b11111000],
1290 1,
1291 None,
1292 )
1293 .await
1294 .expect("expected InfraBss::new ok"),
1295 );
1296 ap.bss.as_mut().unwrap().clients.insert(*CLIENT_ADDR, RemoteClient::new(*CLIENT_ADDR));
1297
1298 ap.handle_mlme_req(wlan_sme::MlmeRequest::AssocResponse(fidl_mlme::AssociateResponse {
1299 peer_sta_address: CLIENT_ADDR.to_array(),
1300 result_code: fidl_mlme::AssociateResultCode::Success,
1301 association_id: 1,
1302 capability_info: CapabilityInfo(0).raw(),
1303 rates: vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
1304 }))
1305 .await
1306 .expect("expected Ap::handle_mlme_msg(fidl_mlme::MlmeRequest::AssociateResp) ok");
1307 assert_eq!(fake_device_state.lock().wlan_queue.len(), 1);
1308 assert_eq!(
1309 &fake_device_state.lock().wlan_queue[0].0[..],
1310 &[
1311 0b00010000, 0, 0, 0, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0x10, 0, 0, 0, 0, 0, 1, 0, 1, 8, 1, 2, 3, 4, 5, 6, 7, 8, 50, 2, 9, 10, 90, 3, 90, 0, 0, ][..]
1327 );
1328 }
1329
1330 #[fuchsia::test(allow_stalls = false)]
1331 async fn ap_handle_mlme_req_handle_mlme_disassoc_req() {
1332 let (mut ap, fake_device_state, _) = make_ap().await;
1333 ap.bss.replace(
1334 InfraBss::new(
1335 &mut ap.ctx,
1336 Ssid::try_from("coolnet").unwrap(),
1337 TimeUnit::DEFAULT_BEACON_INTERVAL,
1338 2,
1339 CapabilityInfo(0),
1340 vec![0b11111000],
1341 1,
1342 None,
1343 )
1344 .await
1345 .expect("expected InfraBss::new ok"),
1346 );
1347 ap.bss.as_mut().unwrap().clients.insert(*CLIENT_ADDR, RemoteClient::new(*CLIENT_ADDR));
1348
1349 ap.handle_mlme_req(wlan_sme::MlmeRequest::Disassociate(fidl_mlme::DisassociateRequest {
1350 peer_sta_address: CLIENT_ADDR.to_array(),
1351 reason_code: fidl_ieee80211::ReasonCode::LeavingNetworkDisassoc,
1352 }))
1353 .await
1354 .expect("expected Ap::handle_mlme_msg(fidl_mlme::MlmeRequest::DisassociateReq) ok");
1355 assert_eq!(fake_device_state.lock().wlan_queue.len(), 1);
1356 assert_eq!(
1357 &fake_device_state.lock().wlan_queue[0].0[..],
1358 &[
1359 0b10100000, 0, 0, 0, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0x10, 0, 8, 0, ][..]
1369 );
1370 }
1371
1372 #[fuchsia::test(allow_stalls = false)]
1373 async fn ap_handle_mlme_req_handle_mlme_set_controlled_port_req() {
1374 let (mut ap, _, _) = make_ap().await;
1375 ap.bss.replace(
1376 InfraBss::new(
1377 &mut ap.ctx,
1378 Ssid::try_from("coolnet").unwrap(),
1379 TimeUnit::DEFAULT_BEACON_INTERVAL,
1380 2,
1381 CapabilityInfo(0),
1382 vec![0b11111000],
1383 1,
1384 Some(fake_wpa2_rsne()),
1385 )
1386 .await
1387 .expect("expected InfraBss::new ok"),
1388 );
1389 ap.bss.as_mut().unwrap().clients.insert(*CLIENT_ADDR, RemoteClient::new(*CLIENT_ADDR));
1390
1391 ap.handle_mlme_req(wlan_sme::MlmeRequest::AssocResponse(fidl_mlme::AssociateResponse {
1392 peer_sta_address: CLIENT_ADDR.to_array(),
1393 result_code: fidl_mlme::AssociateResultCode::Success,
1394 association_id: 1,
1395 capability_info: CapabilityInfo(0).raw(),
1396 rates: vec![1, 2, 3],
1397 }))
1398 .await
1399 .expect("expected Ap::handle_mlme_msg(fidl_mlme::MlmeRequest::AssociateResp) ok");
1400
1401 ap.handle_mlme_req(wlan_sme::MlmeRequest::SetCtrlPort(
1402 fidl_mlme::SetControlledPortRequest {
1403 peer_sta_address: CLIENT_ADDR.to_array(),
1404 state: fidl_mlme::ControlledPortState::Open,
1405 },
1406 ))
1407 .await
1408 .expect("expected Ap::handle_mlme_msg(fidl_mlme::MlmeRequest::SetControlledPort) ok");
1409 }
1410
1411 #[fuchsia::test(allow_stalls = false)]
1412 async fn ap_handle_mlme_req_handle_mlme_eapol_req() {
1413 let (mut ap, fake_device_state, _) = make_ap().await;
1414 ap.bss.replace(
1415 InfraBss::new(
1416 &mut ap.ctx,
1417 Ssid::try_from("coolnet").unwrap(),
1418 TimeUnit::DEFAULT_BEACON_INTERVAL,
1419 2,
1420 CapabilityInfo(0),
1421 vec![0b11111000],
1422 1,
1423 None,
1424 )
1425 .await
1426 .expect("expected InfraBss::new ok"),
1427 );
1428 ap.bss.as_mut().unwrap().clients.insert(*CLIENT_ADDR, RemoteClient::new(*CLIENT_ADDR));
1429
1430 ap.handle_mlme_req(wlan_sme::MlmeRequest::Eapol(fidl_mlme::EapolRequest {
1431 dst_addr: CLIENT_ADDR.to_array(),
1432 src_addr: BSSID.to_array(),
1433 data: vec![1, 2, 3],
1434 }))
1435 .await
1436 .expect("expected Ap::handle_mlme_msg(fidl_mlme::MlmeRequest::EapolReq) ok");
1437 assert_eq!(fake_device_state.lock().wlan_queue.len(), 1);
1438 assert_eq!(
1439 &fake_device_state.lock().wlan_queue[0].0[..],
1440 &[
1441 0b00001000, 0b00000010, 0, 0, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0x10, 0, 0xAA, 0xAA, 0x03, 0, 0, 0, 0x88, 0x8E, 1, 2, 3,
1453 ][..]
1454 );
1455 }
1456
1457 #[fuchsia::test(allow_stalls = false)]
1458 async fn ap_mlme_respond_to_query_device_info() {
1459 let (mut ap, _, _) = make_ap().await;
1460
1461 let (responder, receiver) = Responder::new();
1462 assert_variant!(
1463 ap.handle_mlme_req(wlan_sme::MlmeRequest::QueryDeviceInfo(responder)).await,
1464 Ok(())
1465 );
1466 assert_eq!(
1467 receiver.await.unwrap(),
1468 fidl_mlme::DeviceInfo {
1469 sta_addr: BSSID.to_array(),
1470 role: fidl_common::WlanMacRole::Ap,
1471 bands: test_utils::fake_mlme_band_caps(),
1472 softmac_hardware_capability: 0,
1473 qos_capable: false,
1474 }
1475 );
1476 }
1477
1478 #[fuchsia::test(allow_stalls = false)]
1479 async fn ap_mlme_respond_to_query_mac_sublayer_support() {
1480 let (mut ap, _, _) = make_ap().await;
1481
1482 let (responder, receiver) = Responder::new();
1483 assert_variant!(
1484 ap.handle_mlme_req(wlan_sme::MlmeRequest::QueryMacSublayerSupport(responder)).await,
1485 Ok(())
1486 );
1487 let resp = receiver.await.unwrap();
1488 assert_eq!(resp.rate_selection_offload.supported, false);
1489 assert_eq!(resp.data_plane.data_plane_type, fidl_common::DataPlaneType::EthernetDevice);
1490 assert_eq!(resp.device.is_synthetic, true);
1491 assert_eq!(
1492 resp.device.mac_implementation_type,
1493 fidl_common::MacImplementationType::Softmac
1494 );
1495 assert_eq!(resp.device.tx_status_report_supported, true);
1496 }
1497
1498 #[fuchsia::test(allow_stalls = false)]
1499 async fn ap_mlme_respond_to_query_security_support() {
1500 let (mut ap, _, _) = make_ap().await;
1501
1502 let (responder, receiver) = Responder::new();
1503 assert_variant!(
1504 ap.handle_mlme_req(wlan_sme::MlmeRequest::QuerySecuritySupport(responder)).await,
1505 Ok(())
1506 );
1507 let resp = receiver.await.unwrap();
1508 assert_eq!(resp.mfp.supported, false);
1509 assert_eq!(resp.sae.driver_handler_supported, false);
1510 assert_eq!(resp.sae.sme_handler_supported, false);
1511 }
1512
1513 #[fuchsia::test(allow_stalls = false)]
1514 async fn ap_mlme_respond_to_query_spectrum_management_support() {
1515 let (mut ap, _, _) = make_ap().await;
1516
1517 let (responder, receiver) = Responder::new();
1518 assert_variant!(
1519 ap.handle_mlme_req(wlan_sme::MlmeRequest::QuerySpectrumManagementSupport(responder))
1520 .await,
1521 Ok(())
1522 );
1523 assert_eq!(receiver.await.unwrap().dfs.supported, true);
1524 }
1525
1526 #[test]
1527 fn display_rejection() {
1528 assert_eq!(format!("{}", Rejection::BadDsBits), "BadDsBits");
1529 }
1530}