xref: /aosp_15_r20/external/cronet/net/base/network_interfaces_fuchsia.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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)24 IPAddress 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)38 std::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)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 
Update(fuchsia::net::interfaces::Properties properties)57 bool 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) const84 void 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() const102 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 
ConvertConnectionType(const fuchsia::net::interfaces::DeviceClass & device_class)119 NetworkChangeNotifier::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)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;
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)166 bool 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()194 std::string GetWifiSSID() {
195   NOTIMPLEMENTED();
196   return std::string();
197 }
198 
199 }  // namespace net
200