1aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
2aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Copyright (C) 2012 The Android Open Source Project
3aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
4aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Licensed under the Apache License, Version 2.0 (the "License");
5aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// you may not use this file except in compliance with the License.
6aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// You may obtain a copy of the License at
7aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
8aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//      http://www.apache.org/licenses/LICENSE-2.0
9aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
10aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Unless required by applicable law or agreed to in writing, software
11aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// distributed under the License is distributed on an "AS IS" BASIS,
12aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// See the License for the specific language governing permissions and
14aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// limitations under the License.
15aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
16d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes
174348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan#include "update_engine/connection_manager.h"
18d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes
19d2779df63aaad8b65fc5d4badee7dbc9bed7f2b6Alex Vakulenko#include <set>
20d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes#include <string>
21d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes
224348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan#include <base/stl_util.h>
2375039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko#include <base/strings/string_util.h>
241f84723f499b3b309efac11324ed4e6c937341b6Gilad Arnold#include <policy/device_policy.h>
25d6deb1d0357f47d5525bfaeffa6c201b19abd3e7Alex Deymo#include <shill/dbus-constants.h>
26d6deb1d0357f47d5525bfaeffa6c201b19abd3e7Alex Deymo#include <shill/dbus-proxies.h>
27d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes
2839910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/prefs.h"
2939910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/utils.h"
304348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan#include "update_engine/system_state.h"
31d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes
32305345001d85ca2282112c2a30fe75c7a4773491Alex Deymousing org::chromium::flimflam::ManagerProxyInterface;
33305345001d85ca2282112c2a30fe75c7a4773491Alex Deymousing org::chromium::flimflam::ServiceProxyInterface;
344348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasanusing std::set;
35d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyesusing std::string;
36d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes
37d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyesnamespace chromeos_update_engine {
38d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes
39d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyesnamespace {
40d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes
41305345001d85ca2282112c2a30fe75c7a4773491Alex DeymoNetworkConnectionType ParseConnectionType(const string& type_str) {
42305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (type_str == shill::kTypeEthernet) {
4375eac7e523f825afdb88508922d7dc65fa366b19Alex Deymo    return NetworkConnectionType::kEthernet;
44305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  } else if (type_str == shill::kTypeWifi) {
4575eac7e523f825afdb88508922d7dc65fa366b19Alex Deymo    return NetworkConnectionType::kWifi;
46305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  } else if (type_str == shill::kTypeWimax) {
4775eac7e523f825afdb88508922d7dc65fa366b19Alex Deymo    return NetworkConnectionType::kWimax;
48305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  } else if (type_str == shill::kTypeBluetooth) {
4975eac7e523f825afdb88508922d7dc65fa366b19Alex Deymo    return NetworkConnectionType::kBluetooth;
50305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  } else if (type_str == shill::kTypeCellular) {
5175eac7e523f825afdb88508922d7dc65fa366b19Alex Deymo    return NetworkConnectionType::kCellular;
52d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes  }
5375eac7e523f825afdb88508922d7dc65fa366b19Alex Deymo  return NetworkConnectionType::kUnknown;
54d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes}
55d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes
56305345001d85ca2282112c2a30fe75c7a4773491Alex DeymoNetworkTethering ParseTethering(const string& tethering_str) {
57305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (tethering_str == shill::kTetheringNotDetectedState) {
586ae9120dc76ce9a3c8d05f71c05f23e3f4bdc6bdAlex Deymo    return NetworkTethering::kNotDetected;
59305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  } else if (tethering_str == shill::kTetheringSuspectedState) {
606ae9120dc76ce9a3c8d05f71c05f23e3f4bdc6bdAlex Deymo    return NetworkTethering::kSuspected;
61305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  } else if (tethering_str == shill::kTetheringConfirmedState) {
626ae9120dc76ce9a3c8d05f71c05f23e3f4bdc6bdAlex Deymo    return NetworkTethering::kConfirmed;
636ae9120dc76ce9a3c8d05f71c05f23e3f4bdc6bdAlex Deymo  }
646ae9120dc76ce9a3c8d05f71c05f23e3f4bdc6bdAlex Deymo  LOG(WARNING) << "Unknown Tethering value: " << tethering_str;
656ae9120dc76ce9a3c8d05f71c05f23e3f4bdc6bdAlex Deymo  return NetworkTethering::kUnknown;
666ae9120dc76ce9a3c8d05f71c05f23e3f4bdc6bdAlex Deymo}
676ae9120dc76ce9a3c8d05f71c05f23e3f4bdc6bdAlex Deymo
68d2779df63aaad8b65fc5d4badee7dbc9bed7f2b6Alex Vakulenko}  // namespace
69d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes
70305345001d85ca2282112c2a30fe75c7a4773491Alex DeymoConnectionManager::ConnectionManager(ShillProxyInterface* shill_proxy,
71305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo                                     SystemState* system_state)
72305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    : shill_proxy_(shill_proxy), system_state_(system_state) {}
734348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan
746ae9120dc76ce9a3c8d05f71c05f23e3f4bdc6bdAlex Deymobool ConnectionManager::IsUpdateAllowedOver(NetworkConnectionType type,
756ae9120dc76ce9a3c8d05f71c05f23e3f4bdc6bdAlex Deymo                                            NetworkTethering tethering) const {
764348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan  switch (type) {
7775eac7e523f825afdb88508922d7dc65fa366b19Alex Deymo    case NetworkConnectionType::kBluetooth:
784348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan      return false;
794348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan
8075eac7e523f825afdb88508922d7dc65fa366b19Alex Deymo    case NetworkConnectionType::kCellular: {
814348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan      set<string> allowed_types;
824348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan      const policy::DevicePolicy* device_policy =
836f6ea00aa8c4cf54b6842be32ca1226854c24f78Jay Srinivasan          system_state_->device_policy();
84f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo
85f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo      // A device_policy is loaded in a lazy way right before an update check,
86f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo      // so the device_policy should be already loaded at this point. If it's
87f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo      // not, return a safe value for this setting.
884348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan      if (!device_policy) {
89f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo        LOG(INFO) << "Disabling updates over cellular networks as there's no "
90f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo                     "device policy loaded yet.";
914348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan        return false;
924348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan      }
934348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan
94f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo      if (device_policy->GetAllowedConnectionTypesForUpdate(&allowed_types)) {
95f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo        // The update setting is enforced by the device policy.
96f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo
979a423ff19e3a7503cd8128998b3a10d65c499fdcGilad Arnold        if (!ContainsKey(allowed_types, shill::kTypeCellular)) {
98f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo          LOG(INFO) << "Disabling updates over cellular connection as it's not "
99f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo                       "allowed in the device policy.";
100f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo          return false;
101f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo        }
102f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo
103f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo        LOG(INFO) << "Allowing updates over cellular per device policy.";
104f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo        return true;
105f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo      } else {
106f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo        // There's no update setting in the device policy, using the local user
107f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo        // setting.
108f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo        PrefsInterface* prefs = system_state_->prefs();
109f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo
110f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo        if (!prefs || !prefs->Exists(kPrefsUpdateOverCellularPermission)) {
111f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo          LOG(INFO) << "Disabling updates over cellular connection as there's "
112f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo                       "no device policy setting nor user preference present.";
113f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo          return false;
114f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo        }
115f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo
116efb7c4c605440fdc6297deed8fa9d1aecb77235eAlex Deymo        bool stored_value;
117efb7c4c605440fdc6297deed8fa9d1aecb77235eAlex Deymo        if (!prefs->GetBoolean(kPrefsUpdateOverCellularPermission,
118efb7c4c605440fdc6297deed8fa9d1aecb77235eAlex Deymo                               &stored_value)) {
119f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo          return false;
120efb7c4c605440fdc6297deed8fa9d1aecb77235eAlex Deymo        }
121f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo
122f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo        if (!stored_value) {
123f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo          LOG(INFO) << "Disabling updates over cellular connection per user "
124f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo                       "setting.";
125f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo          return false;
126f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo        }
127f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo        LOG(INFO) << "Allowing updates over cellular per user setting.";
128f4867c4dab4d1ca566f1aa3f585bd16d87b911ddAlex Deymo        return true;
1294348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan      }
1304348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan    }
1314348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan
1324348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan    default:
1336ae9120dc76ce9a3c8d05f71c05f23e3f4bdc6bdAlex Deymo      if (tethering == NetworkTethering::kConfirmed) {
1346ae9120dc76ce9a3c8d05f71c05f23e3f4bdc6bdAlex Deymo        // Treat this connection as if it is a cellular connection.
1356ae9120dc76ce9a3c8d05f71c05f23e3f4bdc6bdAlex Deymo        LOG(INFO) << "Current connection is confirmed tethered, using Cellular "
1366ae9120dc76ce9a3c8d05f71c05f23e3f4bdc6bdAlex Deymo                     "setting.";
13775eac7e523f825afdb88508922d7dc65fa366b19Alex Deymo        return IsUpdateAllowedOver(NetworkConnectionType::kCellular,
13875eac7e523f825afdb88508922d7dc65fa366b19Alex Deymo                                   NetworkTethering::kUnknown);
1396ae9120dc76ce9a3c8d05f71c05f23e3f4bdc6bdAlex Deymo      }
1404348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan      return true;
1414348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan  }
1424348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan}
1434348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasan
144f6ee0163504eaf1a7cc136ba2c075d77ae2b4dd5Alex Deymo// static
1454348879380222dc8c74b0976e527bf3da66ba08fJay Srinivasanconst char* ConnectionManager::StringForConnectionType(
146f6ee0163504eaf1a7cc136ba2c075d77ae2b4dd5Alex Deymo    NetworkConnectionType type) {
14775eac7e523f825afdb88508922d7dc65fa366b19Alex Deymo  switch (type) {
14875eac7e523f825afdb88508922d7dc65fa366b19Alex Deymo    case NetworkConnectionType::kEthernet:
14975eac7e523f825afdb88508922d7dc65fa366b19Alex Deymo      return shill::kTypeEthernet;
15075eac7e523f825afdb88508922d7dc65fa366b19Alex Deymo    case NetworkConnectionType::kWifi:
15175eac7e523f825afdb88508922d7dc65fa366b19Alex Deymo      return shill::kTypeWifi;
15275eac7e523f825afdb88508922d7dc65fa366b19Alex Deymo    case NetworkConnectionType::kWimax:
15375eac7e523f825afdb88508922d7dc65fa366b19Alex Deymo      return shill::kTypeWimax;
15475eac7e523f825afdb88508922d7dc65fa366b19Alex Deymo    case NetworkConnectionType::kBluetooth:
15575eac7e523f825afdb88508922d7dc65fa366b19Alex Deymo      return shill::kTypeBluetooth;
15675eac7e523f825afdb88508922d7dc65fa366b19Alex Deymo    case NetworkConnectionType::kCellular:
15775eac7e523f825afdb88508922d7dc65fa366b19Alex Deymo      return shill::kTypeCellular;
15875eac7e523f825afdb88508922d7dc65fa366b19Alex Deymo    case NetworkConnectionType::kUnknown:
15975eac7e523f825afdb88508922d7dc65fa366b19Alex Deymo      return "Unknown";
160d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes  }
16175eac7e523f825afdb88508922d7dc65fa366b19Alex Deymo  return "Unknown";
162d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes}
163d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes
1646ae9120dc76ce9a3c8d05f71c05f23e3f4bdc6bdAlex Deymobool ConnectionManager::GetConnectionProperties(
1656ae9120dc76ce9a3c8d05f71c05f23e3f4bdc6bdAlex Deymo    NetworkConnectionType* out_type,
166305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    NetworkTethering* out_tethering) {
167758dd53cf503adbcb049909f25f54603d411be09Alex Deymo  dbus::ObjectPath default_service_path;
168305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  TEST_AND_RETURN_FALSE(GetDefaultServicePath(&default_service_path));
169758dd53cf503adbcb049909f25f54603d411be09Alex Deymo  if (!default_service_path.IsValid())
170305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    return false;
1711fbaac8c911ee484de521e8302d28543ad33cfe1Alex Deymo  // Shill uses the "/" service path to indicate that it is not connected.
1721fbaac8c911ee484de521e8302d28543ad33cfe1Alex Deymo  if (default_service_path.value() == "/")
1731fbaac8c911ee484de521e8302d28543ad33cfe1Alex Deymo    return false;
174305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  TEST_AND_RETURN_FALSE(
175305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo      GetServicePathProperties(default_service_path, out_type, out_tethering));
176305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  return true;
177305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo}
178305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo
179758dd53cf503adbcb049909f25f54603d411be09Alex Deymobool ConnectionManager::GetDefaultServicePath(dbus::ObjectPath* out_path) {
1803f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::VariantDictionary properties;
1813f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::ErrorPtr error;
182305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  ManagerProxyInterface* manager_proxy = shill_proxy_->GetManagerProxy();
183305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (!manager_proxy)
184305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    return false;
185305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  TEST_AND_RETURN_FALSE(manager_proxy->GetProperties(&properties, &error));
186305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo
187305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  const auto& prop_default_service =
188305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo      properties.find(shill::kDefaultServiceProperty);
189305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (prop_default_service == properties.end())
190305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    return false;
191305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo
192758dd53cf503adbcb049909f25f54603d411be09Alex Deymo  *out_path = prop_default_service->second.TryGet<dbus::ObjectPath>();
193758dd53cf503adbcb049909f25f54603d411be09Alex Deymo  return out_path->IsValid();
194305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo}
195305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo
196305345001d85ca2282112c2a30fe75c7a4773491Alex Deymobool ConnectionManager::GetServicePathProperties(
197758dd53cf503adbcb049909f25f54603d411be09Alex Deymo    const dbus::ObjectPath& path,
198305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    NetworkConnectionType* out_type,
199305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    NetworkTethering* out_tethering) {
200305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  // We create and dispose the ServiceProxyInterface on every request.
201305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  std::unique_ptr<ServiceProxyInterface> service =
202305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo      shill_proxy_->GetServiceForPath(path);
203305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo
2043f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::VariantDictionary properties;
2053f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::ErrorPtr error;
206305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  TEST_AND_RETURN_FALSE(service->GetProperties(&properties, &error));
207305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo
208305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  // Populate the out_tethering.
209305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  const auto& prop_tethering = properties.find(shill::kTetheringProperty);
210305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (prop_tethering == properties.end()) {
211305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    // Set to Unknown if not present.
212305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    *out_tethering = NetworkTethering::kUnknown;
213305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  } else {
214305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    // If the property doesn't contain a string value, the empty string will
215305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    // become kUnknown.
216305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    *out_tethering = ParseTethering(prop_tethering->second.TryGet<string>());
217305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  }
218305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo
219305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  // Populate the out_type property.
220305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  const auto& prop_type = properties.find(shill::kTypeProperty);
221305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (prop_type == properties.end()) {
222305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    // Set to Unknown if not present.
223305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    *out_type = NetworkConnectionType::kUnknown;
224305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    return false;
225305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  }
226305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo
227305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  string type_str = prop_type->second.TryGet<string>();
228305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  if (type_str == shill::kTypeVPN) {
229305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    const auto& prop_physical =
230305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo        properties.find(shill::kPhysicalTechnologyProperty);
231305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    if (prop_physical == properties.end()) {
232305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo      LOG(ERROR) << "No PhysicalTechnology property found for a VPN"
233758dd53cf503adbcb049909f25f54603d411be09Alex Deymo                    " connection (service: "
234758dd53cf503adbcb049909f25f54603d411be09Alex Deymo                 << path.value() << "). Returning default kUnknown value.";
235305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo      *out_type = NetworkConnectionType::kUnknown;
236305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    } else {
237305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo      *out_type = ParseConnectionType(prop_physical->second.TryGet<string>());
238305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    }
239305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  } else {
240305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo    *out_type = ParseConnectionType(type_str);
241305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo  }
242d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes  return true;
243d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes}
244d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes
245d57d1474a7bb152adf10d8c31d7ef6d40d27f7ccAndrew de los Reyes}  // namespace chromeos_update_engine
246