1 //
2 // Copyright (C) 2012 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 // pppd.h, which is required by lcp.h, is not C++ compatible.  The following
18 // contortions are required before including anything else to ensure that we
19 // control the definition of bool before stdbool get indirectly included so that
20 // we can redefine it.
21 
22 #include <sys/types.h>
23 
24 extern "C" {
25 #include <pppd/fsm.h>
26 #include <pppd/ipcp.h>
27 
28 #define class class_num
29 #define bool pppd_bool_t
30 #include <pppd/pppd.h>
31 #undef bool
32 #undef class
33 #undef STOPPED
34 #include <pppd/lcp.h>
35 }
36 
37 #include "shill/shims/ppp.h"
38 
39 #include <arpa/inet.h>
40 #include <netinet/in.h>
41 
42 #include <map>
43 
44 #include <base/command_line.h>
45 #include <base/logging.h>
46 #include <base/strings/string_number_conversions.h>
47 #include <brillo/syslog_logging.h>
48 
49 #include "shill/ppp_device.h"
50 #include "shill/rpc_task.h"
51 #include "shill/shims/environment.h"
52 #include "shill/shims/task_proxy.h"
53 
54 using std::map;
55 using std::string;
56 
57 namespace shill {
58 
59 namespace shims {
60 
61 static base::LazyInstance<PPP> g_ppp = LAZY_INSTANCE_INITIALIZER;
62 
PPP()63 PPP::PPP() : running_(false) {}
64 
~PPP()65 PPP::~PPP() {}
66 
67 // static
GetInstance()68 PPP* PPP::GetInstance() {
69   return g_ppp.Pointer();
70 }
71 
Init()72 void PPP::Init() {
73   if (running_) {
74     return;
75   }
76   running_ = true;
77   base::CommandLine::Init(0, NULL);
78   brillo::InitLog(brillo::kLogToSyslog | brillo::kLogHeader);
79   LOG(INFO) << "PPP started.";
80 }
81 
GetSecret(string * username,string * password)82 bool PPP::GetSecret(string* username, string* password) {
83   LOG(INFO) << __func__;
84   if (!CreateProxy()) {
85     return false;
86   }
87   bool success = proxy_->GetSecret(username, password);
88   DestroyProxy();
89   return success;
90 }
91 
OnAuthenticateStart()92 void PPP::OnAuthenticateStart() {
93   LOG(INFO) << __func__;
94   if (CreateProxy()) {
95     map<string, string> details;
96     proxy_->Notify(kPPPReasonAuthenticating, details);
97     DestroyProxy();
98   }
99 }
100 
OnAuthenticateDone()101 void PPP::OnAuthenticateDone() {
102   LOG(INFO) << __func__;
103   if (CreateProxy()) {
104     map<string, string> details;
105     proxy_->Notify(kPPPReasonAuthenticated, details);
106     DestroyProxy();
107   }
108 }
109 
OnConnect(const string & ifname)110 void PPP::OnConnect(const string& ifname) {
111   LOG(INFO) << __func__ << "(" << ifname << ")";
112   if (!ipcp_gotoptions[0].ouraddr) {
113     LOG(ERROR) << "ouraddr not set.";
114     return;
115   }
116   map<string, string> dict;
117   dict[kPPPInterfaceName] = ifname;
118   dict[kPPPInternalIP4Address] = ConvertIPToText(&ipcp_gotoptions[0].ouraddr);
119   dict[kPPPExternalIP4Address] = ConvertIPToText(&ipcp_hisoptions[0].hisaddr);
120   if (ipcp_gotoptions[0].default_route) {
121     dict[kPPPGatewayAddress] = dict[kPPPExternalIP4Address];
122   }
123   if (ipcp_gotoptions[0].dnsaddr[0]) {
124     dict[kPPPDNS1] = ConvertIPToText(&ipcp_gotoptions[0].dnsaddr[0]);
125   }
126   if (ipcp_gotoptions[0].dnsaddr[1]) {
127     dict[kPPPDNS2] = ConvertIPToText(&ipcp_gotoptions[0].dnsaddr[1]);
128   }
129   if (lcp_gotoptions[0].mru) {
130     dict[kPPPMRU] = base::IntToString(lcp_gotoptions[0].mru);
131   }
132   string lns_address;
133   if (Environment::GetInstance()->GetVariable("LNS_ADDRESS", &lns_address)) {
134     // Really an L2TP/IPSec option rather than a PPP one. But oh well.
135     dict[kPPPLNSAddress] = lns_address;
136   }
137   if (CreateProxy()) {
138     proxy_->Notify(kPPPReasonConnect, dict);
139     DestroyProxy();
140   }
141 }
142 
OnDisconnect()143 void PPP::OnDisconnect() {
144   LOG(INFO) << __func__;
145   if (CreateProxy()) {
146     map<string, string> dict;
147     proxy_->Notify(kPPPReasonDisconnect, dict);
148     DestroyProxy();
149   }
150 }
151 
CreateProxy()152 bool PPP::CreateProxy() {
153   Environment* environment = Environment::GetInstance();
154   string service, path;
155   if (!environment->GetVariable(kRPCTaskServiceVariable, &service) ||
156       !environment->GetVariable(kRPCTaskPathVariable, &path)) {
157     LOG(ERROR) << "Environment variables not available.";
158     return false;
159   }
160 
161   dbus::Bus::Options options;
162   options.bus_type = dbus::Bus::SYSTEM;
163   bus_ = new dbus::Bus(options);
164   CHECK(bus_->Connect());
165 
166   proxy_.reset(new TaskProxy(bus_, path, service));
167 
168   LOG(INFO) << "Task proxy created: " << service << " - " << path;
169   return true;
170 }
171 
DestroyProxy()172 void PPP::DestroyProxy() {
173   proxy_.reset();
174   if (bus_) {
175     bus_->ShutdownAndBlock();
176   }
177   LOG(INFO) << "Task proxy destroyed.";
178 }
179 
180 // static
ConvertIPToText(const void * addr)181 string PPP::ConvertIPToText(const void* addr) {
182   char text[INET_ADDRSTRLEN];
183   inet_ntop(AF_INET, addr, text, INET_ADDRSTRLEN);
184   return text;
185 }
186 
187 }  // namespace shims
188 
189 }  // namespace shill
190