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