blob: f72d9e84d33a03d12c9f7d65c915efaacdb07d85 [file] [log] [blame]
Alex Deymoaea4c1c2015-08-19 20:24:43 -07001//
2// Copyright (C) 2012 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
Andrew de los Reyesd57d1472010-10-21 13:34:08 -070016
Jay Srinivasan43488792012-06-19 00:25:31 -070017#include "update_engine/connection_manager.h"
Andrew de los Reyesd57d1472010-10-21 13:34:08 -070018
Alex Vakulenkod2779df2014-06-16 13:19:00 -070019#include <set>
Andrew de los Reyesd57d1472010-10-21 13:34:08 -070020#include <string>
21
Jay Srinivasan43488792012-06-19 00:25:31 -070022#include <base/stl_util.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070023#include <base/strings/string_util.h>
Gilad Arnold1f847232014-04-07 12:07:49 -070024#include <policy/device_policy.h>
Alex Deymod6deb1d2015-08-28 15:54:37 -070025#include <shill/dbus-constants.h>
26#include <shill/dbus-proxies.h>
Andrew de los Reyesd57d1472010-10-21 13:34:08 -070027
Alex Deymo39910dc2015-11-09 17:04:30 -080028#include "update_engine/common/prefs.h"
29#include "update_engine/common/utils.h"
Sen Jiang255e22b2016-05-20 16:15:29 -070030#include "update_engine/connection_utils.h"
Sen Jiangf5bebae2016-06-03 15:36:54 -070031#include "update_engine/shill_proxy.h"
Jay Srinivasan43488792012-06-19 00:25:31 -070032#include "update_engine/system_state.h"
Andrew de los Reyesd57d1472010-10-21 13:34:08 -070033
Alex Deymo30534502015-07-20 15:06:33 -070034using org::chromium::flimflam::ManagerProxyInterface;
35using org::chromium::flimflam::ServiceProxyInterface;
Jay Srinivasan43488792012-06-19 00:25:31 -070036using std::set;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -070037using std::string;
38
39namespace chromeos_update_engine {
40
Sen Jiangf5bebae2016-06-03 15:36:54 -070041namespace connection_manager {
42std::unique_ptr<ConnectionManagerInterface> CreateConnectionManager(
43 SystemState* system_state) {
44 return std::unique_ptr<ConnectionManagerInterface>(
45 new ConnectionManager(new ShillProxy(), system_state));
46}
47}
48
Alex Deymo30534502015-07-20 15:06:33 -070049ConnectionManager::ConnectionManager(ShillProxyInterface* shill_proxy,
50 SystemState* system_state)
51 : shill_proxy_(shill_proxy), system_state_(system_state) {}
Jay Srinivasan43488792012-06-19 00:25:31 -070052
Sen Jiang255e22b2016-05-20 16:15:29 -070053bool ConnectionManager::IsUpdateAllowedOver(
54 ConnectionType type, ConnectionTethering tethering) const {
Jay Srinivasan43488792012-06-19 00:25:31 -070055 switch (type) {
Sen Jiang255e22b2016-05-20 16:15:29 -070056 case ConnectionType::kBluetooth:
Jay Srinivasan43488792012-06-19 00:25:31 -070057 return false;
58
Sen Jiang255e22b2016-05-20 16:15:29 -070059 case ConnectionType::kCellular: {
Jay Srinivasan43488792012-06-19 00:25:31 -070060 set<string> allowed_types;
61 const policy::DevicePolicy* device_policy =
Jay Srinivasan6f6ea002012-12-14 11:26:28 -080062 system_state_->device_policy();
Alex Deymof4867c42013-06-28 14:41:39 -070063
64 // A device_policy is loaded in a lazy way right before an update check,
65 // so the device_policy should be already loaded at this point. If it's
66 // not, return a safe value for this setting.
Jay Srinivasan43488792012-06-19 00:25:31 -070067 if (!device_policy) {
Alex Deymof4867c42013-06-28 14:41:39 -070068 LOG(INFO) << "Disabling updates over cellular networks as there's no "
69 "device policy loaded yet.";
Jay Srinivasan43488792012-06-19 00:25:31 -070070 return false;
71 }
72
Alex Deymof4867c42013-06-28 14:41:39 -070073 if (device_policy->GetAllowedConnectionTypesForUpdate(&allowed_types)) {
74 // The update setting is enforced by the device policy.
Jay Srinivasan43488792012-06-19 00:25:31 -070075
Gilad Arnold9a423ff2014-03-27 15:27:35 -070076 if (!ContainsKey(allowed_types, shill::kTypeCellular)) {
Alex Deymof4867c42013-06-28 14:41:39 -070077 LOG(INFO) << "Disabling updates over cellular connection as it's not "
78 "allowed in the device policy.";
79 return false;
80 }
Jay Srinivasan43488792012-06-19 00:25:31 -070081
Alex Deymof4867c42013-06-28 14:41:39 -070082 LOG(INFO) << "Allowing updates over cellular per device policy.";
83 return true;
84 } else {
85 // There's no update setting in the device policy, using the local user
86 // setting.
87 PrefsInterface* prefs = system_state_->prefs();
88
89 if (!prefs || !prefs->Exists(kPrefsUpdateOverCellularPermission)) {
90 LOG(INFO) << "Disabling updates over cellular connection as there's "
91 "no device policy setting nor user preference present.";
92 return false;
93 }
94
Alex Deymoefb7c4c2013-07-09 14:34:00 -070095 bool stored_value;
96 if (!prefs->GetBoolean(kPrefsUpdateOverCellularPermission,
97 &stored_value)) {
Alex Deymof4867c42013-06-28 14:41:39 -070098 return false;
Alex Deymoefb7c4c2013-07-09 14:34:00 -070099 }
Alex Deymof4867c42013-06-28 14:41:39 -0700100
101 if (!stored_value) {
102 LOG(INFO) << "Disabling updates over cellular connection per user "
103 "setting.";
104 return false;
105 }
106 LOG(INFO) << "Allowing updates over cellular per user setting.";
107 return true;
108 }
Jay Srinivasan43488792012-06-19 00:25:31 -0700109 }
110
111 default:
Sen Jiang255e22b2016-05-20 16:15:29 -0700112 if (tethering == ConnectionTethering::kConfirmed) {
Alex Deymo6ae91202014-03-10 19:21:25 -0700113 // Treat this connection as if it is a cellular connection.
114 LOG(INFO) << "Current connection is confirmed tethered, using Cellular "
115 "setting.";
Sen Jiang255e22b2016-05-20 16:15:29 -0700116 return IsUpdateAllowedOver(ConnectionType::kCellular,
117 ConnectionTethering::kUnknown);
Alex Deymo6ae91202014-03-10 19:21:25 -0700118 }
Jay Srinivasan43488792012-06-19 00:25:31 -0700119 return true;
120 }
121}
122
Alex Deymo30534502015-07-20 15:06:33 -0700123bool ConnectionManager::GetConnectionProperties(
Sen Jiang255e22b2016-05-20 16:15:29 -0700124 ConnectionType* out_type, ConnectionTethering* out_tethering) {
Alex Deymo758dd532015-09-09 15:21:22 -0700125 dbus::ObjectPath default_service_path;
Alex Deymo30534502015-07-20 15:06:33 -0700126 TEST_AND_RETURN_FALSE(GetDefaultServicePath(&default_service_path));
Alex Deymo758dd532015-09-09 15:21:22 -0700127 if (!default_service_path.IsValid())
Alex Deymo30534502015-07-20 15:06:33 -0700128 return false;
Alex Deymo1fbaac82015-11-04 04:41:40 -0800129 // Shill uses the "/" service path to indicate that it is not connected.
130 if (default_service_path.value() == "/")
131 return false;
Alex Deymo30534502015-07-20 15:06:33 -0700132 TEST_AND_RETURN_FALSE(
133 GetServicePathProperties(default_service_path, out_type, out_tethering));
134 return true;
Alex Deymo6ae91202014-03-10 19:21:25 -0700135}
136
Alex Deymo758dd532015-09-09 15:21:22 -0700137bool ConnectionManager::GetDefaultServicePath(dbus::ObjectPath* out_path) {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700138 brillo::VariantDictionary properties;
139 brillo::ErrorPtr error;
Alex Deymo30534502015-07-20 15:06:33 -0700140 ManagerProxyInterface* manager_proxy = shill_proxy_->GetManagerProxy();
141 if (!manager_proxy)
142 return false;
143 TEST_AND_RETURN_FALSE(manager_proxy->GetProperties(&properties, &error));
144
145 const auto& prop_default_service =
146 properties.find(shill::kDefaultServiceProperty);
147 if (prop_default_service == properties.end())
148 return false;
149
Alex Deymo758dd532015-09-09 15:21:22 -0700150 *out_path = prop_default_service->second.TryGet<dbus::ObjectPath>();
151 return out_path->IsValid();
Alex Deymo30534502015-07-20 15:06:33 -0700152}
153
154bool ConnectionManager::GetServicePathProperties(
Alex Deymo758dd532015-09-09 15:21:22 -0700155 const dbus::ObjectPath& path,
Sen Jiang255e22b2016-05-20 16:15:29 -0700156 ConnectionType* out_type,
157 ConnectionTethering* out_tethering) {
Alex Deymo30534502015-07-20 15:06:33 -0700158 // We create and dispose the ServiceProxyInterface on every request.
159 std::unique_ptr<ServiceProxyInterface> service =
160 shill_proxy_->GetServiceForPath(path);
161
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700162 brillo::VariantDictionary properties;
163 brillo::ErrorPtr error;
Alex Deymo30534502015-07-20 15:06:33 -0700164 TEST_AND_RETURN_FALSE(service->GetProperties(&properties, &error));
165
166 // Populate the out_tethering.
167 const auto& prop_tethering = properties.find(shill::kTetheringProperty);
168 if (prop_tethering == properties.end()) {
169 // Set to Unknown if not present.
Sen Jiang255e22b2016-05-20 16:15:29 -0700170 *out_tethering = ConnectionTethering::kUnknown;
Alex Deymo30534502015-07-20 15:06:33 -0700171 } else {
172 // If the property doesn't contain a string value, the empty string will
173 // become kUnknown.
Sen Jiang255e22b2016-05-20 16:15:29 -0700174 *out_tethering = connection_utils::ParseConnectionTethering(
175 prop_tethering->second.TryGet<string>());
Alex Deymo30534502015-07-20 15:06:33 -0700176 }
177
178 // Populate the out_type property.
179 const auto& prop_type = properties.find(shill::kTypeProperty);
180 if (prop_type == properties.end()) {
181 // Set to Unknown if not present.
Sen Jiang255e22b2016-05-20 16:15:29 -0700182 *out_type = ConnectionType::kUnknown;
Alex Deymo30534502015-07-20 15:06:33 -0700183 return false;
184 }
185
186 string type_str = prop_type->second.TryGet<string>();
187 if (type_str == shill::kTypeVPN) {
188 const auto& prop_physical =
189 properties.find(shill::kPhysicalTechnologyProperty);
190 if (prop_physical == properties.end()) {
191 LOG(ERROR) << "No PhysicalTechnology property found for a VPN"
Alex Deymo758dd532015-09-09 15:21:22 -0700192 " connection (service: "
193 << path.value() << "). Returning default kUnknown value.";
Sen Jiang255e22b2016-05-20 16:15:29 -0700194 *out_type = ConnectionType::kUnknown;
Alex Deymo30534502015-07-20 15:06:33 -0700195 } else {
Sen Jiang255e22b2016-05-20 16:15:29 -0700196 *out_type = connection_utils::ParseConnectionType(
197 prop_physical->second.TryGet<string>());
Alex Deymo30534502015-07-20 15:06:33 -0700198 }
199 } else {
Sen Jiang255e22b2016-05-20 16:15:29 -0700200 *out_type = connection_utils::ParseConnectionType(type_str);
Alex Deymo30534502015-07-20 15:06:33 -0700201 }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700202 return true;
203}
204
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700205} // namespace chromeos_update_engine