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