blob: 7fa244c12a4ae8630a4550b7f79721747ec0045a [file] [log] [blame]
// 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 <fuchsia/netstack/cpp/fidl.h>
#include <string>
#include <utility>
#include "base/format_macros.h"
#include "base/fuchsia/component_context.h"
#include "base/fuchsia/fuchsia_logging.h"
#include "base/strings/stringprintf.h"
#include "net/base/ip_endpoint.h"
#include "net/base/network_change_notifier.h"
#include "net/base/network_interfaces.h"
#include "starboard/types.h"
namespace net {
namespace internal {
namespace {
using ConnectionType = NetworkChangeNotifier::ConnectionType;
ConnectionType ConvertConnectionType(
const fuchsia::netstack::NetInterface& iface) {
return iface.features & fuchsia::netstack::interfaceFeatureWlan
? NetworkChangeNotifier::CONNECTION_WIFI
: NetworkChangeNotifier::CONNECTION_UNKNOWN;
}
// Converts a Netstack NetInterface |interface| to a Chrome NetworkInterface.
// NetInterfaces may be bound to multiple IPv6 addresses. |address_index| is
// used to specify which address to use for the conversion.
// address_index = 0: Uses NetInterface::addr, NetInterface::netmask.
// address_index >= 1: Uses NetInterface::ipv6addrs[], with the array index
// offset by one.
NetworkInterface NetworkInterfaceFromAddress(
const fuchsia::netstack::NetInterface& interface,
size_t address_index) {
// TODO(sergeyu): attributes field is used to return address state for IPv6
// addresses. Currently Netstack doesn't provide this information.
const int attributes = 0;
IPAddress address;
uint8_t prefix_length;
if (address_index == 0) {
address = NetAddressToIPAddress(interface.addr);
prefix_length = MaskPrefixLength(NetAddressToIPAddress(interface.netmask));
} else {
CHECK_LE(address_index, interface.ipv6addrs->size());
address =
NetAddressToIPAddress(interface.ipv6addrs->at(address_index - 1).addr);
prefix_length = interface.ipv6addrs->at(address_index - 1).prefix_len;
}
return NetworkInterface(*interface.name, interface.name, interface.id,
ConvertConnectionType(interface), address,
prefix_length, attributes);
}
} // namespace
IPAddress NetAddressToIPAddress(const fuchsia::netstack::NetAddress& addr) {
if (addr.ipv4) {
return IPAddress(addr.ipv4->addr.data(), addr.ipv4->addr.count());
}
if (addr.ipv6) {
return IPAddress(addr.ipv6->addr.data(), addr.ipv6->addr.count());
}
return IPAddress();
}
std::vector<NetworkInterface> NetInterfaceToNetworkInterfaces(
const fuchsia::netstack::NetInterface& iface_in) {
std::vector<NetworkInterface> output;
// Check if the interface is up.
if (!(iface_in.flags & fuchsia::netstack::NetInterfaceFlagUp))
return output;
// Skip loopback.
if (iface_in.features & fuchsia::netstack::interfaceFeatureLoopback)
return output;
output.push_back(NetworkInterfaceFromAddress(iface_in, 0));
// Append interface entries for all additional IPv6 addresses.
for (size_t i = 0; i < iface_in.ipv6addrs->size(); ++i) {
output.push_back(NetworkInterfaceFromAddress(iface_in, i + 1));
}
return output;
}
} // namespace internal
bool GetNetworkList(NetworkInterfaceList* networks, int policy) {
DCHECK(networks);
fuchsia::netstack::NetstackSyncPtr netstack =
base::fuchsia::ComponentContext::GetDefault()
->ConnectToServiceSync<fuchsia::netstack::Netstack>();
// TODO(kmarshall): Use NetworkChangeNotifier's cached interface list.
fidl::VectorPtr<fuchsia::netstack::NetInterface> interfaces;
zx_status_t status = netstack->GetInterfaces(&interfaces);
if (status != ZX_OK) {
ZX_LOG(ERROR, status) << "fuchsia::netstack::GetInterfaces()";
return false;
}
for (auto& interface : interfaces.get()) {
auto converted = internal::NetInterfaceToNetworkInterfaces(interface);
std::move(converted.begin(), converted.end(),
std::back_inserter(*networks));
}
return true;
}
std::string GetWifiSSID() {
NOTIMPLEMENTED();
return std::string();
}
} // namespace net