1 // Copyright 2020 The Chromium Authors. All rights reserved.
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 "chrome/browser/chromeos/net/network_diagnostics/dns_resolver_present_routine.h"
6 
7 #include <string>
8 #include <utility>
9 #include <vector>
10 
11 #include "base/bind.h"
12 #include "base/optional.h"
13 #include "chromeos/services/network_config/in_process_instance.h"
14 #include "chromeos/services/network_config/public/cpp/cros_network_config_util.h"
15 #include "mojo/public/cpp/bindings/pending_receiver.h"
16 #include "mojo/public/cpp/bindings/remote.h"
17 
18 namespace chromeos {
19 namespace network_diagnostics {
20 namespace {
21 
NameServersAreWellFormed(const std::vector<std::string> & name_servers)22 bool NameServersAreWellFormed(const std::vector<std::string>& name_servers) {
23   for (const auto& name_server : name_servers) {
24     if (name_server == "0.0.0.0" || name_server == "::/0") {
25       return false;
26     }
27   }
28   return true;
29 }
30 
NameServersAreNonEmpty(const std::vector<std::string> & name_servers)31 bool NameServersAreNonEmpty(const std::vector<std::string>& name_servers) {
32   for (const auto& name_server : name_servers) {
33     if (name_server.empty()) {
34       return false;
35     }
36   }
37   return true;
38 }
39 
40 }  // namespace
41 
DnsResolverPresentRoutine()42 DnsResolverPresentRoutine::DnsResolverPresentRoutine() {
43   set_verdict(mojom::RoutineVerdict::kNotRun);
44   network_config::BindToInProcessInstance(
45       remote_cros_network_config_.BindNewPipeAndPassReceiver());
46 }
47 
48 DnsResolverPresentRoutine::~DnsResolverPresentRoutine() = default;
49 
CanRun()50 bool DnsResolverPresentRoutine::CanRun() {
51   DCHECK(remote_cros_network_config_);
52   return true;
53 }
54 
RunRoutine(mojom::NetworkDiagnosticsRoutines::DnsResolverPresentCallback callback)55 void DnsResolverPresentRoutine::RunRoutine(
56     mojom::NetworkDiagnosticsRoutines::DnsResolverPresentCallback callback) {
57   if (!CanRun()) {
58     std::move(callback).Run(verdict(), std::move(problems_));
59     return;
60   }
61   routine_completed_callback_ = std::move(callback);
62   FetchActiveNetworks();
63 }
64 
AnalyzeResultsAndExecuteCallback()65 void DnsResolverPresentRoutine::AnalyzeResultsAndExecuteCallback() {
66   if (!name_servers_found_) {
67     set_verdict(mojom::RoutineVerdict::kProblem);
68     problems_.emplace_back(
69         mojom::DnsResolverPresentProblem::kNoNameServersFound);
70   } else if (!non_empty_name_servers_) {
71     set_verdict(mojom::RoutineVerdict::kProblem);
72     problems_.emplace_back(mojom::DnsResolverPresentProblem::kEmptyNameServers);
73   } else if (!well_formed_name_servers_) {
74     set_verdict(mojom::RoutineVerdict::kProblem);
75     problems_.emplace_back(
76         mojom::DnsResolverPresentProblem::kMalformedNameServers);
77   } else {
78     // The availability of non-empty, well-formed nameservers ensures that DNS
79     // resolution should be possible.
80     set_verdict(mojom::RoutineVerdict::kNoProblem);
81   }
82   std::move(routine_completed_callback_).Run(verdict(), std::move(problems_));
83 }
84 
FetchActiveNetworks()85 void DnsResolverPresentRoutine::FetchActiveNetworks() {
86   DCHECK(remote_cros_network_config_);
87   remote_cros_network_config_->GetNetworkStateList(
88       network_config::mojom::NetworkFilter::New(
89           network_config::mojom::FilterType::kActive,
90           network_config::mojom::NetworkType::kAll,
91           network_config::mojom::kNoLimit),
92       base::BindOnce(&DnsResolverPresentRoutine::OnNetworkStateListReceived,
93                      base::Unretained(this)));
94 }
95 
FetchManagedProperties(const std::string & guid)96 void DnsResolverPresentRoutine::FetchManagedProperties(
97     const std::string& guid) {
98   remote_cros_network_config_->GetManagedProperties(
99       guid,
100       base::BindOnce(&DnsResolverPresentRoutine::OnManagedPropertiesReceived,
101                      base::Unretained(this)));
102 }
103 
OnManagedPropertiesReceived(network_config::mojom::ManagedPropertiesPtr managed_properties)104 void DnsResolverPresentRoutine::OnManagedPropertiesReceived(
105     network_config::mojom::ManagedPropertiesPtr managed_properties) {
106   if (!managed_properties || !managed_properties->ip_configs.has_value()) {
107     AnalyzeResultsAndExecuteCallback();
108     return;
109   }
110   for (const auto& ip_config : managed_properties->ip_configs.value()) {
111     if (ip_config->name_servers.has_value() &&
112         ip_config->name_servers->size() != 0) {
113       name_servers_found_ = true;
114       if (NameServersAreNonEmpty(ip_config->name_servers.value())) {
115         non_empty_name_servers_ = true;
116       }
117       if (NameServersAreWellFormed(ip_config->name_servers.value())) {
118         well_formed_name_servers_ = true;
119         break;
120       }
121     }
122   }
123   AnalyzeResultsAndExecuteCallback();
124 }
125 
126 // Process the network interface information.
OnNetworkStateListReceived(std::vector<network_config::mojom::NetworkStatePropertiesPtr> networks)127 void DnsResolverPresentRoutine::OnNetworkStateListReceived(
128     std::vector<network_config::mojom::NetworkStatePropertiesPtr> networks) {
129   std::string default_guid;
130   for (const auto& network : networks) {
131     if (network_config::StateIsConnected(network->connection_state)) {
132       default_guid = network->guid;
133       break;
134     }
135   }
136   // Since we are not connected, proceed to analyzing the results and executing
137   // the completion callback.
138   if (default_guid.empty()) {
139     AnalyzeResultsAndExecuteCallback();
140   } else {
141     FetchManagedProperties(default_guid);
142   }
143 }
144 
145 }  // namespace network_diagnostics
146 }  // namespace chromeos
147