|  | // 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 |