// // Copyright (C) 2012 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "shill/static_ip_parameters.h" #include #include #include #if defined(__ANDROID__) #include #else #include #endif // __ANDROID__ #include "shill/error.h" #include "shill/logging.h" #include "shill/net/ip_address.h" #include "shill/property_accessor.h" #include "shill/property_store.h" #include "shill/store_interface.h" using std::string; using std::vector; namespace shill { // static const char StaticIPParameters::kConfigKeyPrefix[] = "StaticIP."; // static const char StaticIPParameters::kSavedConfigKeyPrefix[] = "SavedIP."; // static const StaticIPParameters::Property StaticIPParameters::kProperties[] = { { kAddressProperty, Property::kTypeString }, { kGatewayProperty, Property::kTypeString }, { kMtuProperty, Property::kTypeInt32 }, { kNameServersProperty, Property::kTypeStrings }, { kPeerAddressProperty, Property::kTypeString }, { kPrefixlenProperty, Property::kTypeInt32 } }; StaticIPParameters::StaticIPParameters() {} StaticIPParameters::~StaticIPParameters() {} void StaticIPParameters::PlumbPropertyStore(PropertyStore* store) { // These individual fields will be deprecated once Chrome starts using // the KeyValueStore dict directly. for (size_t i = 0; i < arraysize(kProperties); ++i) { const Property& property = kProperties[i]; const string name(string(kConfigKeyPrefix) + property.name); const string saved_name(string(kSavedConfigKeyPrefix) + property.name); switch (property.type) { case Property::kTypeInt32: store->RegisterDerivedInt32( name, Int32Accessor( new CustomMappedAccessor( this, &StaticIPParameters::ClearMappedProperty, &StaticIPParameters::GetMappedInt32Property, &StaticIPParameters::SetMappedInt32Property, i))); store->RegisterDerivedInt32( saved_name, Int32Accessor( new CustomMappedAccessor( this, &StaticIPParameters::ClearMappedSavedProperty, &StaticIPParameters::GetMappedSavedInt32Property, &StaticIPParameters::SetMappedSavedInt32Property, i))); break; case Property::kTypeString: store->RegisterDerivedString( name, StringAccessor( new CustomMappedAccessor( this, &StaticIPParameters::ClearMappedProperty, &StaticIPParameters::GetMappedStringProperty, &StaticIPParameters::SetMappedStringProperty, i))); store->RegisterDerivedString( saved_name, StringAccessor( new CustomMappedAccessor( this, &StaticIPParameters::ClearMappedSavedProperty, &StaticIPParameters::GetMappedSavedStringProperty, &StaticIPParameters::SetMappedSavedStringProperty, i))); break; case Property::kTypeStrings: // Since Chrome is still using string for the nameservers, the // registered function will convert the string from/to string vector // stored in the KeyValueStore. store->RegisterDerivedString( name, StringAccessor( new CustomMappedAccessor( this, &StaticIPParameters::ClearMappedProperty, &StaticIPParameters::GetMappedStringsProperty, &StaticIPParameters::SetMappedStringsProperty, i))); store->RegisterDerivedString( saved_name, StringAccessor( new CustomMappedAccessor( this, &StaticIPParameters::ClearMappedSavedProperty, &StaticIPParameters::GetMappedSavedStringsProperty, &StaticIPParameters::SetMappedSavedStringsProperty, i))); break; default: NOTIMPLEMENTED(); break; } } // Register KeyValueStore for both static ip and saved ip parameters. store->RegisterDerivedKeyValueStore( kSavedIPConfigProperty, KeyValueStoreAccessor( new CustomAccessor( this, &StaticIPParameters::GetSavedIPConfig, nullptr))); store->RegisterDerivedKeyValueStore( kStaticIPConfigProperty, KeyValueStoreAccessor( new CustomAccessor( this, &StaticIPParameters::GetStaticIPConfig, &StaticIPParameters::SetStaticIPConfig))); } void StaticIPParameters::Load( StoreInterface* storage, const string& storage_id) { for (size_t i = 0; i < arraysize(kProperties); ++i) { const Property& property = kProperties[i]; const string name(string(kConfigKeyPrefix) + property.name); switch (property.type) { case Property::kTypeInt32: { int32_t value; if (storage->GetInt(storage_id, name, &value)) { args_.SetInt(property.name, value); } else { args_.RemoveInt(property.name); } } break; case Property::kTypeString: { string value; if (storage->GetString(storage_id, name, &value)) { args_.SetString(property.name, value); } else { args_.RemoveString(property.name); } } break; case Property::kTypeStrings: { // Name servers field is stored in storage as comma separated string. // Keep it as is to be backward compatible. string value; if (storage->GetString(storage_id, name, &value)) { vector string_list = base::SplitString( value, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); args_.SetStrings(property.name, string_list); } else { args_.RemoveStrings(property.name); } } break; default: NOTIMPLEMENTED(); break; } } } void StaticIPParameters::Save( StoreInterface* storage, const string& storage_id) { for (size_t i = 0; i < arraysize(kProperties); ++i) { const Property& property = kProperties[i]; const string name(string(kConfigKeyPrefix) + property.name); bool property_exists = false; switch (property.type) { case Property::kTypeInt32: if (args_.ContainsInt(property.name)) { property_exists = true; storage->SetInt(storage_id, name, args_.GetInt(property.name)); } break; case Property::kTypeString: if (args_.ContainsString(property.name)) { property_exists = true; storage->SetString(storage_id, name, args_.GetString(property.name)); } break; case Property::kTypeStrings: if (args_.ContainsStrings(property.name)) { property_exists = true; // Name servers field is stored in storage as comma separated string. // Keep it as is to be backward compatible. storage->SetString( storage_id, name, base::JoinString(args_.GetStrings(property.name), ",")); } break; default: NOTIMPLEMENTED(); break; } if (!property_exists) { storage->DeleteKey(storage_id, name); } } } void StaticIPParameters::ApplyInt( const string& property, int32_t* value_out) { saved_args_.SetInt(property, *value_out); if (args_.ContainsInt(property)) { *value_out = args_.GetInt(property); } } void StaticIPParameters::ApplyString( const string& property, string* value_out) { saved_args_.SetString(property, *value_out); if (args_.ContainsString(property)) { *value_out = args_.GetString(property); } } void StaticIPParameters::ApplyStrings( const string& property, vector* value_out) { saved_args_.SetStrings(property, *value_out); if (args_.ContainsStrings(property)) { *value_out = args_.GetStrings(property); } } void StaticIPParameters::ApplyTo(IPConfig::Properties* props) { if (props->address_family == IPAddress::kFamilyUnknown) { // In situations where no address is supplied (bad or missing DHCP config) // supply an address family ourselves. // TODO(pstew): Guess from the address values. props->address_family = IPAddress::kFamilyIPv4; } ClearSavedParameters(); ApplyString(kAddressProperty, &props->address); ApplyString(kGatewayProperty, &props->gateway); ApplyInt(kMtuProperty, &props->mtu); ApplyStrings(kNameServersProperty, &props->dns_servers); ApplyString(kPeerAddressProperty, &props->peer_address); ApplyInt(kPrefixlenProperty, &props->subnet_prefix); } void StaticIPParameters::RestoreTo(IPConfig::Properties* props) { props->address = saved_args_.LookupString(kAddressProperty, ""); props->gateway = saved_args_.LookupString(kGatewayProperty, ""); props->mtu = saved_args_.LookupInt(kMtuProperty, 0); props->dns_servers.clear(); if (saved_args_.ContainsStrings(kNameServersProperty)) { props->dns_servers = saved_args_.GetStrings(kNameServersProperty); } props->peer_address = saved_args_.LookupString(kPeerAddressProperty, ""); props->subnet_prefix = saved_args_.LookupInt(kPrefixlenProperty, 0); ClearSavedParameters(); } void StaticIPParameters::ClearSavedParameters() { saved_args_.Clear(); } bool StaticIPParameters::ContainsAddress() const { return args_.ContainsString(kAddressProperty) && args_.ContainsInt(kPrefixlenProperty); } bool StaticIPParameters::ContainsNameServers() const { return args_.ContainsStrings(kNameServersProperty); } void StaticIPParameters::ClearMappedProperty( const size_t& index, Error* error) { CHECK(index < arraysize(kProperties)); const Property& property = kProperties[index]; switch (property.type) { case Property::kTypeInt32: if (args_.ContainsInt(property.name)) { args_.RemoveInt(property.name); } else { error->Populate(Error::kNotFound, "Property is not set"); } break; case Property::kTypeString: if (args_.ContainsString(property.name)) { args_.RemoveString(property.name); } else { error->Populate(Error::kNotFound, "Property is not set"); } break; case Property::kTypeStrings: if (args_.ContainsStrings(property.name)) { args_.RemoveStrings(property.name); } else { error->Populate(Error::kNotFound, "Property is not set"); } break; default: NOTIMPLEMENTED(); break; } } void StaticIPParameters::ClearMappedSavedProperty( const size_t& index, Error* error) { error->Populate(Error::kInvalidArguments, "Property is read-only"); } int32_t StaticIPParameters::GetMappedInt32Property( const size_t& index, Error* error) { CHECK(index < arraysize(kProperties)); const string& key = kProperties[index].name; if (!args_.ContainsInt(key)) { error->Populate(Error::kNotFound, "Property is not set"); return 0; } return args_.GetInt(key); } int32_t StaticIPParameters::GetMappedSavedInt32Property( const size_t& index, Error* error) { CHECK(index < arraysize(kProperties)); const string& key = kProperties[index].name; if (!saved_args_.ContainsInt(key)) { error->Populate(Error::kNotFound, "Property is not set"); return 0; } return saved_args_.GetInt(key); } string StaticIPParameters::GetMappedStringProperty( const size_t& index, Error* error) { CHECK(index < arraysize(kProperties)); const string& key = kProperties[index].name; if (!args_.ContainsString(key)) { error->Populate(Error::kNotFound, "Property is not set"); return string(); } return args_.GetString(key); } string StaticIPParameters::GetMappedSavedStringProperty( const size_t& index, Error* error) { CHECK(index < arraysize(kProperties)); const string& key = kProperties[index].name; if (!saved_args_.ContainsString(key)) { error->Populate(Error::kNotFound, "Property is not set"); return string(); } return saved_args_.GetString(key); } string StaticIPParameters::GetMappedStringsProperty( const size_t& index, Error* error) { CHECK(index < arraysize(kProperties)); const string& key = kProperties[index].name; if (!args_.ContainsStrings(key)) { error->Populate(Error::kNotFound, "Property is not set"); return string(); } return base::JoinString(args_.GetStrings(key), ","); } string StaticIPParameters::GetMappedSavedStringsProperty( const size_t& index, Error* error) { CHECK(index < arraysize(kProperties)); const string& key = kProperties[index].name; if (!saved_args_.ContainsStrings(key)) { error->Populate(Error::kNotFound, "Property is not set"); return string(); } return base::JoinString(saved_args_.GetStrings(key), ","); } bool StaticIPParameters::SetMappedInt32Property( const size_t& index, const int32_t& value, Error* error) { CHECK(index < arraysize(kProperties)); if (args_.ContainsInt(kProperties[index].name) && args_.GetInt(kProperties[index].name) == value) { return false; } args_.SetInt(kProperties[index].name, value); return true; } bool StaticIPParameters::SetMappedSavedInt32Property( const size_t& index, const int32_t& value, Error* error) { error->Populate(Error::kInvalidArguments, "Property is read-only"); return false; } bool StaticIPParameters::SetMappedStringProperty( const size_t& index, const string& value, Error* error) { CHECK(index < arraysize(kProperties)); if (args_.ContainsString(kProperties[index].name) && args_.GetString(kProperties[index].name) == value) { return false; } args_.SetString(kProperties[index].name, value); return true; } bool StaticIPParameters::SetMappedSavedStringProperty( const size_t& index, const string& value, Error* error) { error->Populate(Error::kInvalidArguments, "Property is read-only"); return false; } bool StaticIPParameters::SetMappedStringsProperty( const size_t& index, const string& value, Error* error) { CHECK(index < arraysize(kProperties)); vector string_list = base::SplitString( value, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); if (args_.ContainsStrings(kProperties[index].name) && args_.GetStrings(kProperties[index].name) == string_list) { return false; } args_.SetStrings(kProperties[index].name, string_list); return true; } bool StaticIPParameters::SetMappedSavedStringsProperty( const size_t& index, const string& value, Error* error) { error->Populate(Error::kInvalidArguments, "Property is read-only"); return false; } KeyValueStore StaticIPParameters::GetSavedIPConfig(Error* /*error*/) { return saved_args_; } KeyValueStore StaticIPParameters::GetStaticIPConfig(Error* /*error*/) { return args_; } bool StaticIPParameters::SetStaticIPConfig(const KeyValueStore& value, Error* /*error*/) { if (args_ == value) { return false; } args_ = value; return true; } } // namespace shill