blob: 6f2665cb2581a5deff346ae565bb1037b314d74e [file] [log] [blame]
// Copyright 2019 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.
#ifndef SRC_CONNECTIVITY_WLAN_DRIVERS_TESTING_LIB_SIM_FAKE_AP_SIM_FAKE_AP_H_
#define SRC_CONNECTIVITY_WLAN_DRIVERS_TESTING_LIB_SIM_FAKE_AP_SIM_FAKE_AP_H_
#include <fuchsia/wlan/ieee80211/cpp/fidl.h>
#include <lib/zx/time.h>
#include <netinet/if_ether.h>
#include <stdint.h>
#include <zircon/types.h>
#include <array>
#include <functional>
#include <list>
#include <wlan/protocol/ieee80211.h>
#include "src/connectivity/wlan/drivers/testing/lib/sim-env/sim-env.h"
#include "src/connectivity/wlan/drivers/testing/lib/sim-env/sim-frame.h"
#include "src/connectivity/wlan/drivers/testing/lib/sim-env/sim-sta-ifc.h"
namespace wlan::simulation {
// To simulate an AP. Only keep minimum information for sim-fw to generate
// response for driver.
//
class FakeAp : public StationIfc {
public:
// How to handle an association request
enum AssocHandling { ASSOC_ALLOWED, ASSOC_IGNORED, ASSOC_REFUSED_TEMPORARILY, ASSOC_REFUSED };
struct Security {
enum SimAuthType auth_handling_mode = AUTH_TYPE_OPEN;
enum ieee80211_cipher_suite cipher_suite;
static constexpr size_t kMaxKeyLen = 32;
size_t key_len;
std::array<uint8_t, kMaxKeyLen> key;
enum SimSecProtoType sec_type = SEC_PROTO_TYPE_OPEN;
// TODO (fxb/61139): Remove this field which is currently used to
// determine success or failure of a simulated authentication
// out of band.
bool expect_challenge_failure = false;
};
struct Client {
// AUTHENTICATING is the status where AP has sent out second auth frame, and waiting for the
// third, this only apply to AUTH_SHARED mode.
enum Status { NOT_AUTHENTICATED, AUTHENTICATING, AUTHENTICATED, ASSOCIATED };
Client(common::MacAddr mac_addr, Status status) : mac_addr_(mac_addr), status_(status) {}
common::MacAddr mac_addr_;
Status status_;
};
FakeAp() = delete;
explicit FakeAp(Environment* environ) : environment_(environ) { environ->AddStation(this); }
FakeAp(Environment* environ, const common::MacAddr& bssid, const wlan_ssid_t& ssid,
const wlan_channel_t chan)
: environment_(environ), bssid_(bssid), ssid_(ssid) {
environ->AddStation(this);
tx_info_.channel = chan;
beacon_state_.beacon_frame_.bssid_ = bssid;
beacon_state_.beacon_frame_.AddSsidIe(ssid);
// By default, assume AP is part of an infrastructure network
beacon_state_.beacon_frame_.capability_info_.set_ibss(0);
beacon_state_.beacon_frame_.capability_info_.set_ess(1);
}
~FakeAp() { environment_->RemoveStation(this); }
void SetChannel(const wlan_channel_t& channel);
void SetBssid(const common::MacAddr& bssid);
void SetSsid(const wlan_ssid_t& ssid);
void SetCsaBeaconInterval(zx::duration interval);
wlan_channel_t GetChannel() const { return tx_info_.channel; }
common::MacAddr GetBssid() const { return bssid_; }
wlan_ssid_t GetSsid() const { return ssid_; }
uint32_t GetNumAssociatedClient() const;
// Will we receive a message sent on the specified channel?
bool CanReceiveChannel(const wlan_channel_t& channel);
// When this is not called, the default is open network.
zx_status_t SetSecurity(struct Security sec);
// Start beaconing. Sends first beacon immediately and schedules beacons to occur every
// beacon_period until disabled.
void EnableBeacon(zx::duration beacon_period);
// Stop beaconing.
void DisableBeacon();
// Specify how to handle association requests
void SetAssocHandling(enum AssocHandling mode);
// Disassociate a Station
zx_status_t DisassocSta(const common::MacAddr& sta_mac, uint16_t reason);
// Beacon-specific error injection.
// The beacon_mutator functor will be applied to each beacon frame before transmission.
void AddErrInjBeacon(std::function<SimBeaconFrame(const SimBeaconFrame&)> beacon_mutator);
void DelErrInjBeacon();
bool CheckIfErrInjBeaconEnabled() const;
// StationIfc operations - these are the functions that allow the simulated AP to be used
// inside of a sim-env environment.
void Rx(std::shared_ptr<const SimFrame> frame, std::shared_ptr<const WlanRxInfo> info) override;
private:
void CancelNotification(uint64_t id);
std::shared_ptr<Client> AddClient(common::MacAddr mac_addr);
std::shared_ptr<Client> FindClient(common::MacAddr mac_addr);
void RemoveClient(common::MacAddr mac_addr);
void RxMgmtFrame(std::shared_ptr<const SimManagementFrame> mgmt_frame);
void RxDataFrame(std::shared_ptr<const SimDataFrame> data_frame);
void ScheduleNextBeacon();
void ScheduleAssocResp(::fuchsia::wlan::ieee80211::StatusCode status, const common::MacAddr& dst);
void ScheduleProbeResp(const common::MacAddr& dst);
void ScheduleAuthResp(std::shared_ptr<const SimAuthFrame> auth_frame_in,
::fuchsia::wlan::ieee80211::StatusCode status);
void ScheduleQosData(bool toDS, bool fromDS, const common::MacAddr& addr1,
const common::MacAddr& addr2, const common::MacAddr& addr3,
const std::vector<uint8_t>& payload);
// Event handlers
void HandleBeaconNotification();
void HandleStopCsaBeaconNotification();
void HandleAssocRespNotification(::fuchsia::wlan::ieee80211::StatusCode status,
common::MacAddr dst);
void HandleProbeRespNotification(common::MacAddr dst);
void HandleAuthRespNotification(SimAuthFrame auth_resp_frame);
void HandleQosDataNotification(bool toDS, bool fromDS, const common::MacAddr& addr1,
const common::MacAddr& addr2, const common::MacAddr& addr3,
const std::vector<uint8_t>& payload);
// The environment in which this fake AP is operating.
Environment* environment_;
// meta information needed for sending transmissions
simulation::WlanTxInfo tx_info_;
common::MacAddr bssid_;
wlan_ssid_t ssid_;
struct Security security_ = {.cipher_suite = IEEE80211_CIPHER_SUITE_NONE};
struct BeaconState {
// Are we currently emitting beacons?
bool is_beaconing = false;
// Are we waiting for the execution of scheduled channel switch announcement?
bool is_switching_channel = false;
// This is the channel AP about to change to
wlan_channel_t channel_after_csa;
// Unique value that is associated with the next beacon event
uint64_t beacon_notification_id;
// Unique value that is associated with the upcoming channel switch event
uint64_t channel_switch_notification_id;
// The time in sim_env for next beacon
zx::time next_beacon_time;
// There is only one static copy of beacon frame, and AP can modify it according to state.
simulation::SimBeaconFrame beacon_frame_;
// Functor that will mutate beacon frames if error injection is enabled.
// If this is nullptr, beacon error injection is disabled.
std::function<SimBeaconFrame(const SimBeaconFrame&)> beacon_mutator;
} beacon_state_;
enum AssocHandling assoc_handling_mode_ = ASSOC_ALLOWED;
// Delay between start and stop sending CSA beacon to old channel
zx::duration csa_beacon_interval_ = zx::msec(150);
// Delay between an association request and an association response
zx::duration assoc_resp_interval_ = zx::msec(1);
// Delay between an Disassociation request and an Disassociation response
zx::duration disassoc_resp_interval_ = zx::msec(1);
// Delay between an probe request and an probe response
zx::duration probe_resp_interval_ = zx::msec(1);
// Delay between an auth request and an auth response
zx::duration auth_resp_interval_ = zx::msec(1);
// Delay between forwarding data frames
zx::duration data_forward_interval_ = zx::msec(1);
std::list<std::shared_ptr<Client>> clients_;
};
} // namespace wlan::simulation
#endif // SRC_CONNECTIVITY_WLAN_DRIVERS_TESTING_LIB_SIM_FAKE_AP_SIM_FAKE_AP_H_