123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- // Copyright 2017 The Chromium 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 "net/base/network_interfaces_fuchsia.h"
- #include <lib/sys/cpp/component_context.h>
- #include <string>
- #include <utility>
- #include "base/format_macros.h"
- #include "base/fuchsia/fuchsia_logging.h"
- #include "base/fuchsia/process_context.h"
- #include "net/base/network_interfaces.h"
- namespace net {
- namespace internal {
- namespace {
- IPAddress FuchsiaIpAddressToIPAddress(const fuchsia::net::IpAddress& address) {
- switch (address.Which()) {
- case fuchsia::net::IpAddress::kIpv4:
- return IPAddress(address.ipv4().addr.data(), address.ipv4().addr.size());
- case fuchsia::net::IpAddress::kIpv6:
- return IPAddress(address.ipv6().addr.data(), address.ipv6().addr.size());
- default:
- return IPAddress();
- }
- }
- } // namespace
- // static
- absl::optional<InterfaceProperties> InterfaceProperties::VerifyAndCreate(
- fuchsia::net::interfaces::Properties properties) {
- if (!internal::VerifyCompleteInterfaceProperties(properties))
- return absl::nullopt;
- return absl::make_optional(InterfaceProperties(std::move(properties)));
- }
- InterfaceProperties::InterfaceProperties(
- fuchsia::net::interfaces::Properties properties)
- : properties_(std::move(properties)) {}
- InterfaceProperties::InterfaceProperties(InterfaceProperties&& interface) =
- default;
- InterfaceProperties& InterfaceProperties::operator=(
- InterfaceProperties&& interface) = default;
- InterfaceProperties::~InterfaceProperties() = default;
- bool InterfaceProperties::Update(
- fuchsia::net::interfaces::Properties properties) {
- if (!properties.has_id() || properties_.id() != properties.id()) {
- LOG(WARNING) << "Update failed: invalid properties.";
- return false;
- }
- if (properties.has_addresses()) {
- for (const auto& fidl_address : properties.addresses()) {
- if (!fidl_address.has_addr()) {
- LOG(WARNING) << "Update failed: invalid properties.";
- return false;
- }
- }
- properties_.set_addresses(std::move(*properties.mutable_addresses()));
- }
- if (properties.has_online())
- properties_.set_online(properties.online());
- if (properties.has_has_default_ipv4_route())
- properties_.set_has_default_ipv4_route(properties.has_default_ipv4_route());
- if (properties.has_has_default_ipv6_route())
- properties_.set_has_default_ipv6_route(properties.has_default_ipv6_route());
- return true;
- }
- void InterfaceProperties::AppendNetworkInterfaces(
- NetworkInterfaceList* interfaces) const {
- for (const auto& fidl_address : properties_.addresses()) {
- IPAddress address = FuchsiaIpAddressToIPAddress(fidl_address.addr().addr);
- if (address.empty()) {
- LOG(WARNING) << "Unknown fuchsia.net/IpAddress variant "
- << fidl_address.addr().addr.Which();
- continue;
- }
- // TODO(crbug.com/1131220): Set correct attributes once available in
- // fuchsia::net::interfaces::Properties.
- const int kAttributes = 0;
- interfaces->emplace_back(
- properties_.name(), properties_.name(), properties_.id(),
- internal::ConvertConnectionType(properties_.device_class()),
- std::move(address), fidl_address.addr().prefix_len, kAttributes);
- }
- }
- bool InterfaceProperties::IsPubliclyRoutable() const {
- if (!properties_.online())
- return false;
- for (const auto& fidl_address : properties_.addresses()) {
- const IPAddress address =
- FuchsiaIpAddressToIPAddress(fidl_address.addr().addr);
- if ((address.IsIPv4() && properties_.has_default_ipv4_route() &&
- !address.IsLinkLocal()) ||
- (address.IsIPv6() && properties_.has_default_ipv6_route() &&
- address.IsPubliclyRoutable())) {
- return true;
- }
- }
- return false;
- }
- NetworkChangeNotifier::ConnectionType ConvertConnectionType(
- const fuchsia::net::interfaces::DeviceClass& device_class) {
- switch (device_class.Which()) {
- case fuchsia::net::interfaces::DeviceClass::kLoopback:
- return NetworkChangeNotifier::CONNECTION_NONE;
- case fuchsia::net::interfaces::DeviceClass::kDevice:
- switch (device_class.device()) {
- case fuchsia::hardware::network::DeviceClass::WLAN:
- return NetworkChangeNotifier::CONNECTION_WIFI;
- case fuchsia::hardware::network::DeviceClass::ETHERNET:
- return NetworkChangeNotifier::CONNECTION_ETHERNET;
- default:
- return NetworkChangeNotifier::CONNECTION_UNKNOWN;
- }
- default:
- LOG(WARNING) << "Received unknown fuchsia.net.interfaces/DeviceClass "
- << device_class.Which();
- return NetworkChangeNotifier::CONNECTION_UNKNOWN;
- }
- }
- fuchsia::net::interfaces::WatcherHandle ConnectInterfacesWatcher() {
- fuchsia::net::interfaces::StateSyncPtr state;
- zx_status_t status =
- base::ComponentContextForProcess()->svc()->Connect(state.NewRequest());
- ZX_CHECK(status == ZX_OK, status) << "Connect()";
- fuchsia::net::interfaces::WatcherHandle watcher;
- state->GetWatcher({} /*options*/, watcher.NewRequest());
- return watcher;
- }
- bool VerifyCompleteInterfaceProperties(
- const fuchsia::net::interfaces::Properties& properties) {
- if (!properties.has_id())
- return false;
- if (!properties.has_addresses())
- return false;
- for (const auto& fidl_address : properties.addresses()) {
- if (!fidl_address.has_addr())
- return false;
- }
- if (!properties.has_online())
- return false;
- if (!properties.has_device_class())
- return false;
- if (!properties.has_has_default_ipv4_route())
- return false;
- if (!properties.has_has_default_ipv6_route())
- return false;
- return true;
- }
- absl::optional<ExistingInterfaceProperties> GetExistingInterfaces(
- const fuchsia::net::interfaces::WatcherSyncPtr& watcher) {
- ExistingInterfaceProperties existing_interfaces;
- for (;;) {
- fuchsia::net::interfaces::Event event;
- zx_status_t status = watcher->Watch(&event);
- if (status != ZX_OK) {
- ZX_LOG(ERROR, status) << "GetExistingInterfaces: Watch() failed";
- return absl::nullopt;
- }
- switch (event.Which()) {
- case fuchsia::net::interfaces::Event::Tag::kExisting: {
- absl::optional<InterfaceProperties> interface =
- InterfaceProperties::VerifyAndCreate(std::move(event.existing()));
- if (!interface) {
- LOG(ERROR) << "GetExistingInterfaces: Invalid kExisting event.";
- return absl::nullopt;
- }
- uint64_t id = interface->id();
- existing_interfaces.emplace_back(id, std::move(*interface));
- break;
- }
- case fuchsia::net::interfaces::Event::Tag::kIdle:
- // Idle means we've listed all the existing interfaces. We can stop
- // fetching events.
- return existing_interfaces;
- default:
- LOG(ERROR) << "GetExistingInterfaces: Unexpected event received.";
- return absl::nullopt;
- }
- }
- }
- } // namespace internal
- bool GetNetworkList(NetworkInterfaceList* networks, int policy) {
- DCHECK(networks);
- fuchsia::net::interfaces::WatcherHandle handle =
- internal::ConnectInterfacesWatcher();
- fuchsia::net::interfaces::WatcherSyncPtr watcher = handle.BindSync();
- // TODO(crbug.com/1131238): Use NetworkChangeNotifier's cached interface
- // list.
- absl::optional<internal::ExistingInterfaceProperties> existing_interfaces =
- internal::GetExistingInterfaces(watcher);
- if (!existing_interfaces)
- return false;
- handle = watcher.Unbind();
- for (const auto& interface_entry : *existing_interfaces) {
- if (!interface_entry.second.online()) {
- // GetNetworkList() only returns online interfaces.
- continue;
- }
- if (interface_entry.second.device_class().is_loopback()) {
- // GetNetworkList() returns all interfaces except loopback.
- continue;
- }
- interface_entry.second.AppendNetworkInterfaces(networks);
- }
- return true;
- }
- std::string GetWifiSSID() {
- NOTIMPLEMENTED();
- return std::string();
- }
- } // namespace net
|