blob: 6aad1bb44b5a590f53adfd3e7ace706f95250da2 [file]
// Copyright 2020 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 "mac_adapter.h"
#include <lib/sync/completion.h>
#include <algorithm>
#include <fbl/alloc_checker.h>
#include <fbl/auto_lock.h>
namespace network {
namespace tun {
zx::result<std::unique_ptr<MacAdapter>> MacAdapter::Create(
MacAdapterParent* parent, fdf::UnownedUnsynchronizedDispatcher dispatcher,
fuchsia_net::wire::MacAddress mac, bool promisc_only) {
fbl::AllocChecker ac;
std::unique_ptr<MacAdapter> adapter(
new (&ac) MacAdapter(parent, std::move(dispatcher), mac, promisc_only));
if (!ac.check()) {
return zx::error(ZX_ERR_NO_MEMORY);
}
return zx::ok(std::move(adapter));
}
void MacAdapter::GetAddress(fdf::Arena& arena, GetAddressCompleter::Sync& completer) {
completer.buffer(arena).Reply(mac_);
}
void MacAdapter::GetFeatures(fdf::Arena& arena, GetFeaturesCompleter::Sync& completer) {
auto builder = fuchsia_hardware_network_driver::wire::Features::Builder(arena);
if (promisc_only_) {
builder.multicast_filter_count(0);
builder.supported_modes(
fuchsia_hardware_network_driver::wire::SupportedMacFilterMode::kPromiscuous);
} else {
builder.multicast_filter_count(fuchsia_net_tun::wire::kMaxMulticastFilters);
builder.supported_modes(
fuchsia_hardware_network_driver::wire::SupportedMacFilterMode::kMulticastPromiscuous |
fuchsia_hardware_network_driver::wire::SupportedMacFilterMode::kMulticastFilter |
fuchsia_hardware_network_driver::wire::SupportedMacFilterMode::kPromiscuous);
}
completer.buffer(arena).Reply(builder.Build());
}
void MacAdapter::SetMode(fuchsia_hardware_network_driver::wire::MacAddrSetModeRequest* request,
fdf::Arena& arena, SetModeCompleter::Sync& completer) {
{
fbl::AutoLock lock(&state_lock_);
fuchsia_hardware_network::wire::MacFilterMode filter_mode = request->mode;
mac_state_.mode = filter_mode;
mac_state_.multicast_filters.clear();
mac_state_.multicast_filters.reserve(request->multicast_macs.size());
std::ranges::copy(request->multicast_macs, std::back_inserter(mac_state_.multicast_filters));
parent_->OnMacStateChanged(this);
}
completer.buffer(arena).Reply();
}
fdf::ClientEnd<fuchsia_hardware_network_driver::MacAddr> MacAdapter::BindDriver() {
ZX_ASSERT(!binding_);
auto [client, server] = fdf::Endpoints<fuchsia_hardware_network_driver::MacAddr>::Create();
binding_ = fdf::BindServer(dispatcher_->get(), std::move(server), this);
return std::move(client);
}
MacAdapter::~MacAdapter() {
if (binding_) {
binding_->Unbind();
}
}
MacState MacAdapter::GetMacState() {
fbl::AutoLock lock(&state_lock_);
return mac_state_;
}
} // namespace tun
} // namespace network