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