1 // Copyright 2017 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "net/base/network_interfaces_fuchsia.h" 6 7 #include <fuchsia/net/interfaces/cpp/fidl.h> 8 #include <zircon/types.h> 9 10 #include <optional> 11 #include <string> 12 #include <utility> 13 14 #include "base/logging.h" 15 #include "net/base/fuchsia/network_interface_cache.h" 16 #include "net/base/network_change_notifier.h" 17 #include "net/base/network_change_notifier_fuchsia.h" 18 #include "net/base/network_interfaces.h" 19 20 namespace net { 21 namespace internal { 22 namespace { 23 FuchsiaIpAddressToIPAddress(const fuchsia::net::IpAddress & address)24IPAddress FuchsiaIpAddressToIPAddress(const fuchsia::net::IpAddress& address) { 25 switch (address.Which()) { 26 case fuchsia::net::IpAddress::kIpv4: 27 return IPAddress(address.ipv4().addr); 28 case fuchsia::net::IpAddress::kIpv6: 29 return IPAddress(address.ipv6().addr); 30 default: 31 return IPAddress(); 32 } 33 } 34 35 } // namespace 36 37 // static VerifyAndCreate(fuchsia::net::interfaces::Properties properties)38std::optional<InterfaceProperties> InterfaceProperties::VerifyAndCreate( 39 fuchsia::net::interfaces::Properties properties) { 40 if (!internal::VerifyCompleteInterfaceProperties(properties)) 41 return std::nullopt; 42 return std::make_optional(InterfaceProperties(std::move(properties))); 43 } 44 InterfaceProperties(fuchsia::net::interfaces::Properties properties)45InterfaceProperties::InterfaceProperties( 46 fuchsia::net::interfaces::Properties properties) 47 : properties_(std::move(properties)) {} 48 49 InterfaceProperties::InterfaceProperties(InterfaceProperties&& interface) = 50 default; 51 52 InterfaceProperties& InterfaceProperties::operator=( 53 InterfaceProperties&& interface) = default; 54 55 InterfaceProperties::~InterfaceProperties() = default; 56 Update(fuchsia::net::interfaces::Properties properties)57bool InterfaceProperties::Update( 58 fuchsia::net::interfaces::Properties properties) { 59 if (!properties.has_id() || properties_.id() != properties.id()) { 60 LOG(ERROR) << "Update failed: invalid properties."; 61 return false; 62 } 63 64 if (properties.has_addresses()) { 65 for (const auto& fidl_address : properties.addresses()) { 66 if (!fidl_address.has_addr()) { 67 LOG(ERROR) << "Update failed: invalid properties."; 68 return false; 69 } 70 } 71 properties_.set_addresses(std::move(*properties.mutable_addresses())); 72 } 73 74 if (properties.has_online()) 75 properties_.set_online(properties.online()); 76 if (properties.has_has_default_ipv4_route()) 77 properties_.set_has_default_ipv4_route(properties.has_default_ipv4_route()); 78 if (properties.has_has_default_ipv6_route()) 79 properties_.set_has_default_ipv6_route(properties.has_default_ipv6_route()); 80 81 return true; 82 } 83 AppendNetworkInterfaces(NetworkInterfaceList * interfaces) const84void InterfaceProperties::AppendNetworkInterfaces( 85 NetworkInterfaceList* interfaces) const { 86 for (const auto& fidl_address : properties_.addresses()) { 87 IPAddress address = FuchsiaIpAddressToIPAddress(fidl_address.addr().addr); 88 if (address.empty()) { 89 LOG(WARNING) << "Unknown fuchsia.net/IpAddress variant " 90 << fidl_address.addr().addr.Which(); 91 continue; 92 } 93 94 const int kAttributes = 0; 95 interfaces->emplace_back( 96 properties_.name(), properties_.name(), properties_.id(), 97 internal::ConvertConnectionType(properties_.device_class()), 98 std::move(address), fidl_address.addr().prefix_len, kAttributes); 99 } 100 } 101 IsPubliclyRoutable() const102bool InterfaceProperties::IsPubliclyRoutable() const { 103 if (!properties_.online()) 104 return false; 105 106 for (const auto& fidl_address : properties_.addresses()) { 107 const IPAddress address = 108 FuchsiaIpAddressToIPAddress(fidl_address.addr().addr); 109 if ((address.IsIPv4() && properties_.has_default_ipv4_route() && 110 !address.IsLinkLocal()) || 111 (address.IsIPv6() && properties_.has_default_ipv6_route() && 112 address.IsPubliclyRoutable())) { 113 return true; 114 } 115 } 116 return false; 117 } 118 ConvertConnectionType(const fuchsia::net::interfaces::DeviceClass & device_class)119NetworkChangeNotifier::ConnectionType ConvertConnectionType( 120 const fuchsia::net::interfaces::DeviceClass& device_class) { 121 switch (device_class.Which()) { 122 case fuchsia::net::interfaces::DeviceClass::kLoopback: 123 return NetworkChangeNotifier::CONNECTION_NONE; 124 case fuchsia::net::interfaces::DeviceClass::kDevice: 125 switch (device_class.device()) { 126 case fuchsia::hardware::network::DeviceClass::WLAN: 127 return NetworkChangeNotifier::CONNECTION_WIFI; 128 case fuchsia::hardware::network::DeviceClass::ETHERNET: 129 return NetworkChangeNotifier::CONNECTION_ETHERNET; 130 default: 131 return NetworkChangeNotifier::CONNECTION_UNKNOWN; 132 } 133 default: 134 LOG(WARNING) << "Received unknown fuchsia.net.interfaces/DeviceClass " 135 << device_class.Which(); 136 return NetworkChangeNotifier::CONNECTION_UNKNOWN; 137 } 138 } 139 VerifyCompleteInterfaceProperties(const fuchsia::net::interfaces::Properties & properties)140bool VerifyCompleteInterfaceProperties( 141 const fuchsia::net::interfaces::Properties& properties) { 142 if (!properties.has_id()) 143 return false; 144 if (!properties.has_addresses()) 145 return false; 146 for (const auto& fidl_address : properties.addresses()) { 147 if (!fidl_address.has_addr()) 148 return false; 149 } 150 if (!properties.has_online()) 151 return false; 152 if (!properties.has_device_class()) 153 return false; 154 if (!properties.has_has_default_ipv4_route()) 155 return false; 156 if (!properties.has_has_default_ipv6_route()) 157 return false; 158 if (!properties.has_name()) { 159 return false; 160 } 161 return true; 162 } 163 164 } // namespace internal 165 GetNetworkList(NetworkInterfaceList * networks,int policy)166bool GetNetworkList(NetworkInterfaceList* networks, int policy) { 167 DCHECK(networks); 168 169 const internal::NetworkInterfaceCache* cache_ptr = 170 NetworkChangeNotifier::GetNetworkInterfaceCache(); 171 if (cache_ptr) { 172 return cache_ptr->GetOnlineInterfaces(networks); 173 } 174 175 fuchsia::net::interfaces::WatcherHandle watcher_handle = 176 internal::ConnectInterfacesWatcher(); 177 std::vector<fuchsia::net::interfaces::Properties> interfaces; 178 179 auto handle_or_status = internal::ReadExistingNetworkInterfacesFromNewWatcher( 180 std::move(watcher_handle), interfaces); 181 if (!handle_or_status.has_value()) { 182 return false; 183 } 184 185 internal::NetworkInterfaceCache temp_cache(/*require_wlan=*/false); 186 auto change_bits = temp_cache.AddInterfaces(std::move(interfaces)); 187 if (!change_bits.has_value()) { 188 return false; 189 } 190 191 return temp_cache.GetOnlineInterfaces(networks); 192 } 193 GetWifiSSID()194std::string GetWifiSSID() { 195 NOTIMPLEMENTED(); 196 return std::string(); 197 } 198 199 } // namespace net 200