1 // 2 // Copyright (C) 2012 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #include "shill/static_ip_parameters.h" 18 19 #include <string.h> 20 21 #include <base/strings/string_split.h> 22 #include <base/strings/string_util.h> 23 #if defined(__ANDROID__) 24 #include <dbus/service_constants.h> 25 #else 26 #include <chromeos/dbus/service_constants.h> 27 #endif // __ANDROID__ 28 29 #include "shill/error.h" 30 #include "shill/logging.h" 31 #include "shill/net/ip_address.h" 32 #include "shill/property_accessor.h" 33 #include "shill/property_store.h" 34 #include "shill/store_interface.h" 35 36 using std::string; 37 using std::vector; 38 39 namespace shill { 40 41 // static 42 const char StaticIPParameters::kConfigKeyPrefix[] = "StaticIP."; 43 // static 44 const char StaticIPParameters::kSavedConfigKeyPrefix[] = "SavedIP."; 45 // static 46 const StaticIPParameters::Property StaticIPParameters::kProperties[] = { 47 { kAddressProperty, Property::kTypeString }, 48 { kGatewayProperty, Property::kTypeString }, 49 { kMtuProperty, Property::kTypeInt32 }, 50 { kNameServersProperty, Property::kTypeStrings }, 51 { kPeerAddressProperty, Property::kTypeString }, 52 { kPrefixlenProperty, Property::kTypeInt32 } 53 }; 54 55 StaticIPParameters::StaticIPParameters() {} 56 57 StaticIPParameters::~StaticIPParameters() {} 58 59 void StaticIPParameters::PlumbPropertyStore(PropertyStore* store) { 60 // These individual fields will be deprecated once Chrome starts using 61 // the KeyValueStore dict directly. 62 for (size_t i = 0; i < arraysize(kProperties); ++i) { 63 const Property& property = kProperties[i]; 64 const string name(string(kConfigKeyPrefix) + property.name); 65 const string saved_name(string(kSavedConfigKeyPrefix) + property.name); 66 switch (property.type) { 67 case Property::kTypeInt32: 68 store->RegisterDerivedInt32( 69 name, 70 Int32Accessor( 71 new CustomMappedAccessor<StaticIPParameters, int32_t, size_t>( 72 this, 73 &StaticIPParameters::ClearMappedProperty, 74 &StaticIPParameters::GetMappedInt32Property, 75 &StaticIPParameters::SetMappedInt32Property, 76 i))); 77 store->RegisterDerivedInt32( 78 saved_name, 79 Int32Accessor( 80 new CustomMappedAccessor<StaticIPParameters, int32_t, size_t>( 81 this, 82 &StaticIPParameters::ClearMappedSavedProperty, 83 &StaticIPParameters::GetMappedSavedInt32Property, 84 &StaticIPParameters::SetMappedSavedInt32Property, 85 i))); 86 break; 87 case Property::kTypeString: 88 store->RegisterDerivedString( 89 name, 90 StringAccessor( 91 new CustomMappedAccessor<StaticIPParameters, string, size_t>( 92 this, 93 &StaticIPParameters::ClearMappedProperty, 94 &StaticIPParameters::GetMappedStringProperty, 95 &StaticIPParameters::SetMappedStringProperty, 96 i))); 97 store->RegisterDerivedString( 98 saved_name, 99 StringAccessor( 100 new CustomMappedAccessor<StaticIPParameters, string, size_t>( 101 this, 102 &StaticIPParameters::ClearMappedSavedProperty, 103 &StaticIPParameters::GetMappedSavedStringProperty, 104 &StaticIPParameters::SetMappedSavedStringProperty, 105 i))); 106 break; 107 case Property::kTypeStrings: 108 // Since Chrome is still using string for the nameservers, the 109 // registered function will convert the string from/to string vector 110 // stored in the KeyValueStore. 111 store->RegisterDerivedString( 112 name, 113 StringAccessor( 114 new CustomMappedAccessor<StaticIPParameters, string, size_t>( 115 this, 116 &StaticIPParameters::ClearMappedProperty, 117 &StaticIPParameters::GetMappedStringsProperty, 118 &StaticIPParameters::SetMappedStringsProperty, 119 i))); 120 store->RegisterDerivedString( 121 saved_name, 122 StringAccessor( 123 new CustomMappedAccessor<StaticIPParameters, string, size_t>( 124 this, 125 &StaticIPParameters::ClearMappedSavedProperty, 126 &StaticIPParameters::GetMappedSavedStringsProperty, 127 &StaticIPParameters::SetMappedSavedStringsProperty, 128 i))); 129 break; 130 default: 131 NOTIMPLEMENTED(); 132 break; 133 } 134 } 135 136 // Register KeyValueStore for both static ip and saved ip parameters. 137 store->RegisterDerivedKeyValueStore( 138 kSavedIPConfigProperty, 139 KeyValueStoreAccessor( 140 new CustomAccessor<StaticIPParameters, KeyValueStore>( 141 this, &StaticIPParameters::GetSavedIPConfig, nullptr))); 142 store->RegisterDerivedKeyValueStore( 143 kStaticIPConfigProperty, 144 KeyValueStoreAccessor( 145 new CustomAccessor<StaticIPParameters, KeyValueStore>( 146 this, &StaticIPParameters::GetStaticIPConfig, 147 &StaticIPParameters::SetStaticIPConfig))); 148 } 149 150 void StaticIPParameters::Load( 151 StoreInterface* storage, const string& storage_id) { 152 for (size_t i = 0; i < arraysize(kProperties); ++i) { 153 const Property& property = kProperties[i]; 154 const string name(string(kConfigKeyPrefix) + property.name); 155 switch (property.type) { 156 case Property::kTypeInt32: 157 { 158 int32_t value; 159 if (storage->GetInt(storage_id, name, &value)) { 160 args_.SetInt(property.name, value); 161 } else { 162 args_.RemoveInt(property.name); 163 } 164 } 165 break; 166 case Property::kTypeString: 167 { 168 string value; 169 if (storage->GetString(storage_id, name, &value)) { 170 args_.SetString(property.name, value); 171 } else { 172 args_.RemoveString(property.name); 173 } 174 } 175 break; 176 case Property::kTypeStrings: 177 { 178 // Name servers field is stored in storage as comma separated string. 179 // Keep it as is to be backward compatible. 180 string value; 181 if (storage->GetString(storage_id, name, &value)) { 182 vector<string> string_list = base::SplitString( 183 value, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); 184 args_.SetStrings(property.name, string_list); 185 } else { 186 args_.RemoveStrings(property.name); 187 } 188 } 189 break; 190 default: 191 NOTIMPLEMENTED(); 192 break; 193 } 194 } 195 } 196 197 void StaticIPParameters::Save( 198 StoreInterface* storage, const string& storage_id) { 199 for (size_t i = 0; i < arraysize(kProperties); ++i) { 200 const Property& property = kProperties[i]; 201 const string name(string(kConfigKeyPrefix) + property.name); 202 bool property_exists = false; 203 switch (property.type) { 204 case Property::kTypeInt32: 205 if (args_.ContainsInt(property.name)) { 206 property_exists = true; 207 storage->SetInt(storage_id, name, args_.GetInt(property.name)); 208 } 209 break; 210 case Property::kTypeString: 211 if (args_.ContainsString(property.name)) { 212 property_exists = true; 213 storage->SetString(storage_id, name, args_.GetString(property.name)); 214 } 215 break; 216 case Property::kTypeStrings: 217 if (args_.ContainsStrings(property.name)) { 218 property_exists = true; 219 // Name servers field is stored in storage as comma separated string. 220 // Keep it as is to be backward compatible. 221 storage->SetString( 222 storage_id, name, 223 base::JoinString(args_.GetStrings(property.name), ",")); 224 } 225 break; 226 default: 227 NOTIMPLEMENTED(); 228 break; 229 } 230 if (!property_exists) { 231 storage->DeleteKey(storage_id, name); 232 } 233 } 234 } 235 236 void StaticIPParameters::ApplyInt( 237 const string& property, int32_t* value_out) { 238 saved_args_.SetInt(property, *value_out); 239 if (args_.ContainsInt(property)) { 240 *value_out = args_.GetInt(property); 241 } 242 } 243 244 void StaticIPParameters::ApplyString( 245 const string& property, string* value_out) { 246 saved_args_.SetString(property, *value_out); 247 if (args_.ContainsString(property)) { 248 *value_out = args_.GetString(property); 249 } 250 } 251 252 void StaticIPParameters::ApplyStrings( 253 const string& property, vector<string>* value_out) { 254 saved_args_.SetStrings(property, *value_out); 255 if (args_.ContainsStrings(property)) { 256 *value_out = args_.GetStrings(property); 257 } 258 } 259 260 261 void StaticIPParameters::ApplyTo(IPConfig::Properties* props) { 262 if (props->address_family == IPAddress::kFamilyUnknown) { 263 // In situations where no address is supplied (bad or missing DHCP config) 264 // supply an address family ourselves. 265 // TODO(pstew): Guess from the address values. 266 props->address_family = IPAddress::kFamilyIPv4; 267 } 268 ClearSavedParameters(); 269 ApplyString(kAddressProperty, &props->address); 270 ApplyString(kGatewayProperty, &props->gateway); 271 ApplyInt(kMtuProperty, &props->mtu); 272 ApplyStrings(kNameServersProperty, &props->dns_servers); 273 ApplyString(kPeerAddressProperty, &props->peer_address); 274 ApplyInt(kPrefixlenProperty, &props->subnet_prefix); 275 } 276 277 void StaticIPParameters::RestoreTo(IPConfig::Properties* props) { 278 props->address = saved_args_.LookupString(kAddressProperty, ""); 279 props->gateway = saved_args_.LookupString(kGatewayProperty, ""); 280 props->mtu = saved_args_.LookupInt(kMtuProperty, 0); 281 props->dns_servers.clear(); 282 if (saved_args_.ContainsStrings(kNameServersProperty)) { 283 props->dns_servers = saved_args_.GetStrings(kNameServersProperty); 284 } 285 props->peer_address = saved_args_.LookupString(kPeerAddressProperty, ""); 286 props->subnet_prefix = saved_args_.LookupInt(kPrefixlenProperty, 0); 287 ClearSavedParameters(); 288 } 289 290 void StaticIPParameters::ClearSavedParameters() { 291 saved_args_.Clear(); 292 } 293 294 bool StaticIPParameters::ContainsAddress() const { 295 return args_.ContainsString(kAddressProperty) && 296 args_.ContainsInt(kPrefixlenProperty); 297 } 298 299 bool StaticIPParameters::ContainsNameServers() const { 300 return args_.ContainsStrings(kNameServersProperty); 301 } 302 303 void StaticIPParameters::ClearMappedProperty( 304 const size_t& index, Error* error) { 305 CHECK(index < arraysize(kProperties)); 306 307 const Property& property = kProperties[index]; 308 switch (property.type) { 309 case Property::kTypeInt32: 310 if (args_.ContainsInt(property.name)) { 311 args_.RemoveInt(property.name); 312 } else { 313 error->Populate(Error::kNotFound, "Property is not set"); 314 } 315 break; 316 case Property::kTypeString: 317 if (args_.ContainsString(property.name)) { 318 args_.RemoveString(property.name); 319 } else { 320 error->Populate(Error::kNotFound, "Property is not set"); 321 } 322 break; 323 case Property::kTypeStrings: 324 if (args_.ContainsStrings(property.name)) { 325 args_.RemoveStrings(property.name); 326 } else { 327 error->Populate(Error::kNotFound, "Property is not set"); 328 } 329 break; 330 default: 331 NOTIMPLEMENTED(); 332 break; 333 } 334 } 335 336 void StaticIPParameters::ClearMappedSavedProperty( 337 const size_t& index, Error* error) { 338 error->Populate(Error::kInvalidArguments, "Property is read-only"); 339 } 340 341 int32_t StaticIPParameters::GetMappedInt32Property( 342 const size_t& index, Error* error) { 343 CHECK(index < arraysize(kProperties)); 344 345 const string& key = kProperties[index].name; 346 if (!args_.ContainsInt(key)) { 347 error->Populate(Error::kNotFound, "Property is not set"); 348 return 0; 349 } 350 return args_.GetInt(key); 351 } 352 353 int32_t StaticIPParameters::GetMappedSavedInt32Property( 354 const size_t& index, Error* error) { 355 CHECK(index < arraysize(kProperties)); 356 357 const string& key = kProperties[index].name; 358 if (!saved_args_.ContainsInt(key)) { 359 error->Populate(Error::kNotFound, "Property is not set"); 360 return 0; 361 } 362 return saved_args_.GetInt(key); 363 } 364 365 string StaticIPParameters::GetMappedStringProperty( 366 const size_t& index, Error* error) { 367 CHECK(index < arraysize(kProperties)); 368 369 const string& key = kProperties[index].name; 370 if (!args_.ContainsString(key)) { 371 error->Populate(Error::kNotFound, "Property is not set"); 372 return string(); 373 } 374 return args_.GetString(key); 375 } 376 377 string StaticIPParameters::GetMappedSavedStringProperty( 378 const size_t& index, Error* error) { 379 CHECK(index < arraysize(kProperties)); 380 381 const string& key = kProperties[index].name; 382 if (!saved_args_.ContainsString(key)) { 383 error->Populate(Error::kNotFound, "Property is not set"); 384 return string(); 385 } 386 return saved_args_.GetString(key); 387 } 388 389 string StaticIPParameters::GetMappedStringsProperty( 390 const size_t& index, Error* error) { 391 CHECK(index < arraysize(kProperties)); 392 393 const string& key = kProperties[index].name; 394 if (!args_.ContainsStrings(key)) { 395 error->Populate(Error::kNotFound, "Property is not set"); 396 return string(); 397 } 398 return base::JoinString(args_.GetStrings(key), ","); 399 } 400 401 string StaticIPParameters::GetMappedSavedStringsProperty( 402 const size_t& index, Error* error) { 403 CHECK(index < arraysize(kProperties)); 404 405 const string& key = kProperties[index].name; 406 if (!saved_args_.ContainsStrings(key)) { 407 error->Populate(Error::kNotFound, "Property is not set"); 408 return string(); 409 } 410 return base::JoinString(saved_args_.GetStrings(key), ","); 411 } 412 413 bool StaticIPParameters::SetMappedInt32Property( 414 const size_t& index, const int32_t& value, Error* error) { 415 CHECK(index < arraysize(kProperties)); 416 if (args_.ContainsInt(kProperties[index].name) && 417 args_.GetInt(kProperties[index].name) == value) { 418 return false; 419 } 420 args_.SetInt(kProperties[index].name, value); 421 return true; 422 } 423 424 bool StaticIPParameters::SetMappedSavedInt32Property( 425 const size_t& index, const int32_t& value, Error* error) { 426 error->Populate(Error::kInvalidArguments, "Property is read-only"); 427 return false; 428 } 429 430 bool StaticIPParameters::SetMappedStringProperty( 431 const size_t& index, const string& value, Error* error) { 432 CHECK(index < arraysize(kProperties)); 433 if (args_.ContainsString(kProperties[index].name) && 434 args_.GetString(kProperties[index].name) == value) { 435 return false; 436 } 437 args_.SetString(kProperties[index].name, value); 438 return true; 439 } 440 441 bool StaticIPParameters::SetMappedSavedStringProperty( 442 const size_t& index, const string& value, Error* error) { 443 error->Populate(Error::kInvalidArguments, "Property is read-only"); 444 return false; 445 } 446 447 bool StaticIPParameters::SetMappedStringsProperty( 448 const size_t& index, const string& value, Error* error) { 449 CHECK(index < arraysize(kProperties)); 450 451 vector<string> string_list = base::SplitString( 452 value, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); 453 if (args_.ContainsStrings(kProperties[index].name) && 454 args_.GetStrings(kProperties[index].name) == string_list) { 455 return false; 456 } 457 458 args_.SetStrings(kProperties[index].name, string_list); 459 return true; 460 } 461 462 bool StaticIPParameters::SetMappedSavedStringsProperty( 463 const size_t& index, const string& value, Error* error) { 464 error->Populate(Error::kInvalidArguments, "Property is read-only"); 465 return false; 466 } 467 468 KeyValueStore StaticIPParameters::GetSavedIPConfig(Error* /*error*/) { 469 return saved_args_; 470 } 471 472 KeyValueStore StaticIPParameters::GetStaticIPConfig(Error* /*error*/) { 473 return args_; 474 } 475 476 bool StaticIPParameters::SetStaticIPConfig(const KeyValueStore& value, 477 Error* /*error*/) { 478 if (args_ == value) { 479 return false; 480 } 481 args_ = value; 482 return true; 483 } 484 485 } // namespace shill 486