blob: 80a1ba8f4f13434ff8a5c91faccff3172e06928a [file] [log] [blame]
Ben Chan26692bd2014-02-03 16:34:55 -08001// Copyright (c) 2014 The Chromium OS 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 "shill/cellular_bearer.h"
6
7#include <ModemManager/ModemManager.h>
8#include <base/bind.h>
9
10#include "shill/dbus_properties.h"
11#include "shill/dbus_properties_proxy.h"
12#include "shill/logging.h"
13#include "shill/proxy_factory.h"
14
15using std::string;
16using std::vector;
17
18namespace shill {
19
20namespace {
21
22const char kPropertyAddress[] = "address";
23const char kPropertyDNS1[] = "dns1";
24const char kPropertyDNS2[] = "dns2";
25const char kPropertyDNS3[] = "dns3";
26const char kPropertyGateway[] = "gateway";
27const char kPropertyMethod[] = "method";
28const char kPropertyPrefix[] = "prefix";
29
30IPConfig::Method ConvertMMBearerIPConfigMethod(uint32 method) {
31 switch (method) {
32 case MM_BEARER_IP_METHOD_PPP:
33 return IPConfig::kMethodPPP;
34 case MM_BEARER_IP_METHOD_STATIC:
35 return IPConfig::kMethodStatic;
36 case MM_BEARER_IP_METHOD_DHCP:
37 return IPConfig::kMethodDHCP;
38 default:
39 return IPConfig::kMethodUnknown;
40 }
41}
42
43} // namespace
44
45CellularBearer::CellularBearer(ProxyFactory *proxy_factory,
46 const string &dbus_path,
47 const string &dbus_service)
48 : proxy_factory_(proxy_factory),
49 dbus_path_(dbus_path),
50 dbus_service_(dbus_service),
51 connected_(false),
52 ipv4_config_method_(IPConfig::kMethodUnknown),
53 ipv6_config_method_(IPConfig::kMethodUnknown) {
54 CHECK(proxy_factory_);
55}
56
57CellularBearer::~CellularBearer() {}
58
59bool CellularBearer::Init() {
60 SLOG(Cellular, 3) << __func__ << ": path='" << dbus_path_
61 << "', service='" << dbus_service_ << "'";
62
63 dbus_properties_proxy_.reset(
64 proxy_factory_->CreateDBusPropertiesProxy(dbus_path_, dbus_service_));
65 // It is possible that ProxyFactory::CreateDBusPropertiesProxy() returns NULL
66 // as the bearer DBus object may no longer exist.
67 if (!dbus_properties_proxy_) {
68 LOG(WARNING) << "Failed to create DBus properties proxy for bearer '"
69 << dbus_path_ << "'. Bearer is likely gone.";
70 return false;
71 }
72
73 dbus_properties_proxy_->set_properties_changed_callback(base::Bind(
74 &CellularBearer::OnDBusPropertiesChanged, base::Unretained(this)));
75 UpdateProperties();
76 return true;
77}
78
79void CellularBearer::GetIPConfigMethodAndProperties(
80 const DBusPropertiesMap &properties,
81 IPAddress::Family address_family,
82 IPConfig::Method *ipconfig_method,
83 scoped_ptr<IPConfig::Properties> *ipconfig_properties) const {
84 DCHECK(ipconfig_method);
85 DCHECK(ipconfig_properties);
86
87 uint32 method;
88 if (!DBusProperties::GetUint32(properties, kPropertyMethod, &method)) {
89 SLOG(Cellular, 2) << "Bearer '" << dbus_path_
90 << "' does not specify an IP configuration method.";
91 method = MM_BEARER_IP_METHOD_UNKNOWN;
92 }
93 *ipconfig_method = ConvertMMBearerIPConfigMethod(method);
94 ipconfig_properties->reset();
95
96 if (*ipconfig_method != IPConfig::kMethodStatic)
97 return;
98
99 string address, gateway;
100 if (!DBusProperties::GetString(properties, kPropertyAddress, &address) ||
101 !DBusProperties::GetString(properties, kPropertyGateway, &gateway)) {
102 SLOG(Cellular, 2) << "Bearer '" << dbus_path_
103 << "' static IP configuration does not specify valid "
104 "address/gateway information.";
105 *ipconfig_method = IPConfig::kMethodUnknown;
106 return;
107 }
108
109 ipconfig_properties->reset(new IPConfig::Properties);
110 (*ipconfig_properties)->address_family = address_family;
111 (*ipconfig_properties)->address = address;
112 (*ipconfig_properties)->gateway = gateway;
113
114 uint32 prefix;
115 if (!DBusProperties::GetUint32(properties, kPropertyPrefix, &prefix)) {
116 prefix = IPAddress::GetMaxPrefixLength(address_family);
117 }
118 (*ipconfig_properties)->subnet_prefix = prefix;
119
120 string dns;
121 if (DBusProperties::GetString(properties, kPropertyDNS1, &dns)) {
122 (*ipconfig_properties)->dns_servers.push_back(dns);
123 }
124 if (DBusProperties::GetString(properties, kPropertyDNS2, &dns)) {
125 (*ipconfig_properties)->dns_servers.push_back(dns);
126 }
127 if (DBusProperties::GetString(properties, kPropertyDNS3, &dns)) {
128 (*ipconfig_properties)->dns_servers.push_back(dns);
129 }
130}
131
132void CellularBearer::ResetProperties() {
133 connected_ = false;
134 data_interface_.clear();
135 ipv4_config_method_ = IPConfig::kMethodUnknown;
136 ipv4_config_properties_.reset();
137 ipv6_config_method_ = IPConfig::kMethodUnknown;
138 ipv6_config_properties_.reset();
139}
140
141void CellularBearer::UpdateProperties() {
142 ResetProperties();
143
144 if (!dbus_properties_proxy_)
145 return;
146
147 DBusPropertiesMap properties =
148 dbus_properties_proxy_->GetAll(MM_DBUS_INTERFACE_BEARER);
149 if (properties.empty()) {
150 LOG(WARNING) << "Could not get properties of bearer '" << dbus_path_
151 << "'. Bearer is likely gone and thus ignored.";
152 return;
153 }
154
155 OnDBusPropertiesChanged(MM_DBUS_INTERFACE_BEARER, properties,
156 vector<string>());
157}
158
159void CellularBearer::OnDBusPropertiesChanged(
160 const string &interface,
161 const DBusPropertiesMap &changed_properties,
162 const vector<string> &/*invalidated_properties*/) {
163 SLOG(Cellular, 3) << __func__ << ": path=" << dbus_path_
164 << ", interface=" << interface;
165
166 if (interface != MM_DBUS_INTERFACE_BEARER)
167 return;
168
169 bool connected;
170 if (DBusProperties::GetBool(
171 changed_properties, MM_BEARER_PROPERTY_CONNECTED, &connected)) {
172 connected_ = connected;
173 }
174
175 string data_interface;
176 if (DBusProperties::GetString(
177 changed_properties, MM_BEARER_PROPERTY_INTERFACE, &data_interface)) {
178 data_interface_ = data_interface;
179 }
180
181 DBusPropertiesMap ipconfig;
182 if (DBusProperties::GetDBusPropertiesMap(
183 changed_properties, MM_BEARER_PROPERTY_IP4CONFIG, &ipconfig)) {
184 GetIPConfigMethodAndProperties(ipconfig,
185 IPAddress::kFamilyIPv4,
186 &ipv4_config_method_,
187 &ipv4_config_properties_);
188 }
189 if (DBusProperties::GetDBusPropertiesMap(
190 changed_properties, MM_BEARER_PROPERTY_IP6CONFIG, &ipconfig)) {
191 GetIPConfigMethodAndProperties(ipconfig,
192 IPAddress::kFamilyIPv6,
193 &ipv6_config_method_,
194 &ipv6_config_properties_);
195 }
196}
197
198} // namespace shill