Home | History | Annotate | Download | only in shill
      1 //
      2 // Copyright (C) 2013 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/ppp_device.h"
     18 
     19 #include <base/stl_util.h>
     20 #include <base/strings/string_number_conversions.h>
     21 
     22 #include "shill/logging.h"
     23 #include "shill/metrics.h"
     24 #include "shill/technology.h"
     25 
     26 using std::map;
     27 using std::string;
     28 
     29 namespace shill {
     30 
     31 namespace Logging {
     32 static auto kModuleLogScope = ScopeLogger::kPPP;
     33 static string ObjectID(PPPDevice* p) { return p->link_name(); }
     34 }
     35 
     36 PPPDevice::PPPDevice(ControlInterface* control,
     37                      EventDispatcher* dispatcher,
     38                      Metrics* metrics,
     39                      Manager* manager,
     40                      const string& link_name,
     41                      int interface_index)
     42     : VirtualDevice(control, dispatcher, metrics, manager, link_name,
     43                     interface_index, Technology::kPPP) {}
     44 
     45 PPPDevice::~PPPDevice() {}
     46 
     47 void PPPDevice::UpdateIPConfigFromPPP(const map<string, string>& configuration,
     48                                       bool blackhole_ipv6) {
     49   SLOG(this, 2) << __func__ << " on " << link_name();
     50   IPConfig::Properties properties =
     51       ParseIPConfiguration(link_name(), configuration);
     52   properties.blackhole_ipv6 = blackhole_ipv6;
     53   UpdateIPConfig(properties);
     54 }
     55 
     56 void PPPDevice::UpdateIPConfigFromPPPWithMTU(
     57     const map<string, string>& configuration,
     58     bool blackhole_ipv6,
     59     int32_t mtu) {
     60   SLOG(this, 2) << __func__ << " on " << link_name();
     61   IPConfig::Properties properties =
     62       ParseIPConfiguration(link_name(), configuration);
     63   properties.blackhole_ipv6 = blackhole_ipv6;
     64   properties.mtu = mtu;
     65   UpdateIPConfig(properties);
     66 }
     67 
     68 #ifndef DISABLE_DHCPV6
     69 bool PPPDevice::AcquireIPv6Config() {
     70   return AcquireIPv6ConfigWithLeaseName(string());
     71 }
     72 #endif
     73 
     74 // static
     75 string PPPDevice::GetInterfaceName(const map<string, string>& configuration) {
     76   if (ContainsKey(configuration, kPPPInterfaceName)) {
     77     return configuration.find(kPPPInterfaceName)->second;
     78   }
     79   return string();
     80 }
     81 
     82 IPConfig::Properties PPPDevice::ParseIPConfiguration(
     83     const string& link_name, const map<string, string>& configuration) {
     84   SLOG(PPP, nullptr, 2) << __func__ << " on " << link_name;
     85   IPConfig::Properties properties;
     86   properties.address_family = IPAddress::kFamilyIPv4;
     87   properties.subnet_prefix = IPAddress::GetMaxPrefixLength(
     88       properties.address_family);
     89   for (const auto& it : configuration)  {
     90     const string& key = it.first;
     91     const string& value = it.second;
     92     SLOG(PPP, nullptr, 2) << "Processing: " << key << " -> " << value;
     93     if (key == kPPPInternalIP4Address) {
     94       properties.address = value;
     95     } else if (key == kPPPExternalIP4Address) {
     96       properties.peer_address = value;
     97     } else if (key == kPPPGatewayAddress) {
     98       properties.gateway = value;
     99     } else if (key == kPPPDNS1) {
    100       properties.dns_servers.insert(properties.dns_servers.begin(), value);
    101     } else if (key == kPPPDNS2) {
    102       properties.dns_servers.push_back(value);
    103     } else if (key == kPPPLNSAddress) {
    104       // This is really a L2TPIPSec property. But it's sent to us by
    105       // our PPP plugin.
    106       size_t prefix = IPAddress::GetMaxPrefixLength(properties.address_family);
    107       properties.exclusion_list.push_back(value + "/" +
    108                                           base::SizeTToString(prefix));
    109     } else if (key == kPPPMRU) {
    110       int mru;
    111       if (!base::StringToInt(value, &mru)) {
    112         LOG(WARNING) << "Failed to parse MRU: " << value;
    113         continue;
    114       }
    115       properties.mtu = mru;
    116       metrics()->SendSparseToUMA(Metrics::kMetricPPPMTUValue, mru);
    117     } else {
    118       SLOG(PPP, nullptr, 2) << "Key ignored.";
    119     }
    120   }
    121   if (properties.gateway.empty()) {
    122     // The gateway may be unspecified, since this is a point-to-point
    123     // link. Set to the peer's address, so that Connection can set the
    124     // routing table.
    125     properties.gateway = properties.peer_address;
    126   }
    127   return properties;
    128 }
    129 
    130 }  // namespace shill
    131