blob: e8abd204b82cc040a4936587d7d1edf102222e20 [file] [log] [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/ash/components/network/network_util.h"
#include <stddef.h>
#include <stdint.h>
#include <utility>
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "base/values.h"
#include "chromeos/ash/components/login/login_state/login_state.h"
#include "chromeos/ash/components/network/device_state.h"
#include "chromeos/ash/components/network/managed_network_configuration_handler.h"
#include "chromeos/ash/components/network/network_state.h"
#include "chromeos/ash/components/network/network_state_handler.h"
#include "chromeos/ash/components/network/network_ui_data.h"
#include "chromeos/ash/components/network/onc/onc_translation_tables.h"
#include "chromeos/ash/components/network/onc/onc_translator.h"
#include "chromeos/components/onc/onc_signature.h"
#include "components/device_event_log/device_event_log.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace ash {
WifiAccessPoint::WifiAccessPoint()
: signal_strength(0),
signal_to_noise(0),
channel(0) {
}
WifiAccessPoint::WifiAccessPoint(const WifiAccessPoint& other) = default;
WifiAccessPoint::~WifiAccessPoint() = default;
CellTower::CellTower() = default;
CellTower::CellTower(const CellTower& other) = default;
CellTower::~CellTower() = default;
CellularScanResult::CellularScanResult() = default;
CellularScanResult::CellularScanResult(const CellularScanResult& other) =
default;
CellularScanResult::~CellularScanResult() = default;
CellularSIMSlotInfo::CellularSIMSlotInfo() = default;
CellularSIMSlotInfo::CellularSIMSlotInfo(const CellularSIMSlotInfo& other) =
default;
CellularSIMSlotInfo::~CellularSIMSlotInfo() = default;
namespace network_util {
std::string PrefixLengthToNetmask(int32_t prefix_length) {
std::string netmask;
// Return the empty string for invalid inputs.
if (prefix_length < 0 || prefix_length > 32)
return netmask;
for (int i = 0; i < 4; i++) {
int remainder = 8;
if (prefix_length >= 8) {
prefix_length -= 8;
} else {
remainder = prefix_length;
prefix_length = 0;
}
if (i > 0)
netmask += ".";
int value = remainder == 0 ? 0 :
((2L << (remainder - 1)) - 1) << (8 - remainder);
netmask += base::NumberToString(value);
}
return netmask;
}
int32_t NetmaskToPrefixLength(const std::string& netmask) {
int count = 0;
int prefix_length = 0;
base::StringTokenizer t(netmask, ".");
while (t.GetNext()) {
// If there are more than 4 numbers, then it's invalid.
if (count == 4)
return -1;
std::string token = t.token();
// If we already found the last mask and the current one is not
// "0" then the netmask is invalid. For example, 255.224.255.0
if (prefix_length / 8 != count) {
if (token != "0")
return -1;
} else if (token == "255") {
prefix_length += 8;
} else if (token == "254") {
prefix_length += 7;
} else if (token == "252") {
prefix_length += 6;
} else if (token == "248") {
prefix_length += 5;
} else if (token == "240") {
prefix_length += 4;
} else if (token == "224") {
prefix_length += 3;
} else if (token == "192") {
prefix_length += 2;
} else if (token == "128") {
prefix_length += 1;
} else if (token == "0") {
prefix_length += 0;
} else {
// mask is not a valid number.
return -1;
}
count++;
}
if (count < 4)
return -1;
return prefix_length;
}
std::string FormattedMacAddress(const std::string& shill_mac_address) {
if (shill_mac_address.size() % 2 != 0)
return shill_mac_address;
std::string result;
for (size_t i = 0; i < shill_mac_address.size(); ++i) {
if ((i != 0) && (i % 2 == 0))
result.push_back(':');
result.push_back(base::ToUpperASCII(shill_mac_address[i]));
}
return result;
}
bool ParseCellularScanResults(const base::Value::List& list,
std::vector<CellularScanResult>* scan_results) {
scan_results->clear();
scan_results->reserve(list.size());
for (const auto& value : list) {
const base::Value::Dict* value_dict = value.GetIfDict();
if (!value_dict) {
return false;
}
CellularScanResult scan_result;
// If the network id property is not present then this network cannot be
// connected to so don't include it in the results.
const std::string* network_id =
value_dict->FindString(shill::kNetworkIdProperty);
if (!network_id) {
continue;
}
scan_result.network_id = *network_id;
const std::string* status = value_dict->FindString(shill::kStatusProperty);
if (status) {
scan_result.status = *status;
}
const std::string* long_name =
value_dict->FindString(shill::kLongNameProperty);
if (long_name) {
scan_result.long_name = *long_name;
}
const std::string* short_name =
value_dict->FindString(shill::kShortNameProperty);
if (short_name) {
scan_result.short_name = *short_name;
}
const std::string* technology =
value_dict->FindString(shill::kTechnologyProperty);
if (technology) {
scan_result.technology = *technology;
}
scan_results->push_back(scan_result);
}
return true;
}
bool ParseCellularSIMSlotInfo(
const base::Value::List& list,
std::vector<CellularSIMSlotInfo>* sim_slot_infos) {
sim_slot_infos->clear();
sim_slot_infos->reserve(list.size());
for (size_t i = 0; i < list.size(); i++) {
const base::Value::Dict* value = list[i].GetIfDict();
if (!value) {
return false;
}
CellularSIMSlotInfo sim_slot_info;
// The |slot_id| should start with 1.
sim_slot_info.slot_id = i + 1;
const std::string* eid = value->FindString(shill::kSIMSlotInfoEID);
if (eid) {
sim_slot_info.eid = *eid;
}
const std::string* iccid = value->FindString(shill::kSIMSlotInfoICCID);
if (iccid) {
sim_slot_info.iccid = *iccid;
}
std::optional<bool> primary = value->FindBool(shill::kSIMSlotInfoPrimary);
sim_slot_info.primary = primary.has_value() ? *primary : false;
sim_slot_infos->push_back(sim_slot_info);
}
return true;
}
base::Value::Dict TranslateNetworkStateToONC(const NetworkState* network) {
// Get the properties from the NetworkState.
base::Value::Dict shill_dictionary;
network->GetStateProperties(&shill_dictionary);
// Get any Device properties required to translate state.
if (NetworkTypePattern::Cellular().MatchesType(network->type())) {
const DeviceState* device =
NetworkHandler::Get()->network_state_handler()->GetDeviceState(
network->device_path());
if (device) {
shill_dictionary.Set(
shill::kDeviceProperty,
base::Value::Dict()
// We need to set Device.Cellular.ProviderRequiresRoaming so that
// Cellular.RoamingState can be set correctly for badging network
// icons.
.Set(shill::kProviderRequiresRoamingProperty,
device->provider_requires_roaming())
// Scanning is also used in the UI when displaying a list of
// networks.
.Set(shill::kScanningProperty, device->scanning()));
}
}
// NetworkState is always associated with the primary user profile, regardless
// of what profile is associated with the page that calls this method. We do
// not expose any sensitive properties in the resulting dictionary, it is
// only used to show connection state and icons.
std::string user_id_hash = LoginState::Get()->primary_user_hash();
::onc::ONCSource onc_source = ::onc::ONC_SOURCE_NONE;
NetworkHandler::Get()
->managed_network_configuration_handler()
->FindPolicyByGUID(user_id_hash, network->guid(), &onc_source);
base::Value::Dict onc_dictionary = onc::TranslateShillServiceToONCPart(
shill_dictionary, onc_source, &chromeos::onc::kNetworkWithStateSignature,
network);
// Remove IPAddressConfigType/NameServersConfigType as these were
// historically not provided by TranslateNetworkStateToONC.
// The source shill properties for those ONC properties are not provided by
// NetworkState::GetStateProperties, however since CL:2530330 these are
// assumed to have defaults that are always enforced during ONC translation.
onc_dictionary.Remove(::onc::network_config::kIPAddressConfigType);
onc_dictionary.Remove(::onc::network_config::kNameServersConfigType);
return onc_dictionary;
}
base::Value::List TranslateNetworkListToONC(NetworkTypePattern pattern,
bool configured_only,
bool visible_only,
int limit) {
NetworkStateHandler::NetworkStateList network_states;
NetworkHandler::Get()->network_state_handler()->GetNetworkListByType(
pattern, configured_only, visible_only, limit, &network_states);
base::Value::List network_properties_list;
for (const NetworkState* state : network_states) {
network_properties_list.Append(TranslateNetworkStateToONC(state));
}
return network_properties_list;
}
std::string TranslateONCTypeToShill(const std::string& onc_type) {
if (onc_type == ::onc::network_type::kEthernet)
return shill::kTypeEthernet;
std::string shill_type;
onc::TranslateStringToShill(onc::kNetworkTypeTable, onc_type, &shill_type);
return shill_type;
}
std::string TranslateONCSecurityToShill(const std::string& onc_security) {
std::string shill_security;
onc::TranslateStringToShill(onc::kWiFiSecurityTable, onc_security,
&shill_security);
return shill_security;
}
std::string TranslateShillTypeToONC(const std::string& shill_type) {
if (shill_type == shill::kTypeEthernet)
return ::onc::network_type::kEthernet;
std::string onc_type;
onc::TranslateStringToONC(onc::kNetworkTypeTable, shill_type, &onc_type);
return onc_type;
}
} // namespace network_util
} // namespace ash