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 63 PPP::PPP() : running_(false) {} 64 65 PPP::~PPP() {} 66 67 // static 68 PPP* PPP::GetInstance() { 69 return g_ppp.Pointer(); 70 } 71 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 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 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 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 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 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 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 172 void PPP::DestroyProxy() { 173 proxy_.reset(); 174 if (bus_) { 175 bus_->ShutdownAndBlock(); 176 } 177 LOG(INFO) << "Task proxy destroyed."; 178 } 179 180 // static 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