Home | History | Annotate | Download | only in shims
      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