blob: a19092012f3f5a2bd545ecb5a6c88e3dc41f6280 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "test_bss.h"
#include "mock_device.h"
#include <wlan/common/buffer_writer.h>
#include <wlan/common/channel.h>
#include <wlan/common/write_element.h>
#include <wlan/mlme/ap/bss_interface.h>
#include <wlan/mlme/debug.h>
#include <wlan/mlme/mac_frame.h>
#include <wlan/mlme/packet.h>
#include <wlan/mlme/rates_elements.h>
#include <wlan/mlme/service.h>
#include <fbl/unique_ptr.h>
#include <fuchsia/wlan/mlme/c/fidl.h>
#include <fuchsia/wlan/mlme/cpp/fidl.h>
#include <gtest/gtest.h>
namespace wlan {
namespace wlan_common = ::fuchsia::wlan::common;
namespace wlan_mlme = ::fuchsia::wlan::mlme;
void WriteTim(BufferWriter* w, const PsCfg& ps_cfg) {
size_t bitmap_len = ps_cfg.GetTim()->BitmapLen();
uint8_t bitmap_offset = ps_cfg.GetTim()->BitmapOffset();
TimHeader hdr;
hdr.dtim_count = ps_cfg.dtim_count();
hdr.dtim_period = ps_cfg.dtim_period();
ZX_DEBUG_ASSERT(hdr.dtim_count != hdr.dtim_period);
if (hdr.dtim_count == hdr.dtim_period) { warnf("illegal DTIM state"); }
hdr.bmp_ctrl.set_offset(bitmap_offset);
if (ps_cfg.IsDtim()) { hdr.bmp_ctrl.set_group_traffic_ind(ps_cfg.GetTim()->HasGroupTraffic()); }
common::WriteTim(w, hdr, {ps_cfg.GetTim()->BitmapData(), bitmap_len});
}
void WriteCountry(BufferWriter* w, const wlan_channel_t chan) {
const Country kCountry = {{'U', 'S', ' '}};
std::vector<SubbandTriplet> subbands;
// TODO(porce): Read from the AP's regulatory domain
if (wlan::common::Is2Ghz(chan)) {
subbands.push_back({1, 11, 36});
} else {
subbands.push_back({36, 4, 36});
subbands.push_back({52, 4, 30});
subbands.push_back({100, 12, 30});
subbands.push_back({149, 5, 36});
}
common::WriteCountry(w, kCountry, subbands);
}
wlan_mlme::BSSDescription CreateBssDescription(bool rsn, wlan_channel_t chan) {
common::MacAddr bssid(kBssid1);
wlan_mlme::BSSDescription bss_desc;
std::memcpy(bss_desc.bssid.mutable_data(), bssid.byte, common::kMacAddrLen);
std::vector<uint8_t> ssid(kSsid, kSsid + sizeof(kSsid));
bss_desc.ssid = std::move(ssid);
bss_desc.bss_type = wlan_mlme::BSSTypes::INFRASTRUCTURE;
bss_desc.beacon_period = kBeaconPeriodTu;
bss_desc.dtim_period = kDtimPeriodTu;
bss_desc.timestamp = 0;
bss_desc.local_time = 0;
bss_desc.basic_rate_set.resize(0);
bss_desc.op_rate_set.resize(0);
wlan_mlme::CapabilityInfo cap;
cap.ess = true;
cap.short_preamble = true;
bss_desc.cap = cap;
if (rsn) {
bss_desc.rsn.reset(std::vector<uint8_t>(kRsne, kRsne + sizeof(kRsne)));
} else {
bss_desc.rsn.reset();
}
bss_desc.rcpi_dbmh = 0;
bss_desc.rsni_dbh = 0;
bss_desc.ht_cap.reset();
bss_desc.ht_op.reset();
bss_desc.vht_cap.reset();
bss_desc.vht_op.reset();
bss_desc.chan.cbw = static_cast<wlan_common::CBW>(chan.cbw);
bss_desc.chan.primary = chan.primary;
bss_desc.rssi_dbm = -35;
return bss_desc;
}
MlmeMsg<wlan_mlme::ScanRequest> CreateScanRequest(uint32_t max_channel_time) {
auto req = wlan_mlme::ScanRequest::New();
req->txn_id = 0;
req->bss_type = wlan_mlme::BSSTypes::ANY_BSS;
std::memcpy(req->bssid.mutable_data(), kBroadcastBssid, sizeof(kBroadcastBssid));
req->ssid = {0};
req->scan_type = wlan_mlme::ScanTypes::PASSIVE;
req->channel_list.reset({11});
req->max_channel_time = max_channel_time;
return {std::move(*req), fuchsia_wlan_mlme_MLMEStartScanOrdinal};
}
MlmeMsg<wlan_mlme::StartRequest> CreateStartRequest(bool protected_ap) {
auto req = wlan_mlme::StartRequest::New();
std::vector<uint8_t> ssid(kSsid, kSsid + sizeof(kSsid));
req->ssid = std::move(ssid);
req->bss_type = wlan_mlme::BSSTypes::INFRASTRUCTURE;
req->beacon_period = kBeaconPeriodTu;
req->dtim_period = kDtimPeriodTu;
req->channel = kBssChannel.primary;
req->mesh_id.resize(0);
if (protected_ap) { req->rsne.reset(std::vector<uint8_t>(kRsne, kRsne + sizeof(kRsne))); }
return {std::move(*req), fuchsia_wlan_mlme_MLMEStartReqOrdinal};
}
MlmeMsg<wlan_mlme::StopRequest> CreateStopRequest() {
auto req = wlan_mlme::StopRequest::New();
req->ssid = std::vector<uint8_t>(kSsid, kSsid + sizeof(kSsid));
return {std::move(*req), fuchsia_wlan_mlme_MLMEStopReqOrdinal};
}
MlmeMsg<wlan_mlme::JoinRequest> CreateJoinRequest(bool rsn) {
auto req = wlan_mlme::JoinRequest::New();
req->join_failure_timeout = kJoinTimeout;
req->nav_sync_delay = 20;
req->op_rate_set = {12, 24, 48};
req->phy = wlan::common::ToFidl(kBssPhy);
req->cbw = wlan::common::ToFidl(kBssChannel).cbw;
req->selected_bss = CreateBssDescription(rsn);
req->selected_bss.op_rate_set = {12, 24, 48};
return {std::move(*req), fuchsia_wlan_mlme_MLMEJoinReqOrdinal};
}
MlmeMsg<wlan_mlme::AuthenticateRequest> CreateAuthRequest() {
common::MacAddr bssid(kBssid1);
auto req = wlan_mlme::AuthenticateRequest::New();
std::memcpy(req->peer_sta_address.mutable_data(), bssid.byte, common::kMacAddrLen);
req->auth_failure_timeout = kAuthTimeout;
req->auth_type = wlan_mlme::AuthenticationTypes::OPEN_SYSTEM;
return {std::move(*req), fuchsia_wlan_mlme_MLMEAuthenticateReqOrdinal};
}
MlmeMsg<wlan_mlme::DeauthenticateRequest> CreateDeauthRequest(common::MacAddr peer_addr,
wlan_mlme::ReasonCode reason_code) {
auto req = wlan_mlme::DeauthenticateRequest::New();
std::memcpy(req->peer_sta_address.mutable_data(), peer_addr.byte, common::kMacAddrLen);
req->reason_code = reason_code;
return {std::move(*req), fuchsia_wlan_mlme_MLMEDeauthenticateReqOrdinal};
}
MlmeMsg<wlan_mlme::AuthenticateResponse> CreateAuthResponse(
common::MacAddr client_addr, wlan_mlme::AuthenticateResultCodes result_code) {
auto resp = wlan_mlme::AuthenticateResponse::New();
std::memcpy(resp->peer_sta_address.mutable_data(), client_addr.byte, common::kMacAddrLen);
resp->result_code = result_code;
return {std::move(*resp), fuchsia_wlan_mlme_MLMEAuthenticateRespOrdinal};
}
MlmeMsg<wlan_mlme::AssociateRequest> CreateAssocRequest(bool rsn) {
common::MacAddr bssid(kBssid1);
auto req = wlan_mlme::AssociateRequest::New();
std::memcpy(req->peer_sta_address.mutable_data(), bssid.byte, common::kMacAddrLen);
if (rsn) {
req->rsn.reset(std::vector<uint8_t>(kRsne, kRsne + sizeof(kRsne)));
} else {
req->rsn.reset();
}
return {std::move(*req), fuchsia_wlan_mlme_MLMEAssociateReqOrdinal};
}
MlmeMsg<wlan_mlme::AssociateResponse> CreateAssocResponse(
common::MacAddr client_addr, wlan_mlme::AssociateResultCodes result_code, uint16_t aid) {
auto resp = wlan_mlme::AssociateResponse::New();
std::memcpy(resp->peer_sta_address.mutable_data(), client_addr.byte, common::kMacAddrLen);
resp->result_code = result_code;
resp->association_id = aid;
return {std::move(*resp), fuchsia_wlan_mlme_MLMEAssociateRespOrdinal};
}
MlmeMsg<wlan_mlme::EapolRequest> CreateEapolRequest(common::MacAddr src_addr,
common::MacAddr dst_addr) {
auto req = wlan_mlme::EapolRequest::New();
std::memcpy(req->src_addr.mutable_data(), src_addr.byte, common::kMacAddrLen);
std::memcpy(req->dst_addr.mutable_data(), dst_addr.byte, common::kMacAddrLen);
std::vector<uint8_t> eapol_pdu(kEapolPdu, kEapolPdu + sizeof(kEapolPdu));
req->data = std::move(eapol_pdu);
return {std::move(*req), fuchsia_wlan_mlme_MLMEEapolReqOrdinal};
}
MlmeMsg<wlan_mlme::SetKeysRequest> CreateSetKeysRequest(common::MacAddr addr,
std::vector<uint8_t> key_data,
wlan_mlme::KeyType key_type) {
wlan_mlme::SetKeyDescriptor key;
key.key = key_data;
key.key_id = 1;
key.key_type = key_type;
std::memcpy(key.address.mutable_data(), addr.byte, sizeof(addr));
std::memcpy(key.cipher_suite_oui.mutable_data(), kCipherOui, sizeof(kCipherOui));
key.cipher_suite_type = kCipherSuiteType;
std::vector<wlan_mlme::SetKeyDescriptor> keylist;
keylist.emplace_back(std::move(key));
auto req = wlan_mlme::SetKeysRequest::New();
req->keylist = std::move(keylist);
return {std::move(*req), fuchsia_wlan_mlme_MLMESetKeysReqOrdinal};
}
MlmeMsg<wlan_mlme::SetControlledPortRequest> CreateSetCtrlPortRequest(
common::MacAddr peer_addr, wlan_mlme::ControlledPortState state) {
auto req = wlan_mlme::SetControlledPortRequest::New();
std::memcpy(req->peer_sta_address.mutable_data(), peer_addr.byte, sizeof(peer_addr));
req->state = state;
return {std::move(*req), fuchsia_wlan_mlme_MLMESetKeysReqOrdinal};
}
fbl::unique_ptr<Packet> CreateBeaconFrame(common::MacAddr bssid) {
constexpr size_t ie_len = 256;
constexpr size_t max_frame_len = MgmtFrameHeader::max_len() + Beacon::max_len() + ie_len;
auto packet = GetWlanPacket(max_frame_len);
ZX_DEBUG_ASSERT(packet != nullptr);
BufferWriter w(*packet);
auto mgmt_hdr = w.Write<MgmtFrameHeader>();
mgmt_hdr->fc.set_type(FrameType::kManagement);
mgmt_hdr->fc.set_subtype(ManagementSubtype::kBeacon);
mgmt_hdr->addr1 = common::kBcastMac;
mgmt_hdr->addr2 = bssid;
mgmt_hdr->addr3 = bssid;
auto bcn = w.Write<Beacon>();
bcn->beacon_interval = kBeaconPeriodTu;
bcn->timestamp = 0;
bcn->cap.set_ess(1);
bcn->cap.set_short_preamble(1);
BufferWriter elem_w(w.RemainingBuffer());
common::WriteSsid(&elem_w, kSsid);
RatesWriter rates_writer{kSupportedRates};
rates_writer.WriteSupportedRates(&elem_w);
common::WriteDsssParamSet(&elem_w, kBssChannel.primary);
WriteCountry(&elem_w, kBssChannel);
rates_writer.WriteExtendedSupportedRates(&elem_w);
packet->set_len(w.WrittenBytes() + elem_w.WrittenBytes());
wlan_rx_info_t rx_info{.rx_flags = 0};
packet->CopyCtrlFrom(rx_info);
return packet;
}
fbl::unique_ptr<Packet> CreateProbeRequest() {
common::MacAddr bssid(kBssid1);
common::MacAddr client(kClientAddress);
constexpr size_t ie_len = 256;
constexpr size_t max_frame_len = MgmtFrameHeader::max_len() + ProbeRequest::max_len() + ie_len;
auto packet = GetWlanPacket(max_frame_len);
ZX_DEBUG_ASSERT(packet != nullptr);
BufferWriter w(*packet);
auto mgmt_hdr = w.Write<MgmtFrameHeader>();
mgmt_hdr->fc.set_type(FrameType::kManagement);
mgmt_hdr->fc.set_subtype(ManagementSubtype::kBeacon);
mgmt_hdr->addr1 = client;
mgmt_hdr->addr2 = bssid;
mgmt_hdr->addr3 = bssid;
w.Write<ProbeRequest>();
BufferWriter elem_w(w.RemainingBuffer());
common::WriteSsid(&elem_w, kSsid);
RatesWriter rates_writer{kSupportedRates};
rates_writer.WriteSupportedRates(&elem_w);
rates_writer.WriteExtendedSupportedRates(&elem_w);
common::WriteDsssParamSet(&elem_w, kBssChannel.primary);
packet->set_len(w.WrittenBytes() + elem_w.WrittenBytes());
wlan_rx_info_t rx_info{.rx_flags = 0};
packet->CopyCtrlFrom(rx_info);
return packet;
}
fbl::unique_ptr<Packet> CreateAuthReqFrame(common::MacAddr client_addr) {
common::MacAddr bssid(kBssid1);
constexpr size_t max_frame_len = MgmtFrameHeader::max_len() + Authentication::max_len();
auto packet = GetWlanPacket(max_frame_len);
ZX_DEBUG_ASSERT(packet != nullptr);
BufferWriter w(*packet);
auto mgmt_hdr = w.Write<MgmtFrameHeader>();
mgmt_hdr->fc.set_type(FrameType::kManagement);
mgmt_hdr->fc.set_subtype(ManagementSubtype::kAuthentication);
mgmt_hdr->addr1 = bssid;
mgmt_hdr->addr2 = client_addr;
mgmt_hdr->addr3 = bssid;
auto auth = w.Write<Authentication>();
auth->auth_algorithm_number = AuthAlgorithm::kOpenSystem;
auth->auth_txn_seq_number = 1;
auth->status_code = 0; // Reserved: explicitly set to 0
packet->set_len(w.WrittenBytes());
wlan_rx_info_t rx_info{.rx_flags = 0};
packet->CopyCtrlFrom(rx_info);
return packet;
}
fbl::unique_ptr<Packet> CreateAuthRespFrame(AuthAlgorithm auth_algo) {
common::MacAddr bssid(kBssid1);
common::MacAddr client(kClientAddress);
constexpr size_t max_frame_len = MgmtFrameHeader::max_len() + Authentication::max_len();
auto packet = GetWlanPacket(max_frame_len);
ZX_DEBUG_ASSERT(packet != nullptr);
BufferWriter w(*packet);
auto mgmt_hdr = w.Write<MgmtFrameHeader>();
mgmt_hdr->fc.set_type(FrameType::kManagement);
mgmt_hdr->fc.set_subtype(ManagementSubtype::kAuthentication);
mgmt_hdr->addr1 = client;
mgmt_hdr->addr2 = bssid;
mgmt_hdr->addr3 = bssid;
auto auth = w.Write<Authentication>();
auth->auth_algorithm_number = auth_algo;
auth->auth_txn_seq_number = 2;
auth->status_code = status_code::kSuccess;
packet->set_len(w.WrittenBytes());
wlan_rx_info_t rx_info{.rx_flags = 0};
packet->CopyCtrlFrom(rx_info);
return packet;
}
fbl::unique_ptr<Packet> CreateDeauthFrame(common::MacAddr client_addr) {
common::MacAddr bssid(kBssid1);
constexpr size_t max_frame_len = MgmtFrameHeader::max_len() + Deauthentication::max_len();
auto packet = GetWlanPacket(max_frame_len);
ZX_DEBUG_ASSERT(packet != nullptr);
BufferWriter w(*packet);
auto mgmt_hdr = w.Write<MgmtFrameHeader>();
mgmt_hdr->fc.set_type(FrameType::kManagement);
mgmt_hdr->fc.set_subtype(ManagementSubtype::kDeauthentication);
mgmt_hdr->addr1 = bssid;
mgmt_hdr->addr2 = client_addr;
mgmt_hdr->addr3 = bssid;
w.Write<Deauthentication>()->reason_code = reason_code::ReasonCode::kLeavingNetworkDeauth;
packet->set_len(w.WrittenBytes());
wlan_rx_info_t rx_info{.rx_flags = 0};
packet->CopyCtrlFrom(rx_info);
return packet;
}
fbl::unique_ptr<Packet> CreateAssocReqFrame(common::MacAddr client_addr, Span<const uint8_t> ssid,
bool rsn) {
common::MacAddr bssid(kBssid1);
// arbitrarily large reserved len; will shrink down later
constexpr size_t ie_len = 1024;
constexpr size_t max_frame_len =
MgmtFrameHeader::max_len() + AssociationRequest::max_len() + ie_len;
auto packet = GetWlanPacket(max_frame_len);
ZX_DEBUG_ASSERT(packet != nullptr);
BufferWriter w(*packet);
auto mgmt_hdr = w.Write<MgmtFrameHeader>();
mgmt_hdr->fc.set_type(FrameType::kManagement);
mgmt_hdr->fc.set_subtype(ManagementSubtype::kAssociationRequest);
mgmt_hdr->addr1 = bssid;
mgmt_hdr->addr2 = client_addr;
mgmt_hdr->addr3 = bssid;
auto assoc = w.Write<AssociationRequest>();
CapabilityInfo cap = {};
cap.set_short_preamble(1);
cap.set_ess(1);
assoc->cap = cap;
assoc->listen_interval = kListenInterval;
BufferWriter elem_w(w.RemainingBuffer());
if (!ssid.empty()) { common::WriteSsid(&w, ssid); }
if (rsn) { w.Write(kRsne); }
packet->set_len(w.WrittenBytes() + elem_w.WrittenBytes());
wlan_rx_info_t rx_info{.rx_flags = 0};
packet->CopyCtrlFrom(rx_info);
return packet;
}
fbl::unique_ptr<Packet> CreateAssocRespFrame(const AssocContext& ap_assoc_ctx) {
common::MacAddr bssid(kBssid1);
common::MacAddr client(kClientAddress);
constexpr size_t reserved_ie_len = 256;
constexpr size_t max_frame_len =
MgmtFrameHeader::max_len() + AssociationResponse::max_len() + reserved_ie_len;
auto packet = GetWlanPacket(max_frame_len);
ZX_DEBUG_ASSERT(packet != nullptr);
// TODO(NET-2007): Implement a common frame builder
BufferWriter w(*packet);
auto mgmt_hdr = w.Write<MgmtFrameHeader>();
mgmt_hdr->fc.set_type(FrameType::kManagement);
mgmt_hdr->fc.set_subtype(ManagementSubtype::kAssociationResponse);
mgmt_hdr->addr1 = client;
mgmt_hdr->addr2 = bssid;
mgmt_hdr->addr3 = bssid;
auto assoc = w.Write<AssociationResponse>();
assoc->aid = kAid;
CapabilityInfo cap = {};
cap.set_short_preamble(1);
cap.set_ess(1);
assoc->cap = cap;
assoc->status_code = status_code::kSuccess;
BufferWriter elem_w(w.RemainingBuffer());
if (ap_assoc_ctx.ht_cap.has_value()) {
common::WriteHtCapabilities(&elem_w, ap_assoc_ctx.ht_cap.value());
}
if (ap_assoc_ctx.ht_op.has_value()) {
common::WriteHtOperation(&elem_w, ap_assoc_ctx.ht_op.value());
}
if (ap_assoc_ctx.vht_cap.has_value()) {
common::WriteVhtCapabilities(&elem_w, ap_assoc_ctx.vht_cap.value());
}
if (ap_assoc_ctx.vht_op.has_value()) {
common::WriteVhtOperation(&elem_w, ap_assoc_ctx.vht_op.value());
}
packet->set_len(w.WrittenBytes() + elem_w.WrittenBytes());
wlan_rx_info_t rx_info{.rx_flags = 0};
packet->CopyCtrlFrom(rx_info);
return packet;
}
fbl::unique_ptr<Packet> CreateDisassocFrame(common::MacAddr client_addr) {
common::MacAddr bssid(kBssid1);
constexpr size_t max_frame_len = MgmtFrameHeader::max_len() + Disassociation::max_len();
auto packet = GetWlanPacket(max_frame_len);
ZX_DEBUG_ASSERT(packet != nullptr);
BufferWriter w(*packet);
auto mgmt_hdr = w.Write<MgmtFrameHeader>();
mgmt_hdr->fc.set_type(FrameType::kManagement);
mgmt_hdr->fc.set_subtype(ManagementSubtype::kDisassociation);
mgmt_hdr->addr1 = bssid;
mgmt_hdr->addr2 = client_addr;
mgmt_hdr->addr3 = bssid;
w.Write<Disassociation>()->reason_code = reason_code::ReasonCode::kLeavingNetworkDisassoc;
packet->set_len(w.WrittenBytes());
wlan_rx_info_t rx_info{.rx_flags = 0};
packet->CopyCtrlFrom(rx_info);
return packet;
}
fbl::unique_ptr<Packet> CreateDataFrame(Span<const uint8_t> payload) {
common::MacAddr bssid(kBssid1);
common::MacAddr client(kClientAddress);
const size_t buf_len = DataFrameHeader::max_len() + LlcHeader::max_len() + payload.size_bytes();
auto packet = GetWlanPacket(buf_len);
ZX_DEBUG_ASSERT(packet != nullptr);
BufferWriter w(*packet);
auto data_hdr = w.Write<DataFrameHeader>();
data_hdr->fc.set_type(FrameType::kData);
data_hdr->fc.set_subtype(DataSubtype::kDataSubtype);
data_hdr->fc.set_from_ds(1);
data_hdr->addr1 = bssid;
data_hdr->addr2 = bssid;
data_hdr->addr3 = client;
data_hdr->sc.set_val(42);
auto llc_hdr = w.Write<LlcHeader>();
llc_hdr->dsap = kLlcSnapExtension;
llc_hdr->ssap = kLlcSnapExtension;
llc_hdr->control = kLlcUnnumberedInformation;
std::memcpy(llc_hdr->oui, kLlcOui, sizeof(llc_hdr->oui));
llc_hdr->protocol_id = 42;
w.Write(payload);
packet->set_len(w.WrittenBytes());
wlan_rx_info_t rx_info{.rx_flags = 0};
packet->CopyCtrlFrom(rx_info);
return packet;
}
fbl::unique_ptr<Packet> CreateAmsduDataFramePacket(
const std::vector<Span<const uint8_t>>& payloads) {
common::MacAddr bssid(kBssid1);
common::MacAddr client(kClientAddress);
const uint8_t padding[]{0, 0, 0};
Span<const uint8_t> padding_span(padding);
size_t buf_len = DataFrameHeader::max_len();
for (auto span : payloads) {
buf_len += AmsduSubframeHeader::max_len() + LlcHeader::max_len() + span.size_bytes() + 3;
};
auto packet = GetWlanPacket(buf_len);
ZX_DEBUG_ASSERT(packet != nullptr);
BufferWriter w(*packet);
auto data_hdr = w.Write<DataFrameHeader>();
data_hdr->fc.set_type(FrameType::kData);
data_hdr->fc.set_subtype(DataSubtype::kQosdata);
data_hdr->fc.set_from_ds(1);
data_hdr->addr1 = bssid;
data_hdr->addr2 = bssid;
data_hdr->addr3 = client;
data_hdr->sc.set_val(42);
auto qos_control = w.Write<QosControl>();
qos_control->set_amsdu_present(1);
for (auto i = 0ULL; i < payloads.size(); ++i) {
auto msdu_hdr = w.Write<AmsduSubframeHeader>();
msdu_hdr->da = client;
msdu_hdr->sa = bssid;
msdu_hdr->msdu_len_be = htobe16(LlcHeader::max_len() + payloads[i].size_bytes());
auto llc_hdr = w.Write<LlcHeader>();
llc_hdr->dsap = kLlcSnapExtension;
llc_hdr->ssap = kLlcSnapExtension;
llc_hdr->control = kLlcUnnumberedInformation;
std::memcpy(llc_hdr->oui, kLlcOui, sizeof(llc_hdr->oui));
llc_hdr->protocol_id = 42;
w.Write(payloads[i]);
if (i != payloads.size() - 1) {
w.Write(padding_span.subspan(0, (6 - payloads[i].size_bytes()) % 4));
}
}
packet->set_len(w.WrittenBytes());
wlan_rx_info_t rx_info{.rx_flags = 0};
packet->CopyCtrlFrom(rx_info);
return packet;
}
DataFrame<> CreateNullDataFrame() {
common::MacAddr bssid(kBssid1);
common::MacAddr client(kClientAddress);
auto packet = GetWlanPacket(DataFrameHeader::max_len());
ZX_DEBUG_ASSERT(packet != nullptr);
BufferWriter w(*packet);
auto data_hdr = w.Write<DataFrameHeader>();
data_hdr->fc.set_type(FrameType::kData);
data_hdr->fc.set_subtype(DataSubtype::kNull);
data_hdr->fc.set_from_ds(1);
data_hdr->addr1 = client;
data_hdr->addr2 = bssid;
data_hdr->addr3 = bssid;
data_hdr->sc.set_val(42);
packet->set_len(w.WrittenBytes());
wlan_rx_info_t rx_info{.rx_flags = 0};
packet->CopyCtrlFrom(rx_info);
return DataFrame<>(std::move(packet));
}
fbl::unique_ptr<Packet> CreateEthFrame(Span<const uint8_t> payload) {
common::MacAddr bssid(kBssid1);
common::MacAddr client(kClientAddress);
size_t buf_len = EthernetII::max_len() + payload.size_bytes();
auto packet = GetEthPacket(buf_len);
ZX_DEBUG_ASSERT(packet != nullptr);
BufferWriter w(*packet);
auto eth_hdr = w.Write<EthernetII>();
eth_hdr->src = client;
eth_hdr->dest = bssid;
eth_hdr->ether_type = 2;
w.Write(payload);
return packet;
}
} // namespace wlan