| // Copyright 2018 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // pppd.h, which is required by lcp.h, is not C++ compatible. The following |
| // contortions are required before including anything else to ensure that we |
| // control the definition of bool before stdbool get indirectly included so that |
| // we can redefine it. |
| |
| #include <sys/types.h> |
| |
| extern "C" { |
| #include <pppd/fsm.h> |
| #include <pppd/ipcp.h> |
| |
| #define class class_num |
| #define bool pppd_bool_t |
| #include <pppd/pppd.h> |
| #undef bool |
| #undef class |
| #undef STOPPED |
| #include <pppd/lcp.h> |
| } |
| |
| #include "shill/shims/ppp.h" |
| |
| #include <arpa/inet.h> |
| #include <netinet/in.h> |
| |
| #include <map> |
| |
| #include <base/command_line.h> |
| #include <base/logging.h> |
| #include <base/strings/string_number_conversions.h> |
| #include <brillo/syslog_logging.h> |
| |
| #include "shill/ppp_device.h" |
| #include "shill/rpc_task.h" |
| #include "shill/shims/environment.h" |
| #include "shill/shims/task_proxy.h" |
| |
| using std::map; |
| using std::string; |
| |
| namespace shill { |
| |
| namespace shims { |
| |
| static base::LazyInstance<PPP>::DestructorAtExit g_ppp = |
| LAZY_INSTANCE_INITIALIZER; |
| |
| PPP::PPP() : running_(false) {} |
| |
| PPP::~PPP() {} |
| |
| // static |
| PPP* PPP::GetInstance() { |
| return g_ppp.Pointer(); |
| } |
| |
| void PPP::Init() { |
| if (running_) { |
| return; |
| } |
| running_ = true; |
| base::CommandLine::Init(0, nullptr); |
| brillo::InitLog(brillo::kLogToSyslog | brillo::kLogHeader); |
| LOG(INFO) << "PPP started."; |
| } |
| |
| bool PPP::GetSecret(string* username, string* password) { |
| LOG(INFO) << __func__; |
| if (!CreateProxy()) { |
| return false; |
| } |
| bool success = proxy_->GetSecret(username, password); |
| DestroyProxy(); |
| return success; |
| } |
| |
| void PPP::OnAuthenticateStart() { |
| LOG(INFO) << __func__; |
| if (CreateProxy()) { |
| map<string, string> details; |
| proxy_->Notify(kPPPReasonAuthenticating, details); |
| DestroyProxy(); |
| } |
| } |
| |
| void PPP::OnAuthenticateDone() { |
| LOG(INFO) << __func__; |
| if (CreateProxy()) { |
| map<string, string> details; |
| proxy_->Notify(kPPPReasonAuthenticated, details); |
| DestroyProxy(); |
| } |
| } |
| |
| void PPP::OnConnect(const string& ifname) { |
| LOG(INFO) << __func__ << "(" << ifname << ")"; |
| if (!ipcp_gotoptions[0].ouraddr) { |
| LOG(ERROR) << "ouraddr not set."; |
| return; |
| } |
| map<string, string> dict; |
| dict[kPPPInterfaceName] = ifname; |
| dict[kPPPInternalIP4Address] = ConvertIPToText(&ipcp_gotoptions[0].ouraddr); |
| dict[kPPPExternalIP4Address] = ConvertIPToText(&ipcp_hisoptions[0].hisaddr); |
| if (ipcp_gotoptions[0].default_route) { |
| dict[kPPPGatewayAddress] = dict[kPPPExternalIP4Address]; |
| } |
| if (ipcp_gotoptions[0].dnsaddr[0]) { |
| dict[kPPPDNS1] = ConvertIPToText(&ipcp_gotoptions[0].dnsaddr[0]); |
| } |
| if (ipcp_gotoptions[0].dnsaddr[1]) { |
| dict[kPPPDNS2] = ConvertIPToText(&ipcp_gotoptions[0].dnsaddr[1]); |
| } |
| if (lcp_gotoptions[0].mru) { |
| dict[kPPPMRU] = base::IntToString(lcp_gotoptions[0].mru); |
| } |
| string lns_address; |
| if (Environment::GetInstance()->GetVariable("LNS_ADDRESS", &lns_address)) { |
| // Really an L2TP/IPSec option rather than a PPP one. But oh well. |
| dict[kPPPLNSAddress] = lns_address; |
| } |
| if (CreateProxy()) { |
| proxy_->Notify(kPPPReasonConnect, dict); |
| DestroyProxy(); |
| } |
| } |
| |
| void PPP::OnDisconnect() { |
| LOG(INFO) << __func__; |
| if (CreateProxy()) { |
| map<string, string> dict; |
| proxy_->Notify(kPPPReasonDisconnect, dict); |
| DestroyProxy(); |
| } |
| } |
| |
| bool PPP::CreateProxy() { |
| Environment* environment = Environment::GetInstance(); |
| string service, path; |
| if (!environment->GetVariable(kRPCTaskServiceVariable, &service) || |
| !environment->GetVariable(kRPCTaskPathVariable, &path)) { |
| LOG(ERROR) << "Environment variables not available."; |
| return false; |
| } |
| |
| dbus::Bus::Options options; |
| options.bus_type = dbus::Bus::SYSTEM; |
| bus_ = new dbus::Bus(options); |
| CHECK(bus_->Connect()); |
| |
| proxy_.reset(new TaskProxy(bus_, path, service)); |
| |
| LOG(INFO) << "Task proxy created: " << service << " - " << path; |
| return true; |
| } |
| |
| void PPP::DestroyProxy() { |
| proxy_.reset(); |
| if (bus_) { |
| bus_->ShutdownAndBlock(); |
| } |
| LOG(INFO) << "Task proxy destroyed."; |
| } |
| |
| // static |
| string PPP::ConvertIPToText(const void* addr) { |
| char text[INET_ADDRSTRLEN]; |
| inet_ntop(AF_INET, addr, text, INET_ADDRSTRLEN); |
| return text; |
| } |
| |
| } // namespace shims |
| |
| } // namespace shill |