wlan_common/ie/
fake_ies.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::append::BufferTooSmall;
6use crate::ie::owe_transition::OweTransition;
7use crate::ie::rsn::rsne::Rsne;
8use crate::ie::rsn::{akm, cipher};
9use crate::ie::wpa::WpaIe;
10use crate::ie::wsc::{ProbeRespWsc, WpsState};
11use crate::ie::*;
12use crate::organization::Oui;
13use ieee80211::{Bssid, Ssid};
14
15pub fn fake_ht_cap_chanwidth(chanwidth: ChanWidthSet) -> HtCapabilities {
16    let mut ht_cap = fake_ht_capabilities();
17    ht_cap.ht_cap_info = ht_cap.ht_cap_info.with_chan_width_set(chanwidth);
18    ht_cap
19}
20
21pub fn fake_ht_op_sec_offset(secondary_offset: SecChanOffset) -> HtOperation {
22    let mut ht_op = fake_ht_operation();
23    ht_op.ht_op_info.set_secondary_chan_offset(secondary_offset);
24    ht_op
25}
26
27fn fake_supported_mcs_set() -> SupportedMcsSet {
28    SupportedMcsSet(0)
29        .with_rx_mcs(RxMcsBitmask(0x01000000ff))
30        .with_rx_highest_rate(0)
31        .with_tx_set_defined(true)
32        .with_tx_rx_diff(false)
33        .with_tx_max_ss(NumSpatialStreams::from_human(1).unwrap())
34        .with_tx_ueqm(false)
35}
36
37pub fn fake_ht_capabilities() -> HtCapabilities {
38    HtCapabilities {
39        ht_cap_info: HtCapabilityInfo(0)
40            .with_chan_width_set(ChanWidthSet::TWENTY_FORTY)
41            .with_sm_power_save(SmPowerSave::DISABLED)
42            .with_greenfield(true)
43            .with_short_gi_20(true)
44            .with_short_gi_40(true)
45            .with_tx_stbc(true)
46            .with_rx_stbc(1),
47        ampdu_params: AmpduParams(0),
48        mcs_set: fake_supported_mcs_set(),
49        ht_ext_cap: HtExtCapabilities(0),
50        txbf_cap: TxBfCapability(0)
51            .with_csi_antennas(NumAntennas::from_human(1).unwrap())
52            .with_noncomp_steering_ants(NumAntennas::from_human(1).unwrap())
53            .with_comp_steering_ants(NumAntennas::from_human(1).unwrap())
54            .with_csi_rows(NumCsiRows::from_human(1).unwrap())
55            .with_chan_estimation(NumSpaceTimeStreams::from_human(1).unwrap()),
56        asel_cap: AselCapability(0),
57    }
58}
59
60pub fn fake_ht_operation() -> HtOperation {
61    HtOperation {
62        primary_channel: 36,
63        ht_op_info: HtOpInfo::new()
64            .with_secondary_chan_offset(SecChanOffset::SECONDARY_ABOVE)
65            .with_sta_chan_width(StaChanWidth::ANY)
66            .with_rifs_mode_permitted(false)
67            .with_ht_protection(HtProtection::NONE)
68            .with_nongreenfield_present(true)
69            .with_obss_non_ht_stas_present(true)
70            .with_center_freq_seg2(0)
71            .with_dual_beacon(false)
72            .with_dual_cts_protection(false)
73            .with_stbc_beacon(false)
74            .with_lsig_txop_protection(false)
75            .with_pco_active(false)
76            .with_pco_phase(PcoPhase::TWENTY_MHZ),
77        basic_ht_mcs_set: fake_supported_mcs_set(),
78    }
79}
80
81pub fn fake_vht_capabilities() -> VhtCapabilities {
82    VhtCapabilities {
83        vht_cap_info: VhtCapabilitiesInfo(0)
84            .with_max_mpdu_len(MaxMpduLen::OCTECTS_7991)
85            .with_supported_cbw_set(0)
86            .with_rx_ldpc(true)
87            .with_sgi_cbw80(true)
88            .with_sgi_cbw160(false)
89            .with_tx_stbc(true)
90            .with_rx_stbc(2)
91            .with_su_bfer(false)
92            .with_su_bfee(false)
93            .with_bfee_sts(0)
94            .with_num_sounding(0)
95            .with_mu_bfer(false)
96            .with_mu_bfee(false)
97            .with_txop_ps(false)
98            .with_htc_vht(false)
99            .with_max_ampdu_exponent(MaxAmpduExponent(2))
100            .with_link_adapt(VhtLinkAdaptation::NO_FEEDBACK)
101            .with_rx_ant_pattern(true)
102            .with_tx_ant_pattern(true)
103            .with_ext_nss_bw(2),
104        vht_mcs_nss: VhtMcsNssSet(0)
105            .with_rx_max_mcs_raw(0x0001020300010203)
106            .with_rx_max_data_rate(867)
107            .with_max_nsts(2)
108            .with_tx_max_mcs_raw(0x0001020300010203)
109            .with_tx_max_data_rate(867)
110            .with_ext_nss_bw(false),
111    }
112}
113
114pub fn fake_vht_operation() -> VhtOperation {
115    VhtOperation {
116        vht_cbw: VhtChannelBandwidth::CBW_80_160_80P80,
117        center_freq_seg0: 42,
118        center_freq_seg1: 0,
119        basic_mcs_nss: VhtMcsNssMap(0x1b1b),
120    }
121}
122
123pub fn fake_ht_cap_bytes() -> [u8; std::mem::size_of::<HtCapabilities>()] {
124    // Safe to unwrap because the size matches the IE.
125    fake_ht_capabilities().as_bytes().try_into().unwrap()
126}
127
128pub fn fake_ht_op_bytes() -> [u8; std::mem::size_of::<HtOperation>()] {
129    // Safe to unwrap because the size matches the IE.
130    fake_ht_operation().as_bytes().try_into().unwrap()
131}
132
133pub fn fake_vht_cap_bytes() -> [u8; std::mem::size_of::<VhtCapabilities>()] {
134    // Safe to unwrap because the size matches the IE.
135    fake_vht_capabilities().as_bytes().try_into().unwrap()
136}
137
138pub fn fake_vht_op_bytes() -> [u8; std::mem::size_of::<VhtOperation>()] {
139    // Safe to unwrap because the size matches the IE.
140    fake_vht_operation().as_bytes().try_into().unwrap()
141}
142
143pub fn fake_wpa_ie() -> WpaIe {
144    WpaIe {
145        unicast_cipher_list: vec![cipher::Cipher { oui: Oui::MSFT, suite_type: cipher::TKIP }],
146        akm_list: vec![akm::Akm { oui: Oui::MSFT, suite_type: akm::PSK }],
147        multicast_cipher: cipher::Cipher { oui: Oui::MSFT, suite_type: cipher::TKIP },
148    }
149}
150
151pub fn get_vendor_ie_bytes_for_wpa_ie(wpa_ie: &WpaIe) -> Result<Vec<u8>, BufferTooSmall> {
152    let mut buf = vec![];
153    write_wpa1_ie(&mut buf, &wpa_ie).map(|_| buf)
154}
155
156pub fn get_rsn_ie_bytes(rsne: &Rsne) -> Vec<u8> {
157    let mut buf = Vec::with_capacity(rsne.len());
158    rsne.write_into(&mut buf).expect("error writing RSNE into buffer");
159    buf
160}
161
162// The returned ProbeRespWsc corresponds to the bytes returned by
163// fake_probe_resp_wsc_ie_bytes().
164pub fn fake_probe_resp_wsc_ie() -> ProbeRespWsc {
165    ProbeRespWsc {
166        version: 0x10,
167        wps_state: WpsState::CONFIGURED,
168        ap_setup_locked: true,
169        selected_reg: false,
170        selected_reg_config_methods: None,
171        response_type: 0x03,
172        uuid_e: [
173            0x3b, 0x3b, 0xe3, 0x66, 0x80, 0x84, 0x4b, 0x03, 0xbb, 0x66, 0x45, 0x2a, 0xf3, 0x00,
174            0x59, 0x22,
175        ],
176        manufacturer: b"ASUSTek Computer Inc.".to_vec(),
177        model_name: b"RT-AC58U".to_vec(),
178        model_number: b"123".to_vec(),
179        serial_number: b"12345".to_vec(),
180        primary_device_type: [0x00, 0x06, 0x00, 0x50, 0xf2, 0x04, 0x00, 0x01],
181        device_name: b"ASUS Router".to_vec(),
182        config_methods: [0x20, 0x0c],
183        rf_bands: None,
184        vendor_ext: vec![0x00, 0x37, 0x2a, 0x00, 0x01, 0x20],
185    }
186}
187
188// The bytes returned correspond to the ProbeRespWsc returned by
189// fake_probe_resp_wsc_ie().
190pub fn fake_probe_resp_wsc_ie_bytes() -> Vec<u8> {
191    #[rustfmt::skip]
192    let bytes = vec![
193        0x10, 0x4a, 0x00, 0x01, 0x10, // Version
194        0x10, 0x44, 0x00, 0x01, 0x02, // WiFi Protected Setup State
195        0x10, 0x57, 0x00, 0x01, 0x01, // AP Setup Locked
196        0x10, 0x3b, 0x00, 0x01, 0x03, // Response Type
197        // UUID-E
198        0x10, 0x47, 0x00, 0x10,
199        0x3b, 0x3b, 0xe3, 0x66, 0x80, 0x84, 0x4b, 0x03,
200        0xbb, 0x66, 0x45, 0x2a, 0xf3, 0x00, 0x59, 0x22,
201        // Manufacturer
202        0x10, 0x21, 0x00, 0x15,
203        0x41, 0x53, 0x55, 0x53, 0x54, 0x65, 0x6b, 0x20, 0x43, 0x6f, 0x6d, 0x70,
204        0x75, 0x74, 0x65, 0x72, 0x20, 0x49, 0x6e, 0x63, 0x2e,
205        // Model name
206        0x10, 0x23, 0x00, 0x08, 0x52, 0x54, 0x2d, 0x41, 0x43, 0x35, 0x38, 0x55,
207        // Model number
208        0x10, 0x24, 0x00, 0x03, 0x31, 0x32, 0x33,
209        // Serial number
210        0x10, 0x42, 0x00, 0x05, 0x31, 0x32, 0x33, 0x34, 0x35,
211        // Primary device type
212        0x10, 0x54, 0x00, 0x08, 0x00, 0x06, 0x00, 0x50, 0xf2, 0x04, 0x00, 0x01,
213        // Device name
214        0x10, 0x11, 0x00, 0x0b,
215        0x41, 0x53, 0x55, 0x53, 0x20, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72,
216        // Config methods
217        0x10, 0x08, 0x00, 0x02, 0x20, 0x0c,
218        // Vendor extension
219        0x10, 0x49, 0x00, 0x06, 0x00, 0x37, 0x2a, 0x00, 0x01, 0x20,
220    ];
221    bytes
222}
223
224pub fn get_vendor_ie_bytes_for_wsc_ie(wsc_ie_bytes: &[u8]) -> Result<Vec<u8>, BufferTooSmall> {
225    let mut buf = vec![];
226    write_wsc_ie(&mut buf, &wsc_ie_bytes).map(|_| buf)
227}
228
229pub fn fake_wmm_param() -> WmmParam {
230    WmmParam {
231        wmm_info: WmmInfo(0).with_ap_wmm_info(ApWmmInfo(0).with_uapsd(true)),
232        _reserved: 0,
233        ac_be_params: WmmAcParams {
234            aci_aifsn: WmmAciAifsn(0).with_aifsn(3).with_aci(0),
235            ecw_min_max: EcwMinMax(0).with_ecw_min(4).with_ecw_max(10),
236            txop_limit: 0,
237        },
238        ac_bk_params: WmmAcParams {
239            aci_aifsn: WmmAciAifsn(0).with_aifsn(7).with_aci(1),
240            ecw_min_max: EcwMinMax(0).with_ecw_min(4).with_ecw_max(10),
241            txop_limit: 0,
242        },
243        ac_vi_params: WmmAcParams {
244            aci_aifsn: WmmAciAifsn(0).with_aifsn(2).with_aci(2),
245            ecw_min_max: EcwMinMax(0).with_ecw_min(3).with_ecw_max(4),
246            txop_limit: 94,
247        },
248        ac_vo_params: WmmAcParams {
249            aci_aifsn: WmmAciAifsn(0).with_aifsn(2).with_aci(3),
250            ecw_min_max: EcwMinMax(0).with_ecw_min(2).with_ecw_max(3),
251            txop_limit: 47,
252        },
253    }
254}
255
256pub fn fake_owe_transition_ie() -> Vec<u8> {
257    vec![
258        0xdd, // Element ID
259        0x12, // Length
260        0x50, 0x6f, 0x9a, // OUI: WFA
261        0x1c, // OI Type: OWE Transition
262        0x13, 0x37, 0x42, 0x42, 0x13, 0x37, // BSSID
263        0x07, // SSID length
264        0x66, 0x6f, 0x6f, 0x2d, 0x6f, 0x77, 0x65, // SSID "foo-owe"
265    ]
266}
267
268pub fn fake_owe_transition() -> OweTransition {
269    OweTransition {
270        bssid: Bssid::from([0x13, 0x37, 0x42, 0x42, 0x13, 0x37]),
271        ssid: Ssid::try_from(b"foo-owe".to_vec()).unwrap(),
272        band_and_channel: None,
273    }
274}