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;
ObjectID(PPPDevice * p)33 static string ObjectID(PPPDevice* p) { return p->link_name(); }
34 }
35 
PPPDevice(ControlInterface * control,EventDispatcher * dispatcher,Metrics * metrics,Manager * manager,const string & link_name,int interface_index)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 
~PPPDevice()45 PPPDevice::~PPPDevice() {}
46 
UpdateIPConfigFromPPP(const map<string,string> & configuration,bool blackhole_ipv6)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 
UpdateIPConfigFromPPPWithMTU(const map<string,string> & configuration,bool blackhole_ipv6,int32_t mtu)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
AcquireIPv6Config()69 bool PPPDevice::AcquireIPv6Config() {
70   return AcquireIPv6ConfigWithLeaseName(string());
71 }
72 #endif
73 
74 // static
GetInterfaceName(const map<string,string> & configuration)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 
ParseIPConfiguration(const string & link_name,const map<string,string> & configuration)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