Avi Drissman | 6459548 | 2022-09-14 20:52:29 | [diff] [blame] | 1 | // Copyright 2017 The Chromium Authors |
Sergey Ulanov | 2beef3d | 2017-10-19 21:53:53 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
Kevin Marshall | 3e89fd7 | 2018-06-05 21:29:10 | [diff] [blame] | 5 | #include "net/base/network_interfaces_fuchsia.h" |
Sergey Ulanov | 2beef3d | 2017-10-19 21:53:53 | [diff] [blame] | 6 | |
David Song | ae64e8f4d | 2023-01-17 21:33:17 | [diff] [blame] | 7 | #include <fuchsia/net/interfaces/cpp/fidl.h> |
| 8 | #include <zircon/types.h> |
Sergey Ulanov | 2beef3d | 2017-10-19 21:53:53 | [diff] [blame] | 9 | |
Kevin Marshall | 3e89fd7 | 2018-06-05 21:29:10 | [diff] [blame] | 10 | #include <string> |
| 11 | #include <utility> |
| 12 | |
David Song | ae64e8f4d | 2023-01-17 21:33:17 | [diff] [blame] | 13 | #include "base/logging.h" |
| 14 | #include "net/base/fuchsia/network_interface_cache.h" |
| 15 | #include "net/base/network_change_notifier.h" |
| 16 | #include "net/base/network_change_notifier_fuchsia.h" |
Kevin Marshall | 3e89fd7 | 2018-06-05 21:29:10 | [diff] [blame] | 17 | #include "net/base/network_interfaces.h" |
David Song | ae64e8f4d | 2023-01-17 21:33:17 | [diff] [blame] | 18 | #include "third_party/abseil-cpp/absl/types/optional.h" |
Sergey Ulanov | 2beef3d | 2017-10-19 21:53:53 | [diff] [blame] | 19 | |
| 20 | namespace net { |
Kevin Marshall | 3e89fd7 | 2018-06-05 21:29:10 | [diff] [blame] | 21 | namespace internal { |
| 22 | namespace { |
| 23 | |
Marina Ciocea | c05c3e3 | 2020-12-03 19:36:58 | [diff] [blame] | 24 | IPAddress FuchsiaIpAddressToIPAddress(const fuchsia::net::IpAddress& address) { |
| 25 | switch (address.Which()) { |
| 26 | case fuchsia::net::IpAddress::kIpv4: |
| 27 | return IPAddress(address.ipv4().addr.data(), address.ipv4().addr.size()); |
| 28 | case fuchsia::net::IpAddress::kIpv6: |
| 29 | return IPAddress(address.ipv6().addr.data(), address.ipv6().addr.size()); |
| 30 | default: |
| 31 | return IPAddress(); |
Kevin Marshall | 3e89fd7 | 2018-06-05 21:29:10 | [diff] [blame] | 32 | } |
Kevin Marshall | 3e89fd7 | 2018-06-05 21:29:10 | [diff] [blame] | 33 | } |
| 34 | |
| 35 | } // namespace |
Sergey Ulanov | 2beef3d | 2017-10-19 21:53:53 | [diff] [blame] | 36 | |
Marina Ciocea | c05c3e3 | 2020-12-03 19:36:58 | [diff] [blame] | 37 | // static |
Anton Bikineev | 068d291 | 2021-05-15 20:43:52 | [diff] [blame] | 38 | absl::optional<InterfaceProperties> InterfaceProperties::VerifyAndCreate( |
Marina Ciocea | c05c3e3 | 2020-12-03 19:36:58 | [diff] [blame] | 39 | fuchsia::net::interfaces::Properties properties) { |
| 40 | if (!internal::VerifyCompleteInterfaceProperties(properties)) |
Anton Bikineev | 068d291 | 2021-05-15 20:43:52 | [diff] [blame] | 41 | return absl::nullopt; |
| 42 | return absl::make_optional(InterfaceProperties(std::move(properties))); |
Marina Ciocea | c05c3e3 | 2020-12-03 19:36:58 | [diff] [blame] | 43 | } |
| 44 | |
| 45 | InterfaceProperties::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 | |
| 57 | bool InterfaceProperties::Update( |
| 58 | fuchsia::net::interfaces::Properties properties) { |
| 59 | if (!properties.has_id() || properties_.id() != properties.id()) { |
David Song | ae64e8f4d | 2023-01-17 21:33:17 | [diff] [blame] | 60 | LOG(ERROR) << "Update failed: invalid properties."; |
Marina Ciocea | c05c3e3 | 2020-12-03 19:36:58 | [diff] [blame] | 61 | return false; |
| 62 | } |
| 63 | |
| 64 | if (properties.has_addresses()) { |
| 65 | for (const auto& fidl_address : properties.addresses()) { |
| 66 | if (!fidl_address.has_addr()) { |
David Song | ae64e8f4d | 2023-01-17 21:33:17 | [diff] [blame] | 67 | LOG(ERROR) << "Update failed: invalid properties."; |
Marina Ciocea | c05c3e3 | 2020-12-03 19:36:58 | [diff] [blame] | 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 | |
| 84 | void InterfaceProperties::AppendNetworkInterfaces( |
| 85 | NetworkInterfaceList* interfaces) const { |
Marina Ciocea | c05c3e3 | 2020-12-03 19:36:58 | [diff] [blame] | 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 | |
Marina Ciocea | c05c3e3 | 2020-12-03 19:36:58 | [diff] [blame] | 94 | const int kAttributes = 0; |
Marina Ciocea | c05c3e3 | 2020-12-03 19:36:58 | [diff] [blame] | 95 | interfaces->emplace_back( |
Peter Johnston | 501ae4d6 | 2020-12-15 17:22:53 | [diff] [blame] | 96 | properties_.name(), properties_.name(), properties_.id(), |
Marina Ciocea | c05c3e3 | 2020-12-03 19:36:58 | [diff] [blame] | 97 | internal::ConvertConnectionType(properties_.device_class()), |
| 98 | std::move(address), fidl_address.addr().prefix_len, kAttributes); |
| 99 | } |
| 100 | } |
| 101 | |
| 102 | bool 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 | |
Aidan Wolter | d89b754 | 2019-01-24 11:01:21 | [diff] [blame] | 119 | NetworkChangeNotifier::ConnectionType ConvertConnectionType( |
Marina Ciocea | c05c3e3 | 2020-12-03 19:36:58 | [diff] [blame] | 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; |
Aidan Wolter | d89b754 | 2019-01-24 11:01:21 | [diff] [blame] | 137 | } |
Aidan Wolter | d89b754 | 2019-01-24 11:01:21 | [diff] [blame] | 138 | } |
| 139 | |
Marina Ciocea | c05c3e3 | 2020-12-03 19:36:58 | [diff] [blame] | 140 | bool 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; |
Kevin Marshall | 3e89fd7 | 2018-06-05 21:29:10 | [diff] [blame] | 149 | } |
Marina Ciocea | c05c3e3 | 2020-12-03 19:36:58 | [diff] [blame] | 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; |
David Song | ae64e8f4d | 2023-01-17 21:33:17 | [diff] [blame] | 158 | if (!properties.has_name()) { |
| 159 | return false; |
Stephen Roe | b9b9702 | 2020-11-20 03:57:23 | [diff] [blame] | 160 | } |
David Song | ae64e8f4d | 2023-01-17 21:33:17 | [diff] [blame] | 161 | return true; |
Kevin Marshall | 3e89fd7 | 2018-06-05 21:29:10 | [diff] [blame] | 162 | } |
| 163 | |
| 164 | } // namespace internal |
| 165 | |
Sergey Ulanov | 2beef3d | 2017-10-19 21:53:53 | [diff] [blame] | 166 | bool GetNetworkList(NetworkInterfaceList* networks, int policy) { |
Kevin Marshall | 3e89fd7 | 2018-06-05 21:29:10 | [diff] [blame] | 167 | DCHECK(networks); |
Sergey Ulanov | f7b2214 | 2018-05-01 00:58:32 | [diff] [blame] | 168 | |
David Song | ae64e8f4d | 2023-01-17 21:33:17 | [diff] [blame] | 169 | const internal::NetworkInterfaceCache* cache_ptr = |
| 170 | NetworkChangeNotifier::GetNetworkInterfaceCache(); |
| 171 | if (cache_ptr) { |
| 172 | return cache_ptr->GetOnlineInterfaces(networks); |
Stephen Roe | b9b9702 | 2020-11-20 03:57:23 | [diff] [blame] | 173 | } |
David Song | ae64e8f4d | 2023-01-17 21:33:17 | [diff] [blame] | 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); |
Sergey Ulanov | 2beef3d | 2017-10-19 21:53:53 | [diff] [blame] | 192 | } |
| 193 | |
| 194 | std::string GetWifiSSID() { |
| 195 | NOTIMPLEMENTED(); |
| 196 | return std::string(); |
| 197 | } |
| 198 | |
| 199 | } // namespace net |