blob: bbba9f7ef39ddcc04749a1db1f6738d4c6572972 [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
7#include <string>
8
Jay Srinivasan43488792012-06-19 00:25:31 -07009#include <base/stl_util.h>
Andrew de los Reyesd57d1472010-10-21 13:34:08 -070010#include <base/string_util.h>
Jay Srinivasan43488792012-06-19 00:25:31 -070011#include <chromeos/dbus/service_constants.h>
Andrew de los Reyesd57d1472010-10-21 13:34:08 -070012#include <dbus/dbus-glib.h>
13#include <glib.h>
14
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
Jay Srinivasan43488792012-06-19 00:25:31 -070019using std::set;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -070020using std::string;
21
22namespace chromeos_update_engine {
23
24namespace {
25
26// Gets the DbusGProxy for FlimFlam. Must be free'd with ProxyUnref()
27bool GetFlimFlamProxy(DbusGlibInterface* dbus_iface,
28 const char* path,
29 const char* interface,
30 DBusGProxy** out_proxy) {
31 DBusGConnection* bus;
32 DBusGProxy* proxy;
33 GError* error = NULL;
34
35 bus = dbus_iface->BusGet(DBUS_BUS_SYSTEM, &error);
36 if (!bus) {
37 LOG(ERROR) << "Failed to get system bus";
38 return false;
39 }
40 proxy = dbus_iface->ProxyNewForNameOwner(bus,
Jay Srinivasan43488792012-06-19 00:25:31 -070041 flimflam::kFlimflamServiceName,
Andrew de los Reyesd57d1472010-10-21 13:34:08 -070042 path,
43 interface,
44 &error);
45 if (!proxy) {
46 LOG(ERROR) << "Error getting FlimFlam proxy: "
Darin Petkova0b9e772011-10-06 05:05:56 -070047 << utils::GetAndFreeGError(&error);
Andrew de los Reyesd57d1472010-10-21 13:34:08 -070048 return false;
49 }
50 *out_proxy = proxy;
51 return true;
52}
53
54// On success, caller owns the GHashTable at out_hash_table.
55// Returns true on success.
56bool GetProperties(DbusGlibInterface* dbus_iface,
57 const char* path,
58 const char* interface,
59 GHashTable** out_hash_table) {
60 DBusGProxy* proxy;
61 GError* error = NULL;
62
63 TEST_AND_RETURN_FALSE(GetFlimFlamProxy(dbus_iface,
64 path,
65 interface,
66 &proxy));
67
68 gboolean rc = dbus_iface->ProxyCall(proxy,
69 "GetProperties",
70 &error,
71 G_TYPE_INVALID,
72 dbus_g_type_get_map("GHashTable",
73 G_TYPE_STRING,
74 G_TYPE_VALUE),
75 out_hash_table,
76 G_TYPE_INVALID);
77 dbus_iface->ProxyUnref(proxy);
78 if (rc == FALSE) {
79 LOG(ERROR) << "dbus_g_proxy_call failed";
80 return false;
81 }
82
83 return true;
84}
85
86// Returns (via out_path) the default network path, or empty string if
87// there's no network up.
88// Returns true on success.
89bool GetDefaultServicePath(DbusGlibInterface* dbus_iface, string* out_path) {
90 GHashTable* hash_table = NULL;
91
92 TEST_AND_RETURN_FALSE(GetProperties(dbus_iface,
Jay Srinivasan43488792012-06-19 00:25:31 -070093 flimflam::kFlimflamServicePath,
94 flimflam::kFlimflamManagerInterface,
Andrew de los Reyesd57d1472010-10-21 13:34:08 -070095 &hash_table));
96
97 GValue* value = reinterpret_cast<GValue*>(g_hash_table_lookup(hash_table,
98 "Services"));
99 GArray* array = NULL;
100 bool success = false;
mukesh agrawal88226ff2012-03-19 17:50:06 -0700101 if (G_VALUE_HOLDS(value, DBUS_TYPE_G_OBJECT_PATH_ARRAY) &&
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700102 (array = reinterpret_cast<GArray*>(g_value_get_boxed(value))) &&
103 (array->len > 0)) {
104 *out_path = g_array_index(array, const char*, 0);
105 success = true;
106 }
mukesh agrawal88226ff2012-03-19 17:50:06 -0700107
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700108 g_hash_table_unref(hash_table);
109 return success;
110}
111
112NetworkConnectionType ParseConnectionType(const char* type_str) {
Jay Srinivasan43488792012-06-19 00:25:31 -0700113 if (!strcmp(type_str, flimflam::kTypeEthernet)) {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700114 return kNetEthernet;
Jay Srinivasan43488792012-06-19 00:25:31 -0700115 } else if (!strcmp(type_str, flimflam::kTypeWifi)) {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700116 return kNetWifi;
Jay Srinivasan43488792012-06-19 00:25:31 -0700117 } else if (!strcmp(type_str, flimflam::kTypeWimax)) {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700118 return kNetWimax;
Jay Srinivasan43488792012-06-19 00:25:31 -0700119 } else if (!strcmp(type_str, flimflam::kTypeBluetooth)) {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700120 return kNetBluetooth;
Jay Srinivasan43488792012-06-19 00:25:31 -0700121 } else if (!strcmp(type_str, flimflam::kTypeCellular)) {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700122 return kNetCellular;
123 }
124 return kNetUnknown;
125}
126
127bool GetServicePathType(DbusGlibInterface* dbus_iface,
128 const string& path,
129 NetworkConnectionType* out_type) {
130 GHashTable* hash_table = NULL;
131
132 TEST_AND_RETURN_FALSE(GetProperties(dbus_iface,
133 path.c_str(),
Jay Srinivasan43488792012-06-19 00:25:31 -0700134 flimflam::kFlimflamServiceInterface,
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700135 &hash_table));
136
Alex Deymo1c4e6382013-07-15 12:09:51 -0700137 GValue* value = (GValue*)g_hash_table_lookup(hash_table,
138 flimflam::kTypeProperty);
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700139 const char* type_str = NULL;
140 bool success = false;
141 if (value != NULL && (type_str = g_value_get_string(value)) != NULL) {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700142 success = true;
Alex Deymo1c4e6382013-07-15 12:09:51 -0700143 if (!strcmp(type_str, flimflam::kTypeVPN)) {
144 value = (GValue*)g_hash_table_lookup(hash_table,
145 shill::kPhysicalTechnologyProperty);
146 if (value != NULL && (type_str = g_value_get_string(value)) != NULL) {
147 *out_type = ParseConnectionType(type_str);
148 } else {
149 LOG(ERROR) << "No PhysicalTechnology property found for a VPN"
150 << " connection (service: " << path << "). Returning default"
151 << " kNetUnknown value.";
152 *out_type = kNetUnknown;
153 }
154 } else {
155 *out_type = ParseConnectionType(type_str);
156 }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700157 }
158 g_hash_table_unref(hash_table);
159 return success;
160}
161
162} // namespace {}
163
Jay Srinivasan43488792012-06-19 00:25:31 -0700164ConnectionManager::ConnectionManager(SystemState *system_state)
165 : system_state_(system_state) {}
166
167bool ConnectionManager::IsUpdateAllowedOver(NetworkConnectionType type) const {
168 switch (type) {
169 case kNetBluetooth:
170 return false;
171
172 case kNetCellular: {
173 set<string> allowed_types;
174 const policy::DevicePolicy* device_policy =
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800175 system_state_->device_policy();
Alex Deymof4867c42013-06-28 14:41:39 -0700176
177 // A device_policy is loaded in a lazy way right before an update check,
178 // so the device_policy should be already loaded at this point. If it's
179 // not, return a safe value for this setting.
Jay Srinivasan43488792012-06-19 00:25:31 -0700180 if (!device_policy) {
Alex Deymof4867c42013-06-28 14:41:39 -0700181 LOG(INFO) << "Disabling updates over cellular networks as there's no "
182 "device policy loaded yet.";
Jay Srinivasan43488792012-06-19 00:25:31 -0700183 return false;
184 }
185
Alex Deymof4867c42013-06-28 14:41:39 -0700186 if (device_policy->GetAllowedConnectionTypesForUpdate(&allowed_types)) {
187 // The update setting is enforced by the device policy.
Jay Srinivasan43488792012-06-19 00:25:31 -0700188
Alex Deymof4867c42013-06-28 14:41:39 -0700189 if ((type == kNetCellular &&
190 !ContainsKey(allowed_types, flimflam::kTypeCellular))) {
191 LOG(INFO) << "Disabling updates over cellular connection as it's not "
192 "allowed in the device policy.";
193 return false;
194 }
Jay Srinivasan43488792012-06-19 00:25:31 -0700195
Alex Deymof4867c42013-06-28 14:41:39 -0700196 LOG(INFO) << "Allowing updates over cellular per device policy.";
197 return true;
198 } else {
199 // There's no update setting in the device policy, using the local user
200 // setting.
201 PrefsInterface* prefs = system_state_->prefs();
202
203 if (!prefs || !prefs->Exists(kPrefsUpdateOverCellularPermission)) {
204 LOG(INFO) << "Disabling updates over cellular connection as there's "
205 "no device policy setting nor user preference present.";
206 return false;
207 }
208
Alex Deymoefb7c4c2013-07-09 14:34:00 -0700209 bool stored_value;
210 if (!prefs->GetBoolean(kPrefsUpdateOverCellularPermission,
211 &stored_value)) {
Alex Deymof4867c42013-06-28 14:41:39 -0700212 return false;
Alex Deymoefb7c4c2013-07-09 14:34:00 -0700213 }
Alex Deymof4867c42013-06-28 14:41:39 -0700214
215 if (!stored_value) {
216 LOG(INFO) << "Disabling updates over cellular connection per user "
217 "setting.";
218 return false;
219 }
220 LOG(INFO) << "Allowing updates over cellular per user setting.";
221 return true;
222 }
Jay Srinivasan43488792012-06-19 00:25:31 -0700223 }
224
225 default:
226 return true;
227 }
228}
229
230const char* ConnectionManager::StringForConnectionType(
231 NetworkConnectionType type) const {
232 static const char* const kValues[] = {flimflam::kTypeEthernet,
233 flimflam::kTypeWifi,
234 flimflam::kTypeWimax,
235 flimflam::kTypeBluetooth,
236 flimflam::kTypeCellular};
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700237 if (type < 0 || type >= static_cast<int>(arraysize(kValues))) {
238 return "Unknown";
239 }
240 return kValues[type];
241}
242
Jay Srinivasan43488792012-06-19 00:25:31 -0700243bool ConnectionManager::GetConnectionType(
244 DbusGlibInterface* dbus_iface,
245 NetworkConnectionType* out_type) const {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700246 string default_service_path;
247 TEST_AND_RETURN_FALSE(GetDefaultServicePath(dbus_iface,
248 &default_service_path));
249 TEST_AND_RETURN_FALSE(GetServicePathType(dbus_iface,
250 default_service_path,
251 out_type));
252 return true;
253}
254
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700255} // namespace chromeos_update_engine