blob: 004eba09778d687f15f7e1cab882a620d2a1b8b7 [file] [log] [blame]
Jay Srinivasan43488792012-06-19 00:25:31 -07001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Jay Srinivasan43488792012-06-19 00:25:31 -07005#include "update_engine/connection_manager.h"
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07006
Alex Vakulenkod2779df2014-06-16 13:19:00 -07007#include <set>
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07008#include <string>
9
Jay Srinivasan43488792012-06-19 00:25:31 -070010#include <base/stl_util.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070011#include <base/strings/string_util.h>
Jay Srinivasan43488792012-06-19 00:25:31 -070012#include <chromeos/dbus/service_constants.h>
Gilad Arnold1f847232014-04-07 12:07:49 -070013#include <policy/device_policy.h>
Andrew de los Reyesd57d1472010-10-21 13:34:08 -070014
Alex Deymof4867c42013-06-28 14:41:39 -070015#include "update_engine/prefs.h"
Jay Srinivasan43488792012-06-19 00:25:31 -070016#include "update_engine/system_state.h"
Andrew de los Reyesd57d1472010-10-21 13:34:08 -070017#include "update_engine/utils.h"
18
Alex Deymo30534502015-07-20 15:06:33 -070019using org::chromium::flimflam::ManagerProxyInterface;
20using org::chromium::flimflam::ServiceProxyInterface;
Jay Srinivasan43488792012-06-19 00:25:31 -070021using std::set;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -070022using std::string;
23
24namespace chromeos_update_engine {
25
26namespace {
27
Alex Deymo30534502015-07-20 15:06:33 -070028NetworkConnectionType ParseConnectionType(const string& type_str) {
29 if (type_str == shill::kTypeEthernet) {
Alex Deymo75eac7e2015-07-29 13:39:14 -070030 return NetworkConnectionType::kEthernet;
Alex Deymo30534502015-07-20 15:06:33 -070031 } else if (type_str == shill::kTypeWifi) {
Alex Deymo75eac7e2015-07-29 13:39:14 -070032 return NetworkConnectionType::kWifi;
Alex Deymo30534502015-07-20 15:06:33 -070033 } else if (type_str == shill::kTypeWimax) {
Alex Deymo75eac7e2015-07-29 13:39:14 -070034 return NetworkConnectionType::kWimax;
Alex Deymo30534502015-07-20 15:06:33 -070035 } else if (type_str == shill::kTypeBluetooth) {
Alex Deymo75eac7e2015-07-29 13:39:14 -070036 return NetworkConnectionType::kBluetooth;
Alex Deymo30534502015-07-20 15:06:33 -070037 } else if (type_str == shill::kTypeCellular) {
Alex Deymo75eac7e2015-07-29 13:39:14 -070038 return NetworkConnectionType::kCellular;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -070039 }
Alex Deymo75eac7e2015-07-29 13:39:14 -070040 return NetworkConnectionType::kUnknown;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -070041}
42
Alex Deymo30534502015-07-20 15:06:33 -070043NetworkTethering ParseTethering(const string& tethering_str) {
44 if (tethering_str == shill::kTetheringNotDetectedState) {
Alex Deymo6ae91202014-03-10 19:21:25 -070045 return NetworkTethering::kNotDetected;
Alex Deymo30534502015-07-20 15:06:33 -070046 } else if (tethering_str == shill::kTetheringSuspectedState) {
Alex Deymo6ae91202014-03-10 19:21:25 -070047 return NetworkTethering::kSuspected;
Alex Deymo30534502015-07-20 15:06:33 -070048 } else if (tethering_str == shill::kTetheringConfirmedState) {
Alex Deymo6ae91202014-03-10 19:21:25 -070049 return NetworkTethering::kConfirmed;
50 }
51 LOG(WARNING) << "Unknown Tethering value: " << tethering_str;
52 return NetworkTethering::kUnknown;
53}
54
Alex Vakulenkod2779df2014-06-16 13:19:00 -070055} // namespace
Andrew de los Reyesd57d1472010-10-21 13:34:08 -070056
Alex Deymo30534502015-07-20 15:06:33 -070057ConnectionManager::ConnectionManager(ShillProxyInterface* shill_proxy,
58 SystemState* system_state)
59 : shill_proxy_(shill_proxy), system_state_(system_state) {}
Jay Srinivasan43488792012-06-19 00:25:31 -070060
Alex Deymo6ae91202014-03-10 19:21:25 -070061bool ConnectionManager::IsUpdateAllowedOver(NetworkConnectionType type,
62 NetworkTethering tethering) const {
Jay Srinivasan43488792012-06-19 00:25:31 -070063 switch (type) {
Alex Deymo75eac7e2015-07-29 13:39:14 -070064 case NetworkConnectionType::kBluetooth:
Jay Srinivasan43488792012-06-19 00:25:31 -070065 return false;
66
Alex Deymo75eac7e2015-07-29 13:39:14 -070067 case NetworkConnectionType::kCellular: {
Jay Srinivasan43488792012-06-19 00:25:31 -070068 set<string> allowed_types;
69 const policy::DevicePolicy* device_policy =
Jay Srinivasan6f6ea002012-12-14 11:26:28 -080070 system_state_->device_policy();
Alex Deymof4867c42013-06-28 14:41:39 -070071
72 // A device_policy is loaded in a lazy way right before an update check,
73 // so the device_policy should be already loaded at this point. If it's
74 // not, return a safe value for this setting.
Jay Srinivasan43488792012-06-19 00:25:31 -070075 if (!device_policy) {
Alex Deymof4867c42013-06-28 14:41:39 -070076 LOG(INFO) << "Disabling updates over cellular networks as there's no "
77 "device policy loaded yet.";
Jay Srinivasan43488792012-06-19 00:25:31 -070078 return false;
79 }
80
Alex Deymof4867c42013-06-28 14:41:39 -070081 if (device_policy->GetAllowedConnectionTypesForUpdate(&allowed_types)) {
82 // The update setting is enforced by the device policy.
Jay Srinivasan43488792012-06-19 00:25:31 -070083
Gilad Arnold9a423ff2014-03-27 15:27:35 -070084 if (!ContainsKey(allowed_types, shill::kTypeCellular)) {
Alex Deymof4867c42013-06-28 14:41:39 -070085 LOG(INFO) << "Disabling updates over cellular connection as it's not "
86 "allowed in the device policy.";
87 return false;
88 }
Jay Srinivasan43488792012-06-19 00:25:31 -070089
Alex Deymof4867c42013-06-28 14:41:39 -070090 LOG(INFO) << "Allowing updates over cellular per device policy.";
91 return true;
92 } else {
93 // There's no update setting in the device policy, using the local user
94 // setting.
95 PrefsInterface* prefs = system_state_->prefs();
96
97 if (!prefs || !prefs->Exists(kPrefsUpdateOverCellularPermission)) {
98 LOG(INFO) << "Disabling updates over cellular connection as there's "
99 "no device policy setting nor user preference present.";
100 return false;
101 }
102
Alex Deymoefb7c4c2013-07-09 14:34:00 -0700103 bool stored_value;
104 if (!prefs->GetBoolean(kPrefsUpdateOverCellularPermission,
105 &stored_value)) {
Alex Deymof4867c42013-06-28 14:41:39 -0700106 return false;
Alex Deymoefb7c4c2013-07-09 14:34:00 -0700107 }
Alex Deymof4867c42013-06-28 14:41:39 -0700108
109 if (!stored_value) {
110 LOG(INFO) << "Disabling updates over cellular connection per user "
111 "setting.";
112 return false;
113 }
114 LOG(INFO) << "Allowing updates over cellular per user setting.";
115 return true;
116 }
Jay Srinivasan43488792012-06-19 00:25:31 -0700117 }
118
119 default:
Alex Deymo6ae91202014-03-10 19:21:25 -0700120 if (tethering == NetworkTethering::kConfirmed) {
121 // Treat this connection as if it is a cellular connection.
122 LOG(INFO) << "Current connection is confirmed tethered, using Cellular "
123 "setting.";
Alex Deymo75eac7e2015-07-29 13:39:14 -0700124 return IsUpdateAllowedOver(NetworkConnectionType::kCellular,
125 NetworkTethering::kUnknown);
Alex Deymo6ae91202014-03-10 19:21:25 -0700126 }
Jay Srinivasan43488792012-06-19 00:25:31 -0700127 return true;
128 }
129}
130
Alex Deymof6ee0162015-07-31 12:35:22 -0700131// static
Jay Srinivasan43488792012-06-19 00:25:31 -0700132const char* ConnectionManager::StringForConnectionType(
Alex Deymof6ee0162015-07-31 12:35:22 -0700133 NetworkConnectionType type) {
Alex Deymo75eac7e2015-07-29 13:39:14 -0700134 switch (type) {
135 case NetworkConnectionType::kEthernet:
136 return shill::kTypeEthernet;
137 case NetworkConnectionType::kWifi:
138 return shill::kTypeWifi;
139 case NetworkConnectionType::kWimax:
140 return shill::kTypeWimax;
141 case NetworkConnectionType::kBluetooth:
142 return shill::kTypeBluetooth;
143 case NetworkConnectionType::kCellular:
144 return shill::kTypeCellular;
145 case NetworkConnectionType::kUnknown:
146 return "Unknown";
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700147 }
Alex Deymo75eac7e2015-07-29 13:39:14 -0700148 return "Unknown";
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700149}
150
Alex Deymo30534502015-07-20 15:06:33 -0700151bool ConnectionManager::GetConnectionProperties(
152 NetworkConnectionType* out_type,
153 NetworkTethering* out_tethering) {
154 string default_service_path;
155 TEST_AND_RETURN_FALSE(GetDefaultServicePath(&default_service_path));
156 if (default_service_path.empty())
157 return false;
158 TEST_AND_RETURN_FALSE(
159 GetServicePathProperties(default_service_path, out_type, out_tethering));
160 return true;
Alex Deymo6ae91202014-03-10 19:21:25 -0700161}
162
Alex Deymo30534502015-07-20 15:06:33 -0700163bool ConnectionManager::GetDefaultServicePath(string* out_path) {
164 chromeos::VariantDictionary properties;
165 chromeos::ErrorPtr error;
166 ManagerProxyInterface* manager_proxy = shill_proxy_->GetManagerProxy();
167 if (!manager_proxy)
168 return false;
169 TEST_AND_RETURN_FALSE(manager_proxy->GetProperties(&properties, &error));
170
171 const auto& prop_default_service =
172 properties.find(shill::kDefaultServiceProperty);
173 if (prop_default_service == properties.end())
174 return false;
175
176 *out_path = prop_default_service->second.TryGet<dbus::ObjectPath>().value();
177 return !out_path->empty();
178}
179
180bool ConnectionManager::GetServicePathProperties(
181 const string& path,
Alex Deymo6ae91202014-03-10 19:21:25 -0700182 NetworkConnectionType* out_type,
Alex Deymo30534502015-07-20 15:06:33 -0700183 NetworkTethering* out_tethering) {
184 // We create and dispose the ServiceProxyInterface on every request.
185 std::unique_ptr<ServiceProxyInterface> service =
186 shill_proxy_->GetServiceForPath(path);
187
188 chromeos::VariantDictionary properties;
189 chromeos::ErrorPtr error;
190 TEST_AND_RETURN_FALSE(service->GetProperties(&properties, &error));
191
192 // Populate the out_tethering.
193 const auto& prop_tethering = properties.find(shill::kTetheringProperty);
194 if (prop_tethering == properties.end()) {
195 // Set to Unknown if not present.
196 *out_tethering = NetworkTethering::kUnknown;
197 } else {
198 // If the property doesn't contain a string value, the empty string will
199 // become kUnknown.
200 *out_tethering = ParseTethering(prop_tethering->second.TryGet<string>());
201 }
202
203 // Populate the out_type property.
204 const auto& prop_type = properties.find(shill::kTypeProperty);
205 if (prop_type == properties.end()) {
206 // Set to Unknown if not present.
207 *out_type = NetworkConnectionType::kUnknown;
208 return false;
209 }
210
211 string type_str = prop_type->second.TryGet<string>();
212 if (type_str == shill::kTypeVPN) {
213 const auto& prop_physical =
214 properties.find(shill::kPhysicalTechnologyProperty);
215 if (prop_physical == properties.end()) {
216 LOG(ERROR) << "No PhysicalTechnology property found for a VPN"
217 << " connection (service: " << path << "). Returning default"
218 << " kUnknown value.";
219 *out_type = NetworkConnectionType::kUnknown;
220 } else {
221 *out_type = ParseConnectionType(prop_physical->second.TryGet<string>());
222 }
223 } else {
224 *out_type = ParseConnectionType(type_str);
225 }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700226 return true;
227}
228
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700229} // namespace chromeos_update_engine