blob: 304413007d5802d74e2754869aecf077136095f1 [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
Jay Srinivasan43488792012-06-19 00:25:31 -070015#include "update_engine/system_state.h"
Andrew de los Reyesd57d1472010-10-21 13:34:08 -070016#include "update_engine/utils.h"
17
Jay Srinivasan43488792012-06-19 00:25:31 -070018using std::set;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -070019using std::string;
20
21namespace chromeos_update_engine {
22
23namespace {
24
25// Gets the DbusGProxy for FlimFlam. Must be free'd with ProxyUnref()
26bool GetFlimFlamProxy(DbusGlibInterface* dbus_iface,
27 const char* path,
28 const char* interface,
29 DBusGProxy** out_proxy) {
30 DBusGConnection* bus;
31 DBusGProxy* proxy;
32 GError* error = NULL;
33
34 bus = dbus_iface->BusGet(DBUS_BUS_SYSTEM, &error);
35 if (!bus) {
36 LOG(ERROR) << "Failed to get system bus";
37 return false;
38 }
39 proxy = dbus_iface->ProxyNewForNameOwner(bus,
Jay Srinivasan43488792012-06-19 00:25:31 -070040 flimflam::kFlimflamServiceName,
Andrew de los Reyesd57d1472010-10-21 13:34:08 -070041 path,
42 interface,
43 &error);
44 if (!proxy) {
45 LOG(ERROR) << "Error getting FlimFlam proxy: "
Darin Petkova0b9e772011-10-06 05:05:56 -070046 << utils::GetAndFreeGError(&error);
Andrew de los Reyesd57d1472010-10-21 13:34:08 -070047 return false;
48 }
49 *out_proxy = proxy;
50 return true;
51}
52
53// On success, caller owns the GHashTable at out_hash_table.
54// Returns true on success.
55bool GetProperties(DbusGlibInterface* dbus_iface,
56 const char* path,
57 const char* interface,
58 GHashTable** out_hash_table) {
59 DBusGProxy* proxy;
60 GError* error = NULL;
61
62 TEST_AND_RETURN_FALSE(GetFlimFlamProxy(dbus_iface,
63 path,
64 interface,
65 &proxy));
66
67 gboolean rc = dbus_iface->ProxyCall(proxy,
68 "GetProperties",
69 &error,
70 G_TYPE_INVALID,
71 dbus_g_type_get_map("GHashTable",
72 G_TYPE_STRING,
73 G_TYPE_VALUE),
74 out_hash_table,
75 G_TYPE_INVALID);
76 dbus_iface->ProxyUnref(proxy);
77 if (rc == FALSE) {
78 LOG(ERROR) << "dbus_g_proxy_call failed";
79 return false;
80 }
81
82 return true;
83}
84
85// Returns (via out_path) the default network path, or empty string if
86// there's no network up.
87// Returns true on success.
88bool GetDefaultServicePath(DbusGlibInterface* dbus_iface, string* out_path) {
89 GHashTable* hash_table = NULL;
90
91 TEST_AND_RETURN_FALSE(GetProperties(dbus_iface,
Jay Srinivasan43488792012-06-19 00:25:31 -070092 flimflam::kFlimflamServicePath,
93 flimflam::kFlimflamManagerInterface,
Andrew de los Reyesd57d1472010-10-21 13:34:08 -070094 &hash_table));
95
96 GValue* value = reinterpret_cast<GValue*>(g_hash_table_lookup(hash_table,
97 "Services"));
98 GArray* array = NULL;
99 bool success = false;
mukesh agrawal88226ff2012-03-19 17:50:06 -0700100 if (G_VALUE_HOLDS(value, DBUS_TYPE_G_OBJECT_PATH_ARRAY) &&
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700101 (array = reinterpret_cast<GArray*>(g_value_get_boxed(value))) &&
102 (array->len > 0)) {
103 *out_path = g_array_index(array, const char*, 0);
104 success = true;
105 }
mukesh agrawal88226ff2012-03-19 17:50:06 -0700106
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700107 g_hash_table_unref(hash_table);
108 return success;
109}
110
111NetworkConnectionType ParseConnectionType(const char* type_str) {
Jay Srinivasan43488792012-06-19 00:25:31 -0700112 if (!strcmp(type_str, flimflam::kTypeEthernet)) {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700113 return kNetEthernet;
Jay Srinivasan43488792012-06-19 00:25:31 -0700114 } else if (!strcmp(type_str, flimflam::kTypeWifi)) {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700115 return kNetWifi;
Jay Srinivasan43488792012-06-19 00:25:31 -0700116 } else if (!strcmp(type_str, flimflam::kTypeWimax)) {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700117 return kNetWimax;
Jay Srinivasan43488792012-06-19 00:25:31 -0700118 } else if (!strcmp(type_str, flimflam::kTypeBluetooth)) {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700119 return kNetBluetooth;
Jay Srinivasan43488792012-06-19 00:25:31 -0700120 } else if (!strcmp(type_str, flimflam::kTypeCellular)) {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700121 return kNetCellular;
122 }
123 return kNetUnknown;
124}
125
126bool GetServicePathType(DbusGlibInterface* dbus_iface,
127 const string& path,
128 NetworkConnectionType* out_type) {
129 GHashTable* hash_table = NULL;
130
131 TEST_AND_RETURN_FALSE(GetProperties(dbus_iface,
132 path.c_str(),
Jay Srinivasan43488792012-06-19 00:25:31 -0700133 flimflam::kFlimflamServiceInterface,
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700134 &hash_table));
135
136 GValue* value = (GValue*)g_hash_table_lookup(hash_table, "Type");
137 const char* type_str = NULL;
138 bool success = false;
139 if (value != NULL && (type_str = g_value_get_string(value)) != NULL) {
140 *out_type = ParseConnectionType(type_str);
141 success = true;
142 }
143 g_hash_table_unref(hash_table);
144 return success;
145}
146
147} // namespace {}
148
Jay Srinivasan43488792012-06-19 00:25:31 -0700149ConnectionManager::ConnectionManager(SystemState *system_state)
150 : system_state_(system_state) {}
151
152bool ConnectionManager::IsUpdateAllowedOver(NetworkConnectionType type) const {
153 switch (type) {
154 case kNetBluetooth:
155 return false;
156
157 case kNetCellular: {
158 set<string> allowed_types;
159 const policy::DevicePolicy* device_policy =
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800160 system_state_->device_policy();
Jay Srinivasan43488792012-06-19 00:25:31 -0700161 if (!device_policy) {
162 LOG(INFO) << "Disabling updates over cellular connection as there's no "
163 "device policy object present";
164 return false;
165 }
166
167 if (!device_policy->GetAllowedConnectionTypesForUpdate(&allowed_types)) {
168 LOG(INFO) << "Disabling updates over cellular connection as there's no "
169 "allowed connection types from policy";
170 return false;
171 }
172
173 if (!ContainsKey(allowed_types, flimflam::kTypeCellular)) {
174 LOG(INFO) << "Disabling updates over cellular connection as it's not "
175 "allowed in the device policy.";
176 return false;
177 }
178
179 LOG(INFO) << "Allowing updates over cellular per device policy";
180 return true;
181 }
182
183 default:
184 return true;
185 }
186}
187
188const char* ConnectionManager::StringForConnectionType(
189 NetworkConnectionType type) const {
190 static const char* const kValues[] = {flimflam::kTypeEthernet,
191 flimflam::kTypeWifi,
192 flimflam::kTypeWimax,
193 flimflam::kTypeBluetooth,
194 flimflam::kTypeCellular};
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700195 if (type < 0 || type >= static_cast<int>(arraysize(kValues))) {
196 return "Unknown";
197 }
198 return kValues[type];
199}
200
Jay Srinivasan43488792012-06-19 00:25:31 -0700201bool ConnectionManager::GetConnectionType(
202 DbusGlibInterface* dbus_iface,
203 NetworkConnectionType* out_type) const {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700204 string default_service_path;
205 TEST_AND_RETURN_FALSE(GetDefaultServicePath(dbus_iface,
206 &default_service_path));
207 TEST_AND_RETURN_FALSE(GetServicePathType(dbus_iface,
208 default_service_path,
209 out_type));
210 return true;
211}
212
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700213} // namespace chromeos_update_engine