1#![warn(clippy::indexing_slicing)]
7#![cfg_attr(test, allow(clippy::indexing_slicing))]
8#![warn(clippy::unwrap_used)]
9#![cfg_attr(test, allow(clippy::unwrap_used))]
10#![warn(clippy::expect_used)]
11#![cfg_attr(test, allow(clippy::expect_used))]
12#![warn(clippy::unreachable)]
13#![cfg_attr(test, allow(clippy::unreachable))]
14#![warn(clippy::unimplemented)]
15#![cfg_attr(test, allow(clippy::unimplemented))]
16
17pub mod ap;
18pub mod client;
19pub mod serve;
20#[cfg(test)]
21pub mod test_utils;
22
23use fidl_fuchsia_wlan_mlme::{self as fidl_mlme, MlmeEvent};
24use futures::channel::mpsc;
25use thiserror::Error;
26use wlan_common::sink::UnboundedSink;
27use wlan_common::timer;
28use {
29 fidl_fuchsia_wlan_common as fidl_common, fidl_fuchsia_wlan_ieee80211 as fidl_ieee80211,
30 fidl_fuchsia_wlan_stats as fidl_stats,
31};
32
33#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd)]
34pub struct Config {
35 pub wep_supported: bool,
36 pub wpa1_supported: bool,
37}
38
39impl Config {
40 pub fn with_wep(mut self) -> Self {
41 self.wep_supported = true;
42 self
43 }
44
45 pub fn with_wpa1(mut self) -> Self {
46 self.wpa1_supported = true;
47 self
48 }
49}
50
51#[derive(Debug)]
52pub enum MlmeRequest {
53 Scan(fidl_mlme::ScanRequest),
54 AuthResponse(fidl_mlme::AuthenticateResponse),
55 AssocResponse(fidl_mlme::AssociateResponse),
56 Connect(fidl_mlme::ConnectRequest),
57 Reconnect(fidl_mlme::ReconnectRequest),
58 Roam(fidl_mlme::RoamRequest),
59 Deauthenticate(fidl_mlme::DeauthenticateRequest),
60 Disassociate(fidl_mlme::DisassociateRequest),
61 Eapol(fidl_mlme::EapolRequest),
62 SetKeys(fidl_mlme::SetKeysRequest),
63 SetCtrlPort(fidl_mlme::SetControlledPortRequest),
64 Start(fidl_mlme::StartRequest),
65 Stop(fidl_mlme::StopRequest),
66 GetIfaceStats(responder::Responder<fidl_mlme::GetIfaceStatsResponse>),
67 GetIfaceHistogramStats(responder::Responder<fidl_mlme::GetIfaceHistogramStatsResponse>),
68 GetSignalReport(responder::Responder<Result<fidl_stats::SignalReport, i32>>),
69 ListMinstrelPeers(responder::Responder<fidl_mlme::MinstrelListResponse>),
70 GetMinstrelStats(
71 fidl_mlme::MinstrelStatsRequest,
72 responder::Responder<fidl_mlme::MinstrelStatsResponse>,
73 ),
74 SaeHandshakeResp(fidl_mlme::SaeHandshakeResponse),
75 SaeFrameTx(fidl_mlme::SaeFrame),
76 WmmStatusReq,
77 FinalizeAssociation(fidl_mlme::NegotiatedCapabilities),
78 QueryDeviceInfo(responder::Responder<fidl_mlme::DeviceInfo>),
79 QueryMacSublayerSupport(responder::Responder<fidl_common::MacSublayerSupport>),
80 QuerySecuritySupport(responder::Responder<fidl_common::SecuritySupport>),
81 QuerySpectrumManagementSupport(responder::Responder<fidl_common::SpectrumManagementSupport>),
82 QueryTelemetrySupport(responder::Responder<Result<fidl_stats::TelemetrySupport, i32>>),
83 QueryApfPacketFilterSupport(
84 responder::Responder<Result<fidl_common::ApfPacketFilterSupport, i32>>,
85 ),
86 SetMacAddress(fidl_ieee80211::MacAddr, responder::Responder<Result<(), i32>>),
87 InstallApfPacketFilter(
88 fidl_mlme::MlmeInstallApfPacketFilterRequest,
89 responder::Responder<Result<(), i32>>,
90 ),
91 ReadApfPacketFilterData(
92 responder::Responder<Result<fidl_mlme::MlmeReadApfPacketFilterDataResponse, i32>>,
93 ),
94 SetApfPacketFilterEnabled(
95 fidl_mlme::MlmeSetApfPacketFilterEnabledRequest,
96 responder::Responder<Result<(), i32>>,
97 ),
98 GetApfPacketFilterEnabled(
99 responder::Responder<Result<fidl_mlme::MlmeGetApfPacketFilterEnabledResponse, i32>>,
100 ),
101}
102
103impl MlmeRequest {
104 pub fn name(&self) -> &'static str {
105 match self {
106 Self::Scan(_) => "Scan",
107 Self::AuthResponse(_) => "AuthResponse",
108 Self::AssocResponse(_) => "AssocResponse",
109 Self::Connect(_) => "Connect",
110 Self::Reconnect(_) => "Reconnect",
111 Self::Roam(_) => "Roam",
112 Self::Deauthenticate(_) => "Deauthenticate",
113 Self::Disassociate(_) => "Disassociate",
114 Self::Eapol(_) => "Eapol",
115 Self::SetKeys(_) => "SetKeys",
116 Self::SetCtrlPort(_) => "SetCtrlPort",
117 Self::Start(_) => "Start",
118 Self::Stop(_) => "Stop",
119 Self::GetIfaceStats(_) => "GetIfaceStats",
120 Self::GetIfaceHistogramStats(_) => "GetIfaceHistogramStats",
121 Self::GetSignalReport(_) => "GetSignalReport",
122 Self::ListMinstrelPeers(_) => "ListMinstrelPeers",
123 Self::GetMinstrelStats(_, _) => "GetMinstrelStats",
124 Self::SaeHandshakeResp(_) => "SaeHandshakeResp",
125 Self::SaeFrameTx(_) => "SaeFrameTx",
126 Self::WmmStatusReq => "WmmStatusReq",
127 Self::FinalizeAssociation(_) => "FinalizeAssociation",
128 Self::QueryDeviceInfo(_) => "QueryDeviceInfo",
129 Self::QueryMacSublayerSupport(_) => "QueryMacSublayerSupport",
130 Self::QuerySecuritySupport(_) => "QuerySecuritySupport",
131 Self::QuerySpectrumManagementSupport(_) => "QuerySpectrumManagementSupport",
132 Self::QueryTelemetrySupport(_) => "QueryTelemetrySupport",
133 Self::QueryApfPacketFilterSupport(_) => "QueryApfPacketFilterSupport",
134 Self::SetMacAddress(..) => "SetMacAddress",
135 Self::InstallApfPacketFilter(..) => "InstallApfPacketFilter",
136 Self::ReadApfPacketFilterData(_) => "ReadApfPacketFilterData",
137 Self::SetApfPacketFilterEnabled(..) => "SetApfPacketFilterEnabled",
138 Self::GetApfPacketFilterEnabled(_) => "GetApfPacketFilterEnabled",
139 }
140 }
141}
142
143pub trait Station {
144 type Event;
145
146 fn on_mlme_event(&mut self, event: fidl_mlme::MlmeEvent);
147 fn on_timeout(&mut self, timed_event: timer::Event<Self::Event>);
148}
149
150pub type MlmeStream = mpsc::UnboundedReceiver<MlmeRequest>;
151pub type MlmeEventStream = mpsc::UnboundedReceiver<MlmeEvent>;
152pub type MlmeSink = UnboundedSink<MlmeRequest>;
153pub type MlmeEventSink = UnboundedSink<MlmeEvent>;
154
155pub mod responder {
156 use futures::channel::oneshot;
157
158 #[derive(Debug)]
159 pub struct Responder<T>(oneshot::Sender<T>);
160
161 impl<T> Responder<T> {
162 pub fn new() -> (Self, oneshot::Receiver<T>) {
163 let (sender, receiver) = oneshot::channel();
164 (Responder(sender), receiver)
165 }
166
167 pub fn respond(self, result: T) {
168 #[allow(
169 clippy::unnecessary_lazy_evaluations,
170 reason = "mass allow for https://fxbug.dev/381896734"
171 )]
172 self.0.send(result).unwrap_or_else(|_| ());
173 }
174 }
175}
176
177fn mlme_event_name(event: &MlmeEvent) -> &str {
179 match event {
180 MlmeEvent::OnScanResult { .. } => "OnScanResult",
181 MlmeEvent::OnScanEnd { .. } => "OnScanEnd",
182 MlmeEvent::ConnectConf { .. } => "ConnectConf",
183 MlmeEvent::RoamConf { .. } => "RoamConf",
184 MlmeEvent::RoamStartInd { .. } => "RoamStartInd",
185 MlmeEvent::RoamResultInd { .. } => "RoamResultInd",
186 MlmeEvent::AuthenticateInd { .. } => "AuthenticateInd",
187 MlmeEvent::DeauthenticateConf { .. } => "DeauthenticateConf",
188 MlmeEvent::DeauthenticateInd { .. } => "DeauthenticateInd",
189 MlmeEvent::AssociateInd { .. } => "AssociateInd",
190 MlmeEvent::DisassociateConf { .. } => "DisassociateConf",
191 MlmeEvent::DisassociateInd { .. } => "DisassociateInd",
192 MlmeEvent::SetKeysConf { .. } => "SetKeysConf",
193 MlmeEvent::StartConf { .. } => "StartConf",
194 MlmeEvent::StopConf { .. } => "StopConf",
195 MlmeEvent::EapolConf { .. } => "EapolConf",
196 MlmeEvent::SignalReport { .. } => "SignalReport",
197 MlmeEvent::EapolInd { .. } => "EapolInd",
198 MlmeEvent::RelayCapturedFrame { .. } => "RelayCapturedFrame",
199 MlmeEvent::OnChannelSwitched { .. } => "OnChannelSwitched",
200 MlmeEvent::OnPmkAvailable { .. } => "OnPmkAvailable",
201 MlmeEvent::OnSaeHandshakeInd { .. } => "OnSaeHandshakeInd",
202 MlmeEvent::OnSaeFrameRx { .. } => "OnSaeFrameRx",
203 MlmeEvent::OnWmmStatusResp { .. } => "OnWmmStatusResp",
204 }
205}
206
207#[derive(Debug, Error)]
208pub enum Error {
209 #[error("scan end while not scanning")]
210 ScanEndNotScanning,
211 #[error("scan end with wrong txn id")]
212 ScanEndWrongTxnId,
213 #[error("scan result while not scanning")]
214 ScanResultNotScanning,
215 #[error("scan result with wrong txn id")]
216 ScanResultWrongTxnId,
217}