1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chromeos/network/network_util.h"
6
7#include "base/strings/string_tokenizer.h"
8#include "base/strings/string_util.h"
9#include "base/strings/stringprintf.h"
10#include "chromeos/network/network_state.h"
11#include "chromeos/network/network_state_handler.h"
12#include "chromeos/network/onc/onc_signature.h"
13#include "chromeos/network/onc/onc_translation_tables.h"
14#include "chromeos/network/onc/onc_translator.h"
15#include "third_party/cros_system_api/dbus/service_constants.h"
16
17namespace chromeos {
18
19WifiAccessPoint::WifiAccessPoint()
20    : signal_strength(0),
21      signal_to_noise(0),
22      channel(0) {
23}
24
25WifiAccessPoint::~WifiAccessPoint() {
26}
27
28CellularScanResult::CellularScanResult() {
29}
30
31CellularScanResult::~CellularScanResult() {
32}
33
34namespace network_util {
35
36std::string PrefixLengthToNetmask(int32 prefix_length) {
37  std::string netmask;
38  // Return the empty string for invalid inputs.
39  if (prefix_length < 0 || prefix_length > 32)
40    return netmask;
41  for (int i = 0; i < 4; i++) {
42    int remainder = 8;
43    if (prefix_length >= 8) {
44      prefix_length -= 8;
45    } else {
46      remainder = prefix_length;
47      prefix_length = 0;
48    }
49    if (i > 0)
50      netmask += ".";
51    int value = remainder == 0 ? 0 :
52        ((2L << (remainder - 1)) - 1) << (8 - remainder);
53    netmask += base::StringPrintf("%d", value);
54  }
55  return netmask;
56}
57
58int32 NetmaskToPrefixLength(const std::string& netmask) {
59  int count = 0;
60  int prefix_length = 0;
61  base::StringTokenizer t(netmask, ".");
62  while (t.GetNext()) {
63    // If there are more than 4 numbers, then it's invalid.
64    if (count == 4)
65      return -1;
66
67    std::string token = t.token();
68    // If we already found the last mask and the current one is not
69    // "0" then the netmask is invalid. For example, 255.224.255.0
70    if (prefix_length / 8 != count) {
71      if (token != "0")
72        return -1;
73    } else if (token == "255") {
74      prefix_length += 8;
75    } else if (token == "254") {
76      prefix_length += 7;
77    } else if (token == "252") {
78      prefix_length += 6;
79    } else if (token == "248") {
80      prefix_length += 5;
81    } else if (token == "240") {
82      prefix_length += 4;
83    } else if (token == "224") {
84      prefix_length += 3;
85    } else if (token == "192") {
86      prefix_length += 2;
87    } else if (token == "128") {
88      prefix_length += 1;
89    } else if (token == "0") {
90      prefix_length += 0;
91    } else {
92      // mask is not a valid number.
93      return -1;
94    }
95    count++;
96  }
97  if (count < 4)
98    return -1;
99  return prefix_length;
100}
101
102std::string FormattedMacAddress(const std::string& shill_mac_address) {
103  if (shill_mac_address.size() % 2 != 0)
104    return shill_mac_address;
105  std::string result;
106  for (size_t i = 0; i < shill_mac_address.size(); ++i) {
107    if ((i != 0) && (i % 2 == 0))
108      result.push_back(':');
109    result.push_back(base::ToUpperASCII(shill_mac_address[i]));
110  }
111  return result;
112}
113
114bool ParseCellularScanResults(const base::ListValue& list,
115                              std::vector<CellularScanResult>* scan_results) {
116  scan_results->clear();
117  scan_results->reserve(list.GetSize());
118  for (base::ListValue::const_iterator it = list.begin();
119       it != list.end(); ++it) {
120    if (!(*it)->IsType(base::Value::TYPE_DICTIONARY))
121      return false;
122    CellularScanResult scan_result;
123    const base::DictionaryValue* dict =
124        static_cast<const base::DictionaryValue*>(*it);
125    // If the network id property is not present then this network cannot be
126    // connected to so don't include it in the results.
127    if (!dict->GetStringWithoutPathExpansion(shill::kNetworkIdProperty,
128                                             &scan_result.network_id))
129      continue;
130    dict->GetStringWithoutPathExpansion(shill::kStatusProperty,
131                                        &scan_result.status);
132    dict->GetStringWithoutPathExpansion(shill::kLongNameProperty,
133                                        &scan_result.long_name);
134    dict->GetStringWithoutPathExpansion(shill::kShortNameProperty,
135                                        &scan_result.short_name);
136    dict->GetStringWithoutPathExpansion(shill::kTechnologyProperty,
137                                        &scan_result.technology);
138    scan_results->push_back(scan_result);
139  }
140  return true;
141}
142
143scoped_ptr<base::DictionaryValue> TranslateNetworkStateToONC(
144    const NetworkState* network) {
145  // Get the properties from the NetworkState.
146  base::DictionaryValue shill_dictionary;
147  network->GetStateProperties(&shill_dictionary);
148
149  scoped_ptr<base::DictionaryValue> onc_dictionary =
150      TranslateShillServiceToONCPart(shill_dictionary,
151                                     ::onc::ONC_SOURCE_UNKNOWN,
152                                     &onc::kNetworkWithStateSignature);
153  return onc_dictionary.Pass();
154}
155
156scoped_ptr<base::ListValue> TranslateNetworkListToONC(
157    NetworkTypePattern pattern,
158    bool configured_only,
159    bool visible_only,
160    int limit,
161    bool debugging_properties) {
162  NetworkStateHandler::NetworkStateList network_states;
163  NetworkHandler::Get()->network_state_handler()->GetNetworkListByType(
164      pattern, configured_only, visible_only, limit, &network_states);
165
166  scoped_ptr<base::ListValue> network_properties_list(new base::ListValue);
167  for (NetworkStateHandler::NetworkStateList::iterator it =
168           network_states.begin();
169       it != network_states.end();
170       ++it) {
171    scoped_ptr<base::DictionaryValue> onc_dictionary =
172        TranslateNetworkStateToONC(*it);
173
174    if (debugging_properties) {
175      onc_dictionary->SetBoolean("connectable", (*it)->connectable());
176      onc_dictionary->SetBoolean("visible", (*it)->visible());
177      onc_dictionary->SetString("profile_path", (*it)->profile_path());
178      onc_dictionary->SetString("service_path", (*it)->path());
179    }
180
181    network_properties_list->Append(onc_dictionary.release());
182  }
183  return network_properties_list.Pass();
184}
185
186std::string TranslateONCTypeToShill(const std::string& onc_type) {
187  if (onc_type == ::onc::network_type::kEthernet)
188    return shill::kTypeEthernet;
189  std::string shill_type;
190  onc::TranslateStringToShill(onc::kNetworkTypeTable, onc_type, &shill_type);
191  return shill_type;
192}
193
194}  // namespace network_util
195}  // namespace chromeos
196