// Copyright 2017 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 "station.h"

#include "device_interface.h"
#include "logging.h"
#include "mac_frame.h"
#include "packet.h"
#include "serialize.h"
#include "timer.h"

#include <cstring>
#include <utility>

namespace wlan {

// TODO(hahnr): Revisit frame construction to reduce boilerplate code.

static constexpr zx_duration_t kAssocTimeoutTu = 20;
static constexpr zx_duration_t kSignalReportTimeoutTu = 10;

Station::Station(DeviceInterface* device, fbl::unique_ptr<Timer> timer)
    : device_(device), timer_(std::move(timer)) {
    (void)assoc_timeout_;
    bssid_.Reset();
}

void Station::Reset() {
    debugfn();

    timer_->CancelTimer();
    state_ = WlanState::kUnjoined;
    bss_.reset();
    join_timeout_ = 0;
    auth_timeout_ = 0;
    last_seen_ = 0;
    bssid_.Reset();
}

bool Station::ShouldDropMlmeMessage(Method& method) {
    // Always allow MLME-JOIN.request.
    if (method == Method::JOIN_request) { return false; }
    // Drop other MLME requests if there is no BSSID set yet.
    return bssid() == nullptr;
}

zx_status_t Station::HandleMlmeJoinReq(const JoinRequest& req) {
    debugfn();

    if (req.selected_bss.is_null()) {
        errorf("bad join request\n");
        // Don't reset because of a bad request. Just send the response.
        return SendJoinResponse();
    }

    if (state_ != WlanState::kUnjoined) {
        warnf("already joined; resetting station\n");
        Reset();
    }

    // Clone request to take ownership of the BSS>
    auto req_clone = req.Clone();
    bss_ = std::move(req_clone->selected_bss);
    bssid_.Set(bss_->bssid.data());
    debugjoin("setting channel to %u\n", bss_->channel);
    zx_status_t status = device_->SetChannel(wlan_channel_t{bss_->channel});
    if (status != ZX_OK) {
        errorf("could not set wlan channel: %d\n", status);
        Reset();
        SendJoinResponse();
        return status;
    }

    join_timeout_ = deadline_after_bcn_period(req.join_failure_timeout);
    status = timer_->SetTimer(join_timeout_);
    if (status != ZX_OK) {
        errorf("could not set join timer: %d\n", status);
        Reset();
        SendJoinResponse();
    }

    // TODO(hahnr): Update when other BSS types are supported.
    device_->SetBss(bssid_, WLAN_BSS_TYPE_INFRASTRUCTURE);
    return status;
}

zx_status_t Station::HandleMlmeAuthReq(const AuthenticateRequest& req) {
    debugfn();

    if (bss_.is_null()) { return ZX_ERR_BAD_STATE; }

    // TODO(tkilbourn): better result codes
    if (!bss_->bssid.Equals(req.peer_sta_address)) {
        errorf("cannot authenticate before joining\n");
        return SendAuthResponse(AuthenticateResultCodes::REFUSED);
    }
    if (state_ == WlanState::kUnjoined) {
        errorf("must join before authenticating\n");
        return SendAuthResponse(AuthenticateResultCodes::REFUSED);
    }
    if (state_ != WlanState::kUnauthenticated) {
        warnf("already authenticated; sending request anyway\n");
    }
    if (req.auth_type != AuthenticationTypes::OPEN_SYSTEM) {
        // TODO(tkilbourn): support other authentication types
        // TODO(tkilbourn): set the auth_alg_ when we support other authentication types
        errorf("only OpenSystem authentication is supported\n");
        return SendAuthResponse(AuthenticateResultCodes::REFUSED);
    }

    debugjoin("authenticating to %s\n", MACSTR(bssid_));

    // TODO(tkilbourn): better size management
    size_t auth_len = sizeof(MgmtFrameHeader) + sizeof(Authentication);
    fbl::unique_ptr<Buffer> buffer = GetBuffer(auth_len);
    if (buffer == nullptr) { return ZX_ERR_NO_RESOURCES; }

    const common::MacAddr& mymac = device_->GetState()->address();

    auto packet = fbl::unique_ptr<Packet>(new Packet(std::move(buffer), auth_len));
    packet->clear();
    packet->set_peer(Packet::Peer::kWlan);
    auto hdr = packet->mut_field<MgmtFrameHeader>(0);
    hdr->fc.set_type(kManagement);
    hdr->fc.set_subtype(kAuthentication);

    hdr->addr1 = bssid_;
    hdr->addr2 = mymac;
    hdr->addr3 = bssid_;

    hdr->sc.set_seq(next_seq());

    auto auth = packet->mut_field<Authentication>(sizeof(MgmtFrameHeader));
    // TODO(tkilbourn): this assumes Open System authentication
    auth->auth_algorithm_number = auth_alg_;
    auth->auth_txn_seq_number = 1;
    auth->status_code = 0;  // Reserved, so set to 0

    zx_status_t status = device_->SendWlan(std::move(packet));
    if (status != ZX_OK) {
        errorf("could not send auth packet: %d\n", status);
        SendAuthResponse(AuthenticateResultCodes::REFUSED);
        return status;
    }

    auth_timeout_ = deadline_after_bcn_period(req.auth_failure_timeout);
    status = timer_->SetTimer(auth_timeout_);
    if (status != ZX_OK) {
        errorf("could not set auth timer: %d\n", status);
        // This is the wrong result code, but we need to define our own codes at some later time.
        SendAuthResponse(AuthenticateResultCodes::AUTH_FAILURE_TIMEOUT);
        // TODO(tkilbourn): reset the station?
    }
    return status;
}

zx_status_t Station::HandleMlmeDeauthReq(const DeauthenticateRequest& req) {
    debugfn();
    ZX_DEBUG_ASSERT(!req.peer_sta_address.is_null());

    if (state_ != WlanState::kAssociated && state_ != WlanState::kAuthenticated) {
        errorf("not associated or authenticated; ignoring deauthenticate request\n");
        return ZX_OK;
    }

    if (bss_.is_null()) { return ZX_ERR_BAD_STATE; }

    // Check whether the request wants to deauthenticate from this STA's BSS.
    common::MacAddr peer_sta_addr(req.peer_sta_address.data());
    if (bssid_ != peer_sta_addr) { return ZX_OK; }

    size_t deauth_len = sizeof(MgmtFrameHeader) + sizeof(Deauthentication);
    fbl::unique_ptr<Buffer> buffer = GetBuffer(deauth_len);
    if (buffer == nullptr) { return ZX_ERR_NO_RESOURCES; }

    auto packet = fbl::unique_ptr<Packet>(new Packet(std::move(buffer), deauth_len));
    packet->clear();
    packet->set_peer(Packet::Peer::kWlan);
    auto hdr = packet->mut_field<MgmtFrameHeader>(0);
    hdr->fc.set_type(kManagement);
    hdr->fc.set_subtype(kDeauthentication);

    const common::MacAddr& mymac = device_->GetState()->address();
    hdr->addr1 = bssid_;
    hdr->addr2 = mymac;
    hdr->addr3 = bssid_;
    hdr->sc.set_seq(next_seq());

    auto deauth = packet->mut_field<Deauthentication>(sizeof(MgmtFrameHeader));
    deauth->reason_code = req.reason_code;

    zx_status_t status = device_->SendWlan(std::move(packet));
    if (status != ZX_OK) {
        errorf("could not send deauth packet: %d\n", status);
        // Deauthenticate nevertheless. IEEE isn't clear on what we are supposed to do.
    }

    infof("deauthenticating from %s, reason=%u\n", bss_->ssid.data(), req.reason_code);

    // TODO(hahnr): Refactor once we have the new state machine.
    state_ = WlanState::kUnauthenticated;
    device_->SetStatus(0);
    controlled_port_ = PortState::kBlocked;
    SendDeauthResponse(peer_sta_addr);

    return ZX_OK;
}

zx_status_t Station::HandleMlmeAssocReq(const AssociateRequest& req) {
    debugfn();

    if (bss_.is_null()) { return ZX_ERR_BAD_STATE; }

    // TODO(tkilbourn): better result codes
    if (!bss_->bssid.Equals(req.peer_sta_address)) {
        errorf("bad peer STA address for association\n");
        return SendAuthResponse(AuthenticateResultCodes::REFUSED);
    }
    if (state_ == WlanState::kUnjoined || state_ == WlanState::kUnauthenticated) {
        errorf("must authenticate before associating\n");
        return SendAuthResponse(AuthenticateResultCodes::REFUSED);
    }
    if (state_ == WlanState::kAssociated) {
        warnf("already authenticated; sending request anyway\n");
    }

    debugjoin("associating to %s\n", MACSTR(bssid_));

    // TODO(tkilbourn): better size management; for now reserve 128 bytes for Association elements
    size_t assoc_len = sizeof(MgmtFrameHeader) + sizeof(AssociationRequest) + 128;
    fbl::unique_ptr<Buffer> buffer = GetBuffer(assoc_len);
    if (buffer == nullptr) { return ZX_ERR_NO_RESOURCES; }

    const common::MacAddr& mymac = device_->GetState()->address();

    auto packet = fbl::unique_ptr<Packet>(new Packet(std::move(buffer), assoc_len));
    packet->clear();
    packet->set_peer(Packet::Peer::kWlan);
    auto hdr = packet->mut_field<MgmtFrameHeader>(0);
    hdr->fc.set_type(kManagement);
    hdr->fc.set_subtype(kAssociationRequest);

    hdr->addr1 = bssid_;
    hdr->addr2 = mymac;
    hdr->addr3 = bssid_;

    hdr->sc.set_seq(next_seq());

    // TODO(tkilbourn): a lot of this is hardcoded for now. Use device capabilities to set up the
    // request.
    auto assoc = packet->mut_field<AssociationRequest>(sizeof(MgmtFrameHeader));
    assoc->cap.set_ess(1);
    assoc->cap.set_short_preamble(1);
    assoc->listen_interval = 0;
    ElementWriter w(assoc->elements,
                    packet->len() - sizeof(MgmtFrameHeader) - sizeof(AssociationRequest));
    if (!w.write<SsidElement>(bss_->ssid.data())) {
        errorf("could not write ssid \"%s\" to association request\n", bss_->ssid.data());
        SendAssocResponse(AssociateResultCodes::REFUSED_REASON_UNSPECIFIED);
        return ZX_ERR_IO;
    }
    // TODO(tkilbourn): add extended rates support to get the rest of 802.11g rates.
    // TODO(tkilbourn): determine these rates based on hardware and the AP
    std::vector<uint8_t> rates = {0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24};

    if (!w.write<SupportedRatesElement>(std::move(rates))) {
        errorf("could not write supported rates\n");
        SendAssocResponse(AssociateResultCodes::REFUSED_REASON_UNSPECIFIED);
        return ZX_ERR_IO;
    }

    std::vector<uint8_t> ext_rates = {0x30, 0x48, 0x60, 0x6c};
    if (!w.write<ExtendedSupportedRatesElement>(std::move(ext_rates))) {
        errorf("could not write extended supported rates\n");
        SendAssocResponse(AssociateResultCodes::REFUSED_REASON_UNSPECIFIED);
        return ZX_ERR_IO;
    }

    // Write RSNE from MLME-Association.request if available.
    if (req.rsn) {
        if (!w.write<RsnElement>(req.rsn.data(), req.rsn.size())) { return ZX_ERR_IO; }
    }

    if (IsHTReady()) {
        HtCapabilities htc = BuildHtCapabilities();
        if (!w.write<HtCapabilities>(htc.ht_cap_info, htc.ampdu_params, htc.mcs_set, htc.ht_ext_cap,
                                     htc.txbf_cap, htc.asel_cap)) {
            errorf("could not write HtCapabilities\n");
            SendAssocResponse(AssociateResultCodes::REFUSED_REASON_UNSPECIFIED);
            return ZX_ERR_IO;
        }
    }

    // Validate the request in debug mode
    ZX_DEBUG_ASSERT(assoc->Validate(w.size()));

    size_t actual_len = sizeof(MgmtFrameHeader) + sizeof(AssociationRequest) + w.size();
    zx_status_t status = packet->set_len(actual_len);
    if (status != ZX_OK) {
        errorf("could not set packet length to %zu: %d\n", actual_len, status);
        SendAssocResponse(AssociateResultCodes::REFUSED_REASON_UNSPECIFIED);
        return status;
    }

    status = device_->SendWlan(std::move(packet));
    if (status != ZX_OK) {
        errorf("could not send assoc packet: %d\n", status);
        SendAssocResponse(AssociateResultCodes::REFUSED_REASON_UNSPECIFIED);
        return status;
    }

    // TODO(tkilbourn): get the assoc timeout from somewhere
    assoc_timeout_ = deadline_after_bcn_period(kAssocTimeoutTu);
    status = timer_->SetTimer(assoc_timeout_);
    if (status != ZX_OK) {
        errorf("could not set auth timer: %d\n", status);
        // This is the wrong result code, but we need to define our own codes at some later time.
        SendAssocResponse(AssociateResultCodes::REFUSED_REASON_UNSPECIFIED);
        // TODO(tkilbourn): reset the station?
    }
    return status;
}

bool Station::ShouldDropMgmtFrame(const MgmtFrameHeader& hdr) {
    // Drop management frames if either, there is no BSSID set yet,
    // or the frame is not from the BSS.
    return bssid() == nullptr || *bssid() != hdr.addr3;
}

// TODO(hahnr): Support ProbeResponses.
zx_status_t Station::HandleBeacon(const MgmtFrame<Beacon>& frame, const wlan_rx_info_t& rxinfo) {
    debugfn();
    ZX_DEBUG_ASSERT(!bss_.is_null());
    ZX_DEBUG_ASSERT(frame.hdr->fc.subtype() == ManagementSubtype::kBeacon);
    ZX_DEBUG_ASSERT(frame.hdr->addr3 == common::MacAddr(bss_->bssid.data()));

    avg_rssi_.add(rxinfo.rssi);

    // TODO(tkilbourn): update any other info (like rolling average of rssi)
    last_seen_ = timer_->Now();
    if (join_timeout_ > 0) {
        join_timeout_ = 0;
        timer_->CancelTimer();
        state_ = WlanState::kUnauthenticated;
        debugjoin("joined %s\n", bss_->ssid.data());
        return SendJoinResponse();
    }

    auto bcn = frame.body;
    size_t elt_len = frame.body_len - sizeof(Beacon);
    ElementReader reader(bcn->elements, elt_len);
    while (reader.is_valid()) {
        const ElementHeader* hdr = reader.peek();
        if (hdr == nullptr) break;

        switch (hdr->id) {
        case element_id::kTim: {
            auto tim = reader.read<TimElement>();
            if (tim == nullptr) goto done_iter;
            if (tim->traffic_buffered(aid_)) { SendPsPoll(); }
            break;
        }
        default:
            reader.skip(sizeof(ElementHeader) + hdr->len);
            break;
        }
    }

done_iter:
    return ZX_OK;
}

zx_status_t Station::HandleAuthentication(const MgmtFrame<Authentication>& frame,
                                          const wlan_rx_info_t& rxinfo) {
    debugfn();
    ZX_DEBUG_ASSERT(frame.hdr->fc.subtype() == ManagementSubtype::kAuthentication);
    ZX_DEBUG_ASSERT(frame.hdr->addr3 == common::MacAddr(bss_->bssid.data()));

    if (state_ != WlanState::kUnauthenticated) {
        // TODO(tkilbourn): should we process this Authentication packet anyway? The spec is
        // unclear.
        debugjoin("unexpected authentication frame\n");
        return ZX_OK;
    }

    auto auth = frame.body;
    if (auth->auth_algorithm_number != auth_alg_) {
        errorf("mismatched authentication algorithm (expected %u, got %u)\n", auth_alg_,
               auth->auth_algorithm_number);
        return ZX_ERR_BAD_STATE;
    }

    // TODO(tkilbourn): this only makes sense for Open System.
    if (auth->auth_txn_seq_number != 2) {
        errorf("unexpected auth txn sequence number (expected 2, got %u)\n",
               auth->auth_txn_seq_number);
        return ZX_ERR_BAD_STATE;
    }

    if (auth->status_code != status_code::kSuccess) {
        errorf("authentication failed (status code=%u)\n", auth->status_code);
        // TODO(tkilbourn): is this the right result code?
        SendAuthResponse(AuthenticateResultCodes::AUTHENTICATION_REJECTED);
        return ZX_ERR_BAD_STATE;
    }

    common::MacAddr bssid(bss_->bssid.data());
    debugjoin("authenticated to %s\n", MACSTR(bssid));
    state_ = WlanState::kAuthenticated;
    auth_timeout_ = 0;
    timer_->CancelTimer();
    SendAuthResponse(AuthenticateResultCodes::SUCCESS);
    return ZX_OK;
}

zx_status_t Station::HandleDeauthentication(const MgmtFrame<Deauthentication>& frame,
                                            const wlan_rx_info_t& rxinfo) {
    debugfn();
    ZX_DEBUG_ASSERT(frame.hdr->fc.subtype() == ManagementSubtype::kDeauthentication);
    ZX_DEBUG_ASSERT(frame.hdr->addr3 == common::MacAddr(bss_->bssid.data()));

    if (state_ != WlanState::kAssociated && state_ != WlanState::kAuthenticated) {
        debugjoin("got spurious deauthenticate; ignoring\n");
        return ZX_OK;
    }

    auto deauth = frame.body;
    infof("deauthenticating from %s, reason=%u\n", bss_->ssid.data(), deauth->reason_code);

    state_ = WlanState::kUnauthenticated;
    device_->SetStatus(0);
    controlled_port_ = PortState::kBlocked;

    return SendDeauthIndication(deauth->reason_code);
}

zx_status_t Station::HandleAssociationResponse(const MgmtFrame<AssociationResponse>& frame,
                                               const wlan_rx_info_t& rxinfo) {
    debugfn();
    ZX_DEBUG_ASSERT(frame.hdr->fc.subtype() == ManagementSubtype::kAssociationResponse);
    ZX_DEBUG_ASSERT(frame.hdr->addr3 == common::MacAddr(bss_->bssid.data()));

    if (state_ != WlanState::kAuthenticated) {
        // TODO(tkilbourn): should we process this Association response packet anyway? The spec is
        // unclear.
        debugjoin("unexpected association response frame\n");
        return ZX_OK;
    }

    auto assoc = frame.body;
    if (assoc->status_code != status_code::kSuccess) {
        errorf("association failed (status code=%u)\n", assoc->status_code);
        // TODO(tkilbourn): map to the correct result code
        SendAssocResponse(AssociateResultCodes::REFUSED_REASON_UNSPECIFIED);
        return ZX_ERR_BAD_STATE;
    }

    common::MacAddr bssid(bss_->bssid.data());
    debugjoin("associated with %s\n", MACSTR(bssid));
    state_ = WlanState::kAssociated;
    assoc_timeout_ = 0;
    aid_ = assoc->aid & kAidMask;
    timer_->CancelTimer();
    SendAssocResponse(AssociateResultCodes::SUCCESS);

    signal_report_timeout_ = deadline_after_bcn_period(kSignalReportTimeoutTu);
    timer_->SetTimer(signal_report_timeout_);
    avg_rssi_.reset();
    avg_rssi_.add(rxinfo.rssi);
    SendSignalReportIndication(rxinfo.rssi);

    // Open port if user connected to an open network.
    if (bss_->rsn.is_null()) {
        debugjoin("802.1X controlled port is now open\n");
        controlled_port_ = PortState::kOpen;
        device_->SetStatus(ETH_STATUS_ONLINE);
    }

    std::printf("associated\n");

    return ZX_OK;
}

zx_status_t Station::HandleDisassociation(const MgmtFrame<Disassociation>& frame,
                                          const wlan_rx_info_t& rxinfo) {
    debugfn();
    ZX_DEBUG_ASSERT(frame.hdr->fc.subtype() == ManagementSubtype::kDisassociation);
    ZX_DEBUG_ASSERT(frame.hdr->addr3 == common::MacAddr(bss_->bssid.data()));

    if (state_ != WlanState::kAssociated) {
        debugjoin("got spurious disassociate; ignoring\n");
        return ZX_OK;
    }

    auto disassoc = frame.body;
    common::MacAddr bssid(bss_->bssid.data());
    infof("disassociating from %s(%s), reason=%u\n", MACSTR(bssid), bss_->ssid.data(),
          disassoc->reason_code);

    state_ = WlanState::kAuthenticated;
    device_->SetStatus(0);
    controlled_port_ = PortState::kBlocked;

    signal_report_timeout_ = 0;
    timer_->CancelTimer();

    return SendDisassociateIndication(disassoc->reason_code);
}

zx_status_t Station::HandleAddBaRequestFrame(const MgmtFrame<AddBaRequestFrame>& frame,
                                             const wlan_rx_info_t& rxinfo) {
    debugfn();
    ZX_DEBUG_ASSERT(frame.hdr->fc.subtype() == ManagementSubtype::kAction);
    ZX_DEBUG_ASSERT(frame.hdr->addr3 == common::MacAddr(bss_->bssid.data()));
    ZX_DEBUG_ASSERT(frame.body->category == action::Category::kBlockAck);
    ZX_DEBUG_ASSERT(frame.body->action == action::BaAction::kAddBaRequest);

    auto addbar = frame.body;
    debugf(
        "Rxed ADDBAR: token %3u, amsdu %u policy %u tid %u buffer_size %u, timeout %u, "
        "fragment "
        "%u starting_seq %u",
        addbar->dialog_token, addbar->params.amsdu(), addbar->params.policy(), addbar->params.tid(),
        addbar->params.buffer_size(), addbar->timeout, addbar->seq_ctrl.fragment(),
        addbar->seq_ctrl.starting_seq());

    // Construct AddBaResponse frame
    // Here MgmtFrameHeader construction does not use an optional header field.
    // TODO(porce): Build a robust frame header constructor.
    size_t frame_len = sizeof(MgmtFrameHeader) + sizeof(AddBaResponseFrame);
    fbl::unique_ptr<Buffer> buffer = GetBuffer(frame_len);
    if (buffer == nullptr) { return ZX_ERR_NO_RESOURCES; }

    const common::MacAddr& mymac = device_->GetState()->address();
    auto packet = fbl::unique_ptr<Packet>(new Packet(std::move(buffer), frame_len));
    packet->clear();
    packet->set_peer(Packet::Peer::kWlan);
    auto hdr = packet->mut_field<MgmtFrameHeader>(0);
    hdr->fc.set_type(kManagement);
    hdr->fc.set_subtype(kAction);
    hdr->addr1 = bssid_;
    hdr->addr2 = mymac;
    hdr->addr3 = bssid_;
    hdr->sc.set_seq(next_seq());
    auto resp = packet->mut_field<AddBaResponseFrame>(sizeof(MgmtFrameHeader));
    resp->category = action::Category::kBlockAck;
    resp->action = action::BaAction::kAddBaResponse;
    resp->dialog_token = addbar->dialog_token;

    // TODO(porce): Implement DelBa as a response to AddBar for decline

    // Note: Returning AddBaResponse with status_code::kRefused seems ineffective.
    // ArubaAP is persistent not honoring that.
    resp->status_code = status_code::kSuccess;

    // TODO(porce): Query the radio chipset capability to build the response.
    resp->params.set_amsdu(0);
    resp->params.set_policy(BlockAckParameters::kImmediate);
    resp->params.set_tid(addbar->params.tid());

    // TODO(porce): Once chipset capability is ready, refactor below buffer_size
    // calculation.
    auto buffer_size_ap = addbar->params.buffer_size();
    constexpr size_t buffer_size_ralink = 64;
    auto buffer_size = (buffer_size_ap <= buffer_size_ralink) ? buffer_size_ap : buffer_size_ralink;
    resp->params.set_buffer_size(buffer_size);

    resp->timeout = addbar->timeout;

    zx_status_t status = device_->SendWlan(std::move(packet));
    if (status != ZX_OK) {
        errorf("could not send AddBaResponse: %d\n", status);
        return status;
    }

    return ZX_OK;
}

bool Station::ShouldDropDataFrame(const DataFrameHeader& hdr) {
    // Drop data frames if either, there is no BSSID set yet,
    // or the frame is not from the BSS.
    auto from_bss = (bssid() != nullptr && *bssid() == hdr.addr2);
    auto associated = (state_ == WlanState::kAssociated);
    if (!associated) { debugf("dropping data packet while not associated\n"); }
    return !from_bss || !associated;
}

zx_status_t Station::HandleNullDataFrame(const DataFrameHeader& hdr, const wlan_rx_info_t& rxinfo) {
    debugfn();
    ZX_DEBUG_ASSERT(hdr.fc.subtype() == DataSubtype::kNull);
    ZX_DEBUG_ASSERT(bssid() != nullptr);
    ZX_DEBUG_ASSERT(hdr.addr2 == common::MacAddr(bss_->bssid.data()));
    ZX_DEBUG_ASSERT(state_ == WlanState::kAssociated);

    // Take signal strength into account.
    avg_rssi_.add(rxinfo.rssi);

    // Some AP's such as Netgear Routers send periodic NULL data frames to test whether a client
    // timed out. The client must respond with a NULL data frame itself to not get
    // deauthenticated.
    SendKeepAliveResponse();
    return ZX_OK;
}

zx_status_t Station::HandleDataFrame(const DataFrame<LlcHeader>& frame,
                                     const wlan_rx_info_t& rxinfo) {
    debugfn();
    ZX_DEBUG_ASSERT(bssid() != nullptr);
    ZX_DEBUG_ASSERT(frame.hdr->addr2 == common::MacAddr(bss_->bssid.data()));
    ZX_DEBUG_ASSERT(state_ == WlanState::kAssociated);

    switch (frame.hdr->fc.subtype()) {
    case DataSubtype::kDataSubtype:
        // Fall-through
    case DataSubtype::kQosdata:  // For data frames within BlockAck session.
        break;
    default:
        warnf("unsupported data subtype %02x\n", frame.hdr->fc.subtype());
        return ZX_OK;
    }

    // Take signal strength into account.
    avg_rssi_.add(rxinfo.rssi);

    auto hdr = frame.hdr;
    auto llc = frame.body;

    // Forward EAPOL frames to SME.
    if (be16toh(llc->protocol_id) == kEapolProtocolId) {
        if (frame.body_len < sizeof(EapolFrame)) {
            warnf("short EAPOL frame; len = %zu", frame.body_len);
            return ZX_OK;
        }
        auto eapol = reinterpret_cast<const EapolFrame*>(llc->payload);
        uint16_t actual_body_len = frame.body_len;
        uint16_t expected_body_len = be16toh(eapol->packet_body_length);
        if (actual_body_len >= expected_body_len) {
            return SendEapolIndication(eapol, hdr->addr3, hdr->addr1);
        }
        return ZX_OK;
    }

    // Drop packets if RSNA was not yet established.
    if (controlled_port_ == PortState::kBlocked) { return ZX_OK; }

    // PS-POLL if there are more buffered unicast frames.
    if (hdr->fc.more_data() && hdr->addr1.IsUcast()) { SendPsPoll(); }

    const size_t eth_len = frame.body_len + sizeof(EthernetII);
    auto buffer = GetBuffer(eth_len);
    if (buffer == nullptr) { return ZX_ERR_NO_RESOURCES; }

    auto eth_packet = fbl::unique_ptr<Packet>(new Packet(std::move(buffer), eth_len));
    // no need to clear the packet since every byte is overwritten
    eth_packet->set_peer(Packet::Peer::kEthernet);
    auto eth = eth_packet->mut_field<EthernetII>(0);

    eth->dest = hdr->addr1;
    eth->src = hdr->addr3;

    eth->ether_type = llc->protocol_id;
    std::memcpy(eth->payload, llc->payload, frame.body_len - sizeof(LlcHeader));

    zx_status_t status = device_->SendEthernet(std::move(eth_packet));
    if (status != ZX_OK) { errorf("could not send ethernet data: %d\n", status); }
    return status;
}

bool Station::ShouldDropEthFrame(const BaseFrame<EthernetII>& hdr) {
    // Drop Ethernet frames when not associated.
    auto bss_setup = (bssid() != nullptr);
    auto associated = (state_ == WlanState::kAssociated);
    if (!associated) { debugf("dropping eth packet while not associated\n"); }
    return !bss_setup || !associated;
}

zx_status_t Station::HandleEthFrame(const BaseFrame<EthernetII>& frame) {
    debugfn();
    ZX_DEBUG_ASSERT(bssid() != nullptr);
    ZX_DEBUG_ASSERT(state_ == WlanState::kAssociated);

    auto eth = frame.hdr;
    const size_t wlan_len = kDataPayloadHeader + frame.body_len;
    auto buffer = GetBuffer(wlan_len);
    if (buffer == nullptr) { return ZX_ERR_NO_RESOURCES; }

    wlan_tx_info_t txinfo = {};
    auto wlan_packet = fbl::unique_ptr<Packet>(new Packet(std::move(buffer), wlan_len));
    // no need to clear the whole packet; we memset the headers instead and copy over all bytes in
    // the payload
    wlan_packet->set_peer(Packet::Peer::kWlan);
    auto hdr = wlan_packet->mut_field<DataFrameHeader>(0);
    std::memset(hdr, 0, sizeof(DataFrameHeader));
    hdr->fc.set_type(kData);
    hdr->fc.set_to_ds(1);
    // Ensure all outgoing data frames are protected when RSNA is established.
    if (!bss_->rsn.is_null() && controlled_port_ == PortState::kOpen) {
        hdr->fc.set_protected_frame(1);
        txinfo.tx_flags |= WLAN_TX_INFO_FLAGS_PROTECTED;
    }

    hdr->addr1 = common::MacAddr(bss_->bssid.data());
    hdr->addr2 = eth->src;
    hdr->addr3 = eth->dest;

    hdr->sc.set_seq(next_seq());
    debughdr("Frame control: %04x  duration: %u  seq: %u frag: %u\n", hdr->fc.val(), hdr->duration,
             hdr->sc.seq(), hdr->sc.frag());

    // TODO(porce): Fix this inconsistency. See how addr1,2,3 are assigned.
    debughdr("dest: %s source: %s bssid: %s\n", MACSTR(hdr->addr1), MACSTR(hdr->addr2),
             MACSTR(hdr->addr3));

    auto llc = wlan_packet->mut_field<LlcHeader>(sizeof(DataFrameHeader));
    llc->dsap = kLlcSnapExtension;
    llc->ssap = kLlcSnapExtension;
    llc->control = kLlcUnnumberedInformation;
    std::memcpy(llc->oui, kLlcOui, sizeof(llc->oui));
    llc->protocol_id = eth->ether_type;

    std::memcpy(llc->payload, eth->payload, frame.body_len);
    wlan_packet->CopyCtrlFrom(txinfo);

    zx_status_t status = device_->SendWlan(std::move(wlan_packet));
    if (status != ZX_OK) { errorf("could not send wlan data: %d\n", status); }
    return status;
}

zx_status_t Station::HandleTimeout() {
    debugfn();
    zx_time_t now = timer_->Now();
    if (join_timeout_ > 0 && now > join_timeout_) {
        debugjoin("join timed out; resetting\n");

        Reset();
        return SendJoinResponse();
    }

    if (auth_timeout_ > 0 && now >= auth_timeout_) {
        debugjoin("auth timed out; moving back to joining\n");
        auth_timeout_ = 0;
        return SendAuthResponse(AuthenticateResultCodes::AUTH_FAILURE_TIMEOUT);
    }

    if (assoc_timeout_ > 0 && now >= assoc_timeout_) {
        debugjoin("assoc timed out; moving back to authenticated\n");
        assoc_timeout_ = 0;
        // TODO(tkilbourn): need a better error code for this
        return SendAssocResponse(AssociateResultCodes::REFUSED_TEMPORARILY);
    }

    if (signal_report_timeout_ > 0 && now > signal_report_timeout_ &&
        state_ == WlanState::kAssociated) {
        signal_report_timeout_ = deadline_after_bcn_period(kSignalReportTimeoutTu);
        timer_->SetTimer(signal_report_timeout_);
        SendSignalReportIndication(avg_rssi_.avg());
    }

    return ZX_OK;
}

zx_status_t Station::SendJoinResponse() {
    debugfn();
    auto resp = JoinResponse::New();
    resp->result_code = state_ == WlanState::kUnjoined ? JoinResultCodes::JOIN_FAILURE_TIMEOUT
                                                       : JoinResultCodes::SUCCESS;

    size_t buf_len = sizeof(ServiceHeader) + resp->GetSerializedSize();
    fbl::unique_ptr<Buffer> buffer = GetBuffer(buf_len);
    if (buffer == nullptr) { return ZX_ERR_NO_RESOURCES; }

    auto packet = fbl::unique_ptr<Packet>(new Packet(std::move(buffer), buf_len));
    packet->set_peer(Packet::Peer::kService);
    zx_status_t status = SerializeServiceMsg(packet.get(), Method::JOIN_confirm, resp);
    if (status != ZX_OK) {
        errorf("could not serialize JoinResponse: %d\n", status);
    } else {
        status = device_->SendService(std::move(packet));
    }

    return status;
}

zx_status_t Station::SendAuthResponse(AuthenticateResultCodes code) {
    debugfn();
    auto resp = AuthenticateResponse::New();
    resp->peer_sta_address = fidl::Array<uint8_t>::New(common::kMacAddrLen);

    common::MacAddr bssid(bss_->bssid.data());
    bssid.CopyTo(resp->peer_sta_address.data());
    // TODO(tkilbourn): set this based on the actual auth type
    resp->auth_type = AuthenticationTypes::OPEN_SYSTEM;
    resp->result_code = code;

    size_t buf_len = sizeof(ServiceHeader) + resp->GetSerializedSize();
    fbl::unique_ptr<Buffer> buffer = GetBuffer(buf_len);
    if (buffer == nullptr) { return ZX_ERR_NO_RESOURCES; }

    auto packet = fbl::unique_ptr<Packet>(new Packet(std::move(buffer), buf_len));
    packet->set_peer(Packet::Peer::kService);
    zx_status_t status = SerializeServiceMsg(packet.get(), Method::AUTHENTICATE_confirm, resp);
    if (status != ZX_OK) {
        errorf("could not serialize AuthenticateResponse: %d\n", status);
    } else {
        status = device_->SendService(std::move(packet));
    }

    return status;
}

zx_status_t Station::SendDeauthResponse(const common::MacAddr& peer_sta_addr) {
    debugfn();

    auto resp = DeauthenticateResponse::New();
    resp->peer_sta_address = fidl::Array<uint8_t>::New(common::kMacAddrLen);
    peer_sta_addr.CopyTo(resp->peer_sta_address.data());

    size_t buf_len = sizeof(ServiceHeader) + resp->GetSerializedSize();
    fbl::unique_ptr<Buffer> buffer = GetBuffer(buf_len);
    if (buffer == nullptr) { return ZX_ERR_NO_RESOURCES; }

    auto packet = fbl::unique_ptr<Packet>(new Packet(std::move(buffer), buf_len));
    packet->set_peer(Packet::Peer::kService);
    zx_status_t status = SerializeServiceMsg(packet.get(), Method::DEAUTHENTICATE_confirm, resp);
    if (status != ZX_OK) {
        errorf("could not serialize DeauthenticateResponse: %d\n", status);
    } else {
        status = device_->SendService(std::move(packet));
    }

    return status;
}

zx_status_t Station::SendKeepAliveResponse() {
    if (state_ != WlanState::kAssociated) {
        warnf("cannot send keep alive response before being associated\n");
        return ZX_OK;
    }

    const common::MacAddr& mymac = device_->GetState()->address();
    size_t len = sizeof(DataFrameHeader);
    fbl::unique_ptr<Buffer> buffer = GetBuffer(len);
    if (buffer == nullptr) { return ZX_ERR_NO_RESOURCES; }

    auto packet = fbl::unique_ptr<Packet>(new Packet(std::move(buffer), len));
    packet->clear();
    packet->set_peer(Packet::Peer::kWlan);
    auto hdr = packet->mut_field<DataFrameHeader>(0);
    hdr->fc.set_type(kData);
    hdr->fc.set_subtype(DataSubtype::kNull);
    hdr->fc.set_to_ds(1);

    common::MacAddr bssid(bss_->bssid.data());
    hdr->addr1 = bssid;
    hdr->addr2 = mymac;
    hdr->addr3 = bssid;
    hdr->sc.set_seq(next_seq());

    zx_status_t status = device_->SendWlan(std::move(packet));
    if (status != ZX_OK) {
        errorf("could not send keep alive packet: %d\n", status);
        return status;
    }
    return ZX_OK;
}

zx_status_t Station::SendDeauthIndication(uint16_t code) {
    debugfn();
    auto ind = DeauthenticateIndication::New();
    ind->peer_sta_address = fidl::Array<uint8_t>::New(common::kMacAddrLen);
    common::MacAddr bssid(bss_->bssid.data());
    bssid.CopyTo(ind->peer_sta_address.data());
    ind->reason_code = code;

    size_t buf_len = sizeof(ServiceHeader) + ind->GetSerializedSize();
    fbl::unique_ptr<Buffer> buffer = GetBuffer(buf_len);
    if (buffer == nullptr) { return ZX_ERR_NO_RESOURCES; }

    auto packet = fbl::unique_ptr<Packet>(new Packet(std::move(buffer), buf_len));
    packet->set_peer(Packet::Peer::kService);
    zx_status_t status = SerializeServiceMsg(packet.get(), Method::DEAUTHENTICATE_indication, ind);
    if (status != ZX_OK) {
        errorf("could not serialize DeauthenticateIndication: %d\n", status);
    } else {
        status = device_->SendService(std::move(packet));
    }

    return status;
}

zx_status_t Station::SendAssocResponse(AssociateResultCodes code) {
    debugfn();
    auto resp = AssociateResponse::New();
    resp->result_code = code;
    resp->association_id = aid_;

    size_t buf_len = sizeof(ServiceHeader) + resp->GetSerializedSize();
    fbl::unique_ptr<Buffer> buffer = GetBuffer(buf_len);
    if (buffer == nullptr) { return ZX_ERR_NO_RESOURCES; }

    auto packet = fbl::unique_ptr<Packet>(new Packet(std::move(buffer), buf_len));
    packet->set_peer(Packet::Peer::kService);
    zx_status_t status = SerializeServiceMsg(packet.get(), Method::ASSOCIATE_confirm, resp);
    if (status != ZX_OK) {
        errorf("could not serialize AssociateResponse: %d\n", status);
    } else {
        status = device_->SendService(std::move(packet));
    }

    return status;
}

zx_status_t Station::SendDisassociateIndication(uint16_t code) {
    debugfn();
    auto ind = DisassociateIndication::New();
    ind->peer_sta_address = fidl::Array<uint8_t>::New(common::kMacAddrLen);
    common::MacAddr bssid(bss_->bssid.data());
    bssid.CopyTo(ind->peer_sta_address.data());
    ind->reason_code = code;

    size_t buf_len = sizeof(ServiceHeader) + ind->GetSerializedSize();
    fbl::unique_ptr<Buffer> buffer = GetBuffer(buf_len);
    if (buffer == nullptr) { return ZX_ERR_NO_RESOURCES; }

    auto packet = fbl::unique_ptr<Packet>(new Packet(std::move(buffer), buf_len));
    packet->set_peer(Packet::Peer::kService);
    zx_status_t status = SerializeServiceMsg(packet.get(), Method::DISASSOCIATE_indication, ind);
    if (status != ZX_OK) {
        errorf("could not serialize DisassociateIndication: %d\n", status);
    } else {
        status = device_->SendService(std::move(packet));
    }

    return status;
}

zx_status_t Station::SendSignalReportIndication(uint8_t rssi) {
    debugfn();
    if (state_ != WlanState::kAssociated) { return ZX_OK; }

    auto ind = SignalReportIndication::New();
    ind->rssi = rssi;

    size_t buf_len = sizeof(ServiceHeader) + ind->GetSerializedSize();
    fbl::unique_ptr<Buffer> buffer = GetBuffer(buf_len);
    if (buffer == nullptr) { return ZX_ERR_NO_RESOURCES; }

    auto packet = fbl::unique_ptr<Packet>(new Packet(std::move(buffer), buf_len));
    packet->set_peer(Packet::Peer::kService);
    zx_status_t status = SerializeServiceMsg(packet.get(), Method::SIGNAL_REPORT_indication, ind);
    if (status != ZX_OK) {
        errorf("could not serialize SignalReportIndication: %d\n", status);
    } else {
        status = device_->SendService(std::move(packet));
    }

    return status;
}

zx_status_t Station::HandleMlmeEapolReq(const EapolRequest& req) {
    debugfn();

    if (!bss_) { return ZX_ERR_BAD_STATE; }
    if (state_ != WlanState::kAssociated) {
        debugf("dropping MLME-EAPOL.request while not being associated. STA in state %d\n", state_);
        return ZX_OK;
    }

    size_t len = sizeof(DataFrameHeader) + sizeof(LlcHeader) + req.data.size();
    fbl::unique_ptr<Buffer> buffer = GetBuffer(len);
    if (buffer == nullptr) { return ZX_ERR_NO_RESOURCES; }
    auto packet = fbl::unique_ptr<Packet>(new Packet(std::move(buffer), len));
    packet->clear();
    packet->set_peer(Packet::Peer::kWlan);
    auto hdr = packet->mut_field<DataFrameHeader>(0);
    hdr->fc.set_type(kData);
    hdr->fc.set_to_ds(1);

    hdr->addr1.Set(req.dst_addr.data());
    hdr->addr2.Set(req.src_addr.data());
    hdr->addr3.Set(req.dst_addr.data());

    hdr->sc.set_seq(device_->GetState()->next_seq());

    auto llc = packet->mut_field<LlcHeader>(sizeof(DataFrameHeader));
    llc->dsap = kLlcSnapExtension;
    llc->ssap = kLlcSnapExtension;
    llc->control = kLlcUnnumberedInformation;
    std::memcpy(llc->oui, kLlcOui, sizeof(llc->oui));
    llc->protocol_id = htobe16(kEapolProtocolId);
    std::memcpy(llc->payload, req.data.data(), req.data.size());

    zx_status_t status = device_->SendWlan(std::move(packet));
    if (status != ZX_OK) {
        errorf("could not send eapol request packet: %d\n", status);
        SendEapolResponse(EapolResultCodes::TRANSMISSION_FAILURE);
        return status;
    }

    SendEapolResponse(EapolResultCodes::SUCCESS);

    return status;
}

zx_status_t Station::SendEapolResponse(EapolResultCodes result_code) {
    debugfn();

    auto resp = EapolResponse::New();
    resp->result_code = result_code;

    size_t buf_len = sizeof(ServiceHeader) + resp->GetSerializedSize();
    fbl::unique_ptr<Buffer> buffer = GetBuffer(buf_len);
    if (buffer == nullptr) { return ZX_ERR_NO_RESOURCES; }

    auto packet = fbl::unique_ptr<Packet>(new Packet(std::move(buffer), buf_len));
    packet->set_peer(Packet::Peer::kService);
    zx_status_t status = SerializeServiceMsg(packet.get(), Method::EAPOL_confirm, resp);
    if (status != ZX_OK) {
        errorf("could not serialize EapolResponse: %d\n", status);
    } else {
        status = device_->SendService(std::move(packet));
    }

    return status;
}

zx_status_t Station::SendEapolIndication(const EapolFrame* eapol, const common::MacAddr& src,
                                         const common::MacAddr& dst) {
    debugfn();

    // Limit EAPOL packet size. The EAPOL packet's size depends on the link transport protocol and
    // might exceed 255 octets. However, we don't support EAP yet and EAPOL Key frames are always
    // shorter.
    // TODO(hahnr): If necessary, find a better upper bound once we support EAP.
    size_t len = sizeof(EapolFrame) + be16toh(eapol->packet_body_length);
    if (len > 255) { return ZX_OK; }

    auto ind = EapolIndication::New();
    ind->data = ::fidl::Array<uint8_t>::New(len);
    std::memcpy(ind->data.data(), eapol, len);
    ind->src_addr = fidl::Array<uint8_t>::New(common::kMacAddrLen);
    ind->dst_addr = fidl::Array<uint8_t>::New(common::kMacAddrLen);
    src.CopyTo(ind->src_addr.data());
    dst.CopyTo(ind->dst_addr.data());

    size_t buf_len = sizeof(ServiceHeader) + ind->GetSerializedSize();
    fbl::unique_ptr<Buffer> buffer = GetBuffer(buf_len);
    if (buffer == nullptr) { return ZX_ERR_NO_RESOURCES; }

    auto packet = fbl::unique_ptr<Packet>(new Packet(std::move(buffer), buf_len));
    packet->set_peer(Packet::Peer::kService);
    zx_status_t status = SerializeServiceMsg(packet.get(), Method::EAPOL_indication, ind);
    if (status != ZX_OK) {
        errorf("could not serialize EapolIndication: %d\n", status);
    } else {
        status = device_->SendService(std::move(packet));
    }
    return status;
}

zx_status_t Station::HandleMlmeSetKeysReq(const SetKeysRequest& req) {
    debugfn();

    for (auto& keyPtr : req.keylist) {
        if (keyPtr.is_null() || keyPtr->key.is_null()) { return ZX_ERR_NOT_SUPPORTED; }

        uint8_t key_type;
        switch (keyPtr->key_type) {
        case KeyType::PAIRWISE:
            key_type = WLAN_KEY_TYPE_PAIRWISE;
            break;
        case KeyType::PEER_KEY:
            key_type = WLAN_KEY_TYPE_PEER;
            break;
        case KeyType::IGTK:
            key_type = WLAN_KEY_TYPE_IGTK;
            break;
        default:
            key_type = WLAN_KEY_TYPE_GROUP;
            break;
        }

        wlan_key_config_t key_config = {};
        memcpy(key_config.key, keyPtr->key.data(), keyPtr->length);
        key_config.key_type = key_type;
        key_config.key_len = static_cast<uint8_t>(keyPtr->length);
        key_config.key_idx = keyPtr->key_id;
        key_config.protection = WLAN_PROTECTION_RX_TX;
        key_config.cipher_type = keyPtr->cipher_suite_type;
        memcpy(key_config.cipher_oui, keyPtr->cipher_suite_oui.data(),
               sizeof(key_config.cipher_oui));
        if (!keyPtr->address.is_null()) {
            memcpy(key_config.peer_addr, keyPtr->address.data(), sizeof(key_config.peer_addr));
        }

        auto status = device_->SetKey(&key_config);
        if (status != ZX_OK) {
            errorf("Could not configure keys in hardware: %d\n", status);
            return status;
        }
    }

    // Once keys have been successfully configured, open controlled port and report link up
    // status.
    // TODO(hahnr): This is a very simplified assumption and we might need a little more logic to
    // correctly track the port's state.
    controlled_port_ = PortState::kOpen;
    device_->SetStatus(ETH_STATUS_ONLINE);
    return ZX_OK;
}

zx_status_t Station::PreChannelChange(wlan_channel_t chan) {
    debugfn();
    if (state_ != WlanState::kAssociated) { return ZX_OK; }

    auto assoc_chan_num = channel().channel_num;
    auto current_chan_num = device_->GetState()->channel().channel_num;
    if (current_chan_num == assoc_chan_num) {
        SetPowerManagementMode(true);
        // TODO(hahnr): start buffering tx packets (not here though)
    }
    return ZX_OK;
}

zx_status_t Station::PostChannelChange() {
    debugfn();
    if (state_ != WlanState::kAssociated) { return ZX_OK; }

    auto assoc_chan_num = channel().channel_num;
    auto current_chan_num = device_->GetState()->channel().channel_num;
    if (current_chan_num == assoc_chan_num) {
        SetPowerManagementMode(false);
        // TODO(hahnr): wait for TIM, and PS-POLL all buffered frames from AP.
    }
    return ZX_OK;
}

zx_status_t Station::SetPowerManagementMode(bool ps_mode) {
    if (state_ != WlanState::kAssociated) {
        warnf("cannot adjust power management before being associated\n");
        return ZX_OK;
    }

    const common::MacAddr& mymac = device_->GetState()->address();
    size_t len = sizeof(DataFrameHeader);
    fbl::unique_ptr<Buffer> buffer = GetBuffer(len);
    if (buffer == nullptr) { return ZX_ERR_NO_RESOURCES; }
    auto packet = fbl::unique_ptr<Packet>(new Packet(std::move(buffer), len));
    packet->clear();
    packet->set_peer(Packet::Peer::kWlan);
    auto hdr = packet->mut_field<DataFrameHeader>(0);
    hdr->fc.set_type(kData);
    hdr->fc.set_subtype(kNull);
    hdr->fc.set_pwr_mgmt(ps_mode);
    hdr->fc.set_to_ds(1);

    common::MacAddr bssid(bss_->bssid.data());
    hdr->addr1 = bssid;
    hdr->addr2 = mymac;
    hdr->addr3 = bssid;

    uint16_t seq = device_->GetState()->next_seq();
    hdr->sc.set_seq(seq);

    zx_status_t status = device_->SendWlan(std::move(packet));
    if (status != ZX_OK) {
        errorf("could not send power management packet: %d\n", status);
        return status;
    }
    return ZX_OK;
}

zx_status_t Station::SendPsPoll() {
    // TODO(hahnr): We should probably wait for an RSNA if the network is an
    // RSN. Else we cannot work with the incoming data frame.
    if (state_ != WlanState::kAssociated) {
        warnf("cannot send ps-poll before being associated\n");
        return ZX_OK;
    }

    const common::MacAddr& mymac = device_->GetState()->address();
    size_t len = sizeof(PsPollFrame);
    fbl::unique_ptr<Buffer> buffer = GetBuffer(len);
    if (buffer == nullptr) { return ZX_ERR_NO_RESOURCES; }
    auto packet = fbl::unique_ptr<Packet>(new Packet(std::move(buffer), len));
    packet->clear();
    packet->set_peer(Packet::Peer::kWlan);
    auto frame = packet->mut_field<PsPollFrame>(0);
    frame->fc.set_type(kControl);
    frame->fc.set_subtype(kPsPoll);
    frame->aid = aid_;

    frame->bssid = common::MacAddr(bss_->bssid.data());
    frame->ta = mymac;

    zx_status_t status = device_->SendWlan(std::move(packet));
    if (status != ZX_OK) {
        errorf("could not send power management packet: %d\n", status);
        return status;
    }
    return ZX_OK;
}

uint16_t Station::next_seq() {
    uint16_t seq = device_->GetState()->next_seq();
    if (seq == last_seq_) {
        // If the sequence number has rolled over and back to the last seq number we sent to this
        // station, increment again.
        // IEEE Std 802.11-2016, 10.3.2.11.2, Table 10-3, Note TR1
        seq = device_->GetState()->next_seq();
    }
    last_seq_ = seq;
    return seq;
}

zx_time_t Station::deadline_after_bcn_period(zx_duration_t tus) {
    ZX_DEBUG_ASSERT(!bss_.is_null());
    return timer_->Now() + WLAN_TU(bss_->beacon_period * tus);
}

bool Station::IsHTReady() const {
    // TODO(porce): Placeholder.
    // bool bss_is_ht_capable = true;
    // bool client_is_ht_capable = true;
    // bool client_is_ht_config = true;
    // return bss_is_ht_capable && client_is_ht_capable && client_is_ht_config;

    // TODO(porce): GoogleGuest-Legacy fails to offer DHCP upon
    // return true;
    return false;
}

HtCapabilities Station::BuildHtCapabilities() const {
    // TODO(porce): Find intersection of
    // - BSS capabilities
    // - Client radio capabilities
    // - Client configuration

    // Static cooking for Proof-of-Concept
    HtCapabilities htc;
    HtCapabilityInfo& hci = htc.ht_cap_info;

    hci.set_ldpc_coding_cap(0);  // Ralink RT5370 is incapable of LDPC.
    hci.set_chan_width_set(HtCapabilityInfo::TWENTY_ONLY);
    // hci.set_chan_width_set(HtCapabilityInfo::TWENTY_FORTY);
    hci.set_sm_power_save(HtCapabilityInfo::DISABLED);
    hci.set_greenfield(0);
    hci.set_short_gi_20(1);
    hci.set_short_gi_40(0);
    hci.set_tx_stbc(1);
    hci.set_rx_stbc(1);  // one stream.
    hci.set_delayed_block_ack(0);
    hci.set_max_amsdu_len(HtCapabilityInfo::OCTETS_7935);  // Aruba
    // hci.set_max_amsdu_len(HtCapabilityInfo::OCTETS_3839);  // TP-Link
    hci.set_dsss_in_40(0);
    hci.set_intolerant_40(0);
    hci.set_lsig_txop_protect(0);

    AmpduParams& ampdu = htc.ampdu_params;
    ampdu.set_exponent(3);                                // 65535 bytes
    ampdu.set_min_start_spacing(AmpduParams::FOUR_USEC);  // Aruba
    // ampdu.set_min_start_spacing(AmpduParams::EIGHT_USEC);  // TP-Link
    // ampdu.set_min_start_spacing(AmpduParams::SIXTEEN_USEC);

    SupportedMcsSet& mcs = htc.mcs_set;
    mcs.rx_mcs_head.set_bitmask(0xff);  // MCS 0-7
    // mcs.rx_mcs_head.set_bitmask(0xffff);  // MCS 0-15

    HtExtCapabilities& hec = htc.ht_ext_cap;
    hec.set_pco(0);
    hec.set_pco_transition(HtExtCapabilities::PCO_RESERVED);
    hec.set_mcs_feedback(HtExtCapabilities::MCS_NOFEEDBACK);
    hec.set_htc_ht_support(0);
    hec.set_rd_responder(0);

    TxBfCapability& txbf = htc.txbf_cap;
    txbf.set_implicit_rx(0);
    txbf.set_rx_stag_sounding(0);
    txbf.set_tx_stag_sounding(0);
    txbf.set_rx_ndp(0);
    txbf.set_tx_ndp(0);
    txbf.set_implicit(0);
    txbf.set_calibration(TxBfCapability::CALIBRATION_NONE);
    txbf.set_csi(0);
    txbf.set_noncomp_steering(0);
    txbf.set_comp_steering(0);
    txbf.set_csi_feedback(TxBfCapability::FEEDBACK_NONE);
    txbf.set_noncomp_feedback(TxBfCapability::FEEDBACK_NONE);
    txbf.set_comp_feedback(TxBfCapability::FEEDBACK_NONE);
    txbf.set_min_grouping(TxBfCapability::MIN_GROUP_ONE);
    txbf.set_csi_antennas_human(1);           // 1 antenna
    txbf.set_noncomp_steering_ants_human(1);  // 1 antenna
    txbf.set_comp_steering_ants_human(1);     // 1 antenna
    txbf.set_csi_rows_human(1);               // 1 antenna
    txbf.set_chan_estimation_human(1);        // # space-time stream

    AselCapability& asel = htc.asel_cap;
    asel.set_asel(0);
    asel.set_csi_feedback_tx_asel(0);
    asel.set_explicit_csi_feedback(0);
    asel.set_antenna_idx_feedback(0);
    asel.set_rx_asel(0);
    asel.set_tx_sounding_ppdu(0);

    return htc;  // 28 bytes.
}

}  // namespace wlan
