onc_translator_shill_to_onc.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/network/onc/onc_translator.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_reader.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_writer.h" 120f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "base/logging.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chromeos/network/network_state.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/network/network_util.h" 16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chromeos/network/onc/onc_signature.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/network/onc/onc_translation_tables.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/network/shill_property_util.h" 194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "components/onc/onc_constants.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/cros_system_api/dbus/service_constants.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromeos { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace onc { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Converts |str| to a base::Value of the given |type|. If the conversion fails, 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// returns NULL. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<base::Value> ConvertStringToValue(const std::string& str, 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Value::Type type) { 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Value* value; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type == base::Value::TYPE_STRING) { 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) value = new base::StringValue(str); 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value = base::JSONReader::Read(str); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (value == NULL || value->GetType() != type) { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete value; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value = NULL; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return make_scoped_ptr(value); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class implements the translation of properties from the given 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |shill_dictionary| to a new ONC object of signature |onc_signature|. Using 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// recursive calls to CreateTranslatedONCObject of new instances, nested objects 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// are translated. 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ShillToONCTranslator { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShillToONCTranslator(const base::DictionaryValue& shill_dictionary, 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const OncValueSignature& onc_signature) 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : shill_dictionary_(&shill_dictionary), 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) onc_signature_(&onc_signature) { 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) field_translation_table_ = GetFieldTranslationTable(onc_signature); 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShillToONCTranslator(const base::DictionaryValue& shill_dictionary, 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const OncValueSignature& onc_signature, 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const FieldTranslationEntry* field_translation_table) 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : shill_dictionary_(&shill_dictionary), 62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) onc_signature_(&onc_signature), 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) field_translation_table_(field_translation_table) { 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Translates the associated Shill dictionary and creates an ONC object of the 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // given signature. 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::DictionaryValue> CreateTranslatedONCObject(); 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void TranslateEthernet(); 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void TranslateOpenVPN(); 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void TranslateIPsec(); 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void TranslateVPN(); 750f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) void TranslateWiFiWithState(); 760f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) void TranslateCellularWithState(); 770f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) void TranslateCellularDevice(); 780f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) void TranslateNetworkWithState(); 790f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) void TranslateIPConfig(); 800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 810f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Creates an ONC object from |dictionary| according to the signature 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // associated to |onc_field_name| and adds it to |onc_object_| at 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |onc_field_name|. 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void TranslateAndAddNestedObject(const std::string& onc_field_name, 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::DictionaryValue& dictionary); 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Creates an ONC object from |shill_dictionary_| according to the signature 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // associated to |onc_field_name| and adds it to |onc_object_| at 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |onc_field_name|. 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void TranslateAndAddNestedObject(const std::string& onc_field_name); 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Translates a list of nested objects and adds the list to |onc_object_| at 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |onc_field_name|. If there are errors while parsing individual objects or 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // if the resulting list contains no entries, the result will not be added to 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |onc_object_|. 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void TranslateAndAddListOfObjects(const std::string& onc_field_name, 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::ListValue& list); 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Applies function CopyProperty to each field of |value_signature| and its 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // base signatures. 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void CopyPropertiesAccordingToSignature( 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const OncValueSignature* value_signature); 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Applies function CopyProperty to each field of |onc_signature_| and its 1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // base signatures. 1064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) void CopyPropertiesAccordingToSignature(); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If |shill_property_name| is defined in |field_signature|, copies this 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // entry from |shill_dictionary_| to |onc_object_| if it exists. 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void CopyProperty(const OncFieldSignature* field_signature); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If existent, translates the entry at |shill_property_name| in 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |shill_dictionary_| using |table|. It is an error if no matching table 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // entry is found. Writes the result as entry at |onc_field_name| in 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |onc_object_|. 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void TranslateWithTableAndSet(const std::string& shill_property_name, 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const StringTranslationEntry table[], 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& onc_field_name); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::DictionaryValue* shill_dictionary_; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const OncValueSignature* onc_signature_; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FieldTranslationEntry* field_translation_table_; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::DictionaryValue> onc_object_; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ShillToONCTranslator); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<base::DictionaryValue> 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ShillToONCTranslator::CreateTranslatedONCObject() { 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onc_object_.reset(new base::DictionaryValue); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (onc_signature_ == &kNetworkWithStateSignature) { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TranslateNetworkWithState(); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (onc_signature_ == &kEthernetSignature) { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TranslateEthernet(); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (onc_signature_ == &kVPNSignature) { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TranslateVPN(); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (onc_signature_ == &kOpenVPNSignature) { 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TranslateOpenVPN(); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (onc_signature_ == &kIPsecSignature) { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TranslateIPsec(); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (onc_signature_ == &kWiFiWithStateSignature) { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TranslateWiFiWithState(); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (onc_signature_ == &kCellularWithStateSignature) { 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (field_translation_table_ == kCellularDeviceTable) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TranslateCellularDevice(); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TranslateCellularWithState(); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (onc_signature_ == &kIPConfigSignature) { 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TranslateIPConfig(); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CopyPropertiesAccordingToSignature(); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return onc_object_.Pass(); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ShillToONCTranslator::TranslateEthernet() { 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string shill_network_type; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shill_dictionary_->GetStringWithoutPathExpansion(shill::kTypeProperty, 159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) &shill_network_type); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* onc_auth = ::onc::ethernet::kAuthenticationNone; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shill_network_type == shill::kTypeEthernetEap) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onc_auth = ::onc::ethernet::k8021X; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onc_object_->SetStringWithoutPathExpansion(::onc::ethernet::kAuthentication, 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onc_auth); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ShillToONCTranslator::TranslateOpenVPN() { 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shill_dictionary_->HasKey(shill::kOpenVPNVerifyX509NameProperty)) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TranslateAndAddNestedObject(::onc::openvpn::kVerifyX509); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Shill supports only one RemoteCertKU but ONC requires a list. If existing, 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // wraps the value into a list. 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string certKU; 17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (shill_dictionary_->GetStringWithoutPathExpansion( 17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) shill::kOpenVPNRemoteCertKUProperty, &certKU)) { 17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<base::ListValue> certKUs(new base::ListValue); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) certKUs->AppendString(certKU); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onc_object_->SetWithoutPathExpansion(::onc::openvpn::kRemoteCertKU, 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) certKUs.release()); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (const OncFieldSignature* field_signature = onc_signature_->fields; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) field_signature->onc_field_name != NULL; ++field_signature) { 184bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch const std::string& onc_field_name = field_signature->onc_field_name; 185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (onc_field_name == ::onc::vpn::kSaveCredentials || 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onc_field_name == ::onc::openvpn::kRemoteCertKU || 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onc_field_name == ::onc::openvpn::kServerCAPEMs) { 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CopyProperty(field_signature); 1890f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) continue; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string shill_property_name; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Value* shill_value = NULL; 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!field_translation_table_ || 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !GetShillPropertyName(field_signature->onc_field_name, 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) field_translation_table_, 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &shill_property_name) || 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !shill_dictionary_->GetWithoutPathExpansion(shill_property_name, 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &shill_value)) { 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::Value> translated; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string shill_str; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shill_value->GetAsString(&shill_str)) { 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Shill wants all Provider/VPN fields to be strings. Translates these 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // strings back to the correct ONC type. 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) translated = ConvertStringToValue( 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shill_str, 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) field_signature->value_signature->onc_type); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (translated.get() == NULL) { 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Shill property '" << shill_property_name 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "' with value " << *shill_value 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " couldn't be converted to base::Value::Type " 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << field_signature->value_signature->onc_type; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onc_object_->SetWithoutPathExpansion(onc_field_name, 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) translated.release()); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Shill property '" << shill_property_name 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "' has value " << *shill_value 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << ", but expected a string"; 2254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ShillToONCTranslator::TranslateIPsec() { 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CopyPropertiesAccordingToSignature(); 231 if (shill_dictionary_->HasKey(shill::kL2tpIpsecXauthUserProperty)) 232 TranslateAndAddNestedObject(::onc::ipsec::kXAUTH); 233} 234 235void ShillToONCTranslator::TranslateVPN() { 236 TranslateWithTableAndSet( 237 shill::kProviderTypeProperty, kVPNTypeTable, ::onc::vpn::kType); 238 CopyPropertiesAccordingToSignature(); 239 240 std::string vpn_type; 241 if (onc_object_->GetStringWithoutPathExpansion(::onc::vpn::kType, 242 &vpn_type)) { 243 if (vpn_type == ::onc::vpn::kTypeL2TP_IPsec) { 244 TranslateAndAddNestedObject(::onc::vpn::kIPsec); 245 TranslateAndAddNestedObject(::onc::vpn::kL2TP); 246 } else { 247 TranslateAndAddNestedObject(vpn_type); 248 } 249 } 250} 251 252void ShillToONCTranslator::TranslateWiFiWithState() { 253 TranslateWithTableAndSet( 254 shill::kSecurityProperty, kWiFiSecurityTable, ::onc::wifi::kSecurity); 255 std::string ssid = shill_property_util::GetSSIDFromProperties( 256 *shill_dictionary_, NULL /* ignore unknown encoding */); 257 if (!ssid.empty()) 258 onc_object_->SetStringWithoutPathExpansion(::onc::wifi::kSSID, ssid); 259 CopyPropertiesAccordingToSignature(); 260} 261 262void ShillToONCTranslator::TranslateCellularWithState() { 263 CopyPropertiesAccordingToSignature(); 264 const base::DictionaryValue* dictionary = NULL; 265 if (shill_dictionary_->GetDictionaryWithoutPathExpansion( 266 shill::kServingOperatorProperty, &dictionary)) { 267 TranslateAndAddNestedObject(::onc::cellular::kServingOperator, *dictionary); 268 } 269 if (shill_dictionary_->GetDictionaryWithoutPathExpansion( 270 shill::kCellularApnProperty, &dictionary)) { 271 TranslateAndAddNestedObject(::onc::cellular::kAPN, *dictionary); 272 } 273 // Merge the Device dictionary with this one (Cellular) using the 274 // CellularDevice signature. 275 const base::DictionaryValue* device_dictionary = NULL; 276 if (!shill_dictionary_->GetDictionaryWithoutPathExpansion( 277 shill::kDeviceProperty, &device_dictionary)) { 278 return; 279 } 280 ShillToONCTranslator nested_translator(*device_dictionary, 281 kCellularWithStateSignature, 282 kCellularDeviceTable); 283 scoped_ptr<base::DictionaryValue> nested_object = 284 nested_translator.CreateTranslatedONCObject(); 285 onc_object_->MergeDictionary(nested_object.get()); 286} 287 288void ShillToONCTranslator::TranslateCellularDevice() { 289 CopyPropertiesAccordingToSignature(); 290 const base::DictionaryValue* shill_sim_lock_status = NULL; 291 if (shill_dictionary_->GetDictionaryWithoutPathExpansion( 292 shill::kSIMLockStatusProperty, &shill_sim_lock_status)) { 293 TranslateAndAddNestedObject(::onc::cellular::kSIMLockStatus, 294 *shill_sim_lock_status); 295 } 296 const base::ListValue* shill_apns = NULL; 297 if (shill_dictionary_->GetListWithoutPathExpansion( 298 shill::kCellularApnListProperty, &shill_apns)) { 299 TranslateAndAddListOfObjects(::onc::cellular::kAPNList, *shill_apns); 300 } 301 const base::ListValue* shill_found_networks = NULL; 302 if (shill_dictionary_->GetListWithoutPathExpansion( 303 shill::kFoundNetworksProperty, &shill_found_networks)) { 304 TranslateAndAddListOfObjects(::onc::cellular::kFoundNetworks, 305 *shill_found_networks); 306 } 307} 308 309void ShillToONCTranslator::TranslateNetworkWithState() { 310 CopyPropertiesAccordingToSignature(); 311 312 std::string shill_network_type; 313 shill_dictionary_->GetStringWithoutPathExpansion(shill::kTypeProperty, 314 &shill_network_type); 315 std::string onc_network_type = ::onc::network_type::kEthernet; 316 if (shill_network_type != shill::kTypeEthernet && 317 shill_network_type != shill::kTypeEthernetEap) { 318 TranslateStringToONC( 319 kNetworkTypeTable, shill_network_type, &onc_network_type); 320 } 321 // Translate nested Cellular, WiFi, etc. properties. 322 if (!onc_network_type.empty()) { 323 onc_object_->SetStringWithoutPathExpansion(::onc::network_config::kType, 324 onc_network_type); 325 TranslateAndAddNestedObject(onc_network_type); 326 } 327 328 // Since Name is a read only field in Shill unless it's a VPN, it is copied 329 // here, but not when going the other direction (if it's not a VPN). 330 std::string name; 331 shill_dictionary_->GetStringWithoutPathExpansion(shill::kNameProperty, 332 &name); 333 onc_object_->SetStringWithoutPathExpansion(::onc::network_config::kName, 334 name); 335 336 // Limit ONC state to "NotConnected", "Connected", or "Connecting". 337 std::string state; 338 if (shill_dictionary_->GetStringWithoutPathExpansion(shill::kStateProperty, 339 &state)) { 340 std::string onc_state = ::onc::connection_state::kNotConnected; 341 if (NetworkState::StateIsConnected(state)) { 342 onc_state = ::onc::connection_state::kConnected; 343 } else if (NetworkState::StateIsConnecting(state)) { 344 onc_state = ::onc::connection_state::kConnecting; 345 } 346 onc_object_->SetStringWithoutPathExpansion( 347 ::onc::network_config::kConnectionState, onc_state); 348 } 349 350 // Use a human-readable aa:bb format for any hardware MAC address. Note: 351 // this property is provided by the caller but is not part of the Shill 352 // Service properties (it is copied from the Device properties). 353 std::string address; 354 if (shill_dictionary_->GetStringWithoutPathExpansion(shill::kAddressProperty, 355 &address)) { 356 onc_object_->SetStringWithoutPathExpansion( 357 ::onc::network_config::kMacAddress, 358 network_util::FormattedMacAddress(address)); 359 } 360 361 // Shill's Service has an IPConfig property (note the singular), not an 362 // IPConfigs property. However, we require the caller of the translation to 363 // patch the Shill dictionary before passing it to the translator. 364 const base::ListValue* shill_ipconfigs = NULL; 365 if (shill_dictionary_->GetListWithoutPathExpansion(shill::kIPConfigsProperty, 366 &shill_ipconfigs)) { 367 TranslateAndAddListOfObjects(::onc::network_config::kIPConfigs, 368 *shill_ipconfigs); 369 } 370} 371 372void ShillToONCTranslator::TranslateIPConfig() { 373 CopyPropertiesAccordingToSignature(); 374 std::string shill_ip_method; 375 shill_dictionary_->GetStringWithoutPathExpansion(shill::kMethodProperty, 376 &shill_ip_method); 377 std::string type; 378 if (shill_ip_method == shill::kTypeIPv4 || 379 shill_ip_method == shill::kTypeDHCP) { 380 type = ::onc::ipconfig::kIPv4; 381 } else if (shill_ip_method == shill::kTypeIPv6 || 382 shill_ip_method == shill::kTypeDHCP6) { 383 type = ::onc::ipconfig::kIPv6; 384 } else { 385 return; // Ignore unhandled IPConfig types, e.g. bootp, zeroconf, ppp 386 } 387 388 onc_object_->SetStringWithoutPathExpansion(::onc::ipconfig::kType, type); 389} 390 391void ShillToONCTranslator::TranslateAndAddNestedObject( 392 const std::string& onc_field_name) { 393 TranslateAndAddNestedObject(onc_field_name, *shill_dictionary_); 394} 395 396void ShillToONCTranslator::TranslateAndAddNestedObject( 397 const std::string& onc_field_name, 398 const base::DictionaryValue& dictionary) { 399 const OncFieldSignature* field_signature = 400 GetFieldSignature(*onc_signature_, onc_field_name); 401 DCHECK(field_signature) << "Unable to find signature for field " 402 << onc_field_name << "."; 403 ShillToONCTranslator nested_translator(dictionary, 404 *field_signature->value_signature); 405 scoped_ptr<base::DictionaryValue> nested_object = 406 nested_translator.CreateTranslatedONCObject(); 407 if (nested_object->empty()) 408 return; 409 onc_object_->SetWithoutPathExpansion(onc_field_name, nested_object.release()); 410} 411 412void ShillToONCTranslator::TranslateAndAddListOfObjects( 413 const std::string& onc_field_name, 414 const base::ListValue& list) { 415 const OncFieldSignature* field_signature = 416 GetFieldSignature(*onc_signature_, onc_field_name); 417 if (field_signature->value_signature->onc_type != base::Value::TYPE_LIST) { 418 LOG(ERROR) << "ONC Field name: '" << onc_field_name << "' has type '" 419 << field_signature->value_signature->onc_type 420 << "', expected: base::Value::TYPE_LIST."; 421 return; 422 } 423 DCHECK(field_signature->value_signature->onc_array_entry_signature); 424 scoped_ptr<base::ListValue> result(new base::ListValue()); 425 for (base::ListValue::const_iterator it = list.begin(); 426 it != list.end(); ++it) { 427 const base::DictionaryValue* shill_value = NULL; 428 if (!(*it)->GetAsDictionary(&shill_value)) 429 continue; 430 ShillToONCTranslator nested_translator( 431 *shill_value, 432 *field_signature->value_signature->onc_array_entry_signature); 433 scoped_ptr<base::DictionaryValue> nested_object = 434 nested_translator.CreateTranslatedONCObject(); 435 // If the nested object couldn't be parsed, simply omit it. 436 if (nested_object->empty()) 437 continue; 438 result->Append(nested_object.release()); 439 } 440 // If there are no entries in the list, there is no need to expose this field. 441 if (result->empty()) 442 return; 443 onc_object_->SetWithoutPathExpansion(onc_field_name, result.release()); 444} 445 446void ShillToONCTranslator::CopyPropertiesAccordingToSignature() { 447 CopyPropertiesAccordingToSignature(onc_signature_); 448} 449 450void ShillToONCTranslator::CopyPropertiesAccordingToSignature( 451 const OncValueSignature* value_signature) { 452 if (value_signature->base_signature) 453 CopyPropertiesAccordingToSignature(value_signature->base_signature); 454 for (const OncFieldSignature* field_signature = value_signature->fields; 455 field_signature->onc_field_name != NULL; ++field_signature) { 456 CopyProperty(field_signature); 457 } 458} 459 460void ShillToONCTranslator::CopyProperty( 461 const OncFieldSignature* field_signature) { 462 std::string shill_property_name; 463 const base::Value* shill_value = NULL; 464 if (!field_translation_table_ || 465 !GetShillPropertyName(field_signature->onc_field_name, 466 field_translation_table_, 467 &shill_property_name) || 468 !shill_dictionary_->GetWithoutPathExpansion(shill_property_name, 469 &shill_value)) { 470 return; 471 } 472 473 if (shill_value->GetType() != field_signature->value_signature->onc_type) { 474 LOG(ERROR) << "Shill property '" << shill_property_name 475 << "' with value " << *shill_value 476 << " has base::Value::Type " << shill_value->GetType() 477 << " but ONC field '" << field_signature->onc_field_name 478 << "' requires type " 479 << field_signature->value_signature->onc_type << "."; 480 return; 481 } 482 483 onc_object_->SetWithoutPathExpansion(field_signature->onc_field_name, 484 shill_value->DeepCopy()); 485} 486 487void ShillToONCTranslator::TranslateWithTableAndSet( 488 const std::string& shill_property_name, 489 const StringTranslationEntry table[], 490 const std::string& onc_field_name) { 491 std::string shill_value; 492 if (!shill_dictionary_->GetStringWithoutPathExpansion(shill_property_name, 493 &shill_value)) { 494 return; 495 } 496 std::string onc_value; 497 if (TranslateStringToONC(table, shill_value, &onc_value)) { 498 onc_object_->SetStringWithoutPathExpansion(onc_field_name, onc_value); 499 return; 500 } 501 LOG(ERROR) << "Shill property '" << shill_property_name << "' with value " 502 << shill_value << " couldn't be translated to ONC"; 503} 504 505} // namespace 506 507scoped_ptr<base::DictionaryValue> TranslateShillServiceToONCPart( 508 const base::DictionaryValue& shill_dictionary, 509 const OncValueSignature* onc_signature) { 510 CHECK(onc_signature != NULL); 511 512 ShillToONCTranslator translator(shill_dictionary, *onc_signature); 513 return translator.CreateTranslatedONCObject(); 514} 515 516} // namespace onc 517} // namespace chromeos 518