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 
StaticIPParameters()55 StaticIPParameters::StaticIPParameters() {}
56 
~StaticIPParameters()57 StaticIPParameters::~StaticIPParameters() {}
58 
PlumbPropertyStore(PropertyStore * store)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 
Load(StoreInterface * storage,const string & storage_id)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 
Save(StoreInterface * storage,const string & storage_id)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 
ApplyInt(const string & property,int32_t * value_out)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 
ApplyString(const string & property,string * value_out)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 
ApplyStrings(const string & property,vector<string> * value_out)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 
ApplyTo(IPConfig::Properties * props)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 
RestoreTo(IPConfig::Properties * props)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 
ClearSavedParameters()290 void StaticIPParameters::ClearSavedParameters() {
291   saved_args_.Clear();
292 }
293 
ContainsAddress() const294 bool StaticIPParameters::ContainsAddress() const {
295   return args_.ContainsString(kAddressProperty) &&
296       args_.ContainsInt(kPrefixlenProperty);
297 }
298 
ContainsNameServers() const299 bool StaticIPParameters::ContainsNameServers() const {
300   return args_.ContainsStrings(kNameServersProperty);
301 }
302 
ClearMappedProperty(const size_t & index,Error * error)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 
ClearMappedSavedProperty(const size_t & index,Error * error)336 void StaticIPParameters::ClearMappedSavedProperty(
337     const size_t& index, Error* error) {
338   error->Populate(Error::kInvalidArguments, "Property is read-only");
339 }
340 
GetMappedInt32Property(const size_t & index,Error * error)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 
GetMappedSavedInt32Property(const size_t & index,Error * error)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 
GetMappedStringProperty(const size_t & index,Error * error)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 
GetMappedSavedStringProperty(const size_t & index,Error * error)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 
GetMappedStringsProperty(const size_t & index,Error * error)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 
GetMappedSavedStringsProperty(const size_t & index,Error * error)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 
SetMappedInt32Property(const size_t & index,const int32_t & value,Error * error)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 
SetMappedSavedInt32Property(const size_t & index,const int32_t & value,Error * error)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 
SetMappedStringProperty(const size_t & index,const string & value,Error * error)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 
SetMappedSavedStringProperty(const size_t & index,const string & value,Error * error)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 
SetMappedStringsProperty(const size_t & index,const string & value,Error * error)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 
SetMappedSavedStringsProperty(const size_t & index,const string & value,Error * error)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 
GetSavedIPConfig(Error *)468 KeyValueStore StaticIPParameters::GetSavedIPConfig(Error* /*error*/) {
469   return saved_args_;
470 }
471 
GetStaticIPConfig(Error *)472 KeyValueStore StaticIPParameters::GetStaticIPConfig(Error* /*error*/) {
473   return args_;
474 }
475 
SetStaticIPConfig(const KeyValueStore & value,Error *)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