Home | History | Annotate | Download | only in shill
      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