• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright (C) 2008 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 <stdlib.h>
18  #include <errno.h>
19  #include <fcntl.h>
20  #include <string.h>
21  
22  #include <sys/socket.h>
23  #include <sys/stat.h>
24  #include <sys/types.h>
25  #include <sys/wait.h>
26  
27  #include <dirent.h>
28  
29  #include <netinet/in.h>
30  #include <arpa/inet.h>
31  
32  #define LOG_TAG "PppController"
33  #include <cutils/log.h>
34  
35  #include "PppController.h"
36  
PppController()37  PppController::PppController() {
38      mTtys = new TtyCollection();
39      mPid = 0;
40  }
41  
~PppController()42  PppController::~PppController() {
43      TtyCollection::iterator it;
44  
45      for (it = mTtys->begin(); it != mTtys->end(); ++it) {
46          free(*it);
47      }
48      mTtys->clear();
49  }
50  
attachPppd(const char * tty,struct in_addr local,struct in_addr remote,struct in_addr dns1,struct in_addr dns2)51  int PppController::attachPppd(const char *tty, struct in_addr local,
52                                struct in_addr remote, struct in_addr dns1,
53                                struct in_addr dns2) {
54      pid_t pid;
55  
56      if (mPid) {
57          ALOGE("Multiple PPPD instances not currently supported");
58          errno = EBUSY;
59          return -1;
60      }
61  
62      TtyCollection::iterator it;
63      for (it = mTtys->begin(); it != mTtys->end(); ++it) {
64          if (!strcmp(tty, *it)) {
65              break;
66          }
67      }
68      if (it == mTtys->end()) {
69          ALOGE("Invalid tty '%s' specified", tty);
70          errno = -EINVAL;
71          return -1;
72      }
73  
74      if ((pid = fork()) < 0) {
75          ALOGE("fork failed (%s)", strerror(errno));
76          return -1;
77      }
78  
79      if (!pid) {
80          char *l = strdup(inet_ntoa(local));
81          char *r = strdup(inet_ntoa(remote));
82          char *d1 = strdup(inet_ntoa(dns1));
83          char *d2 = strdup(inet_ntoa(dns2));
84          char dev[32];
85          char *lr;
86  
87          asprintf(&lr, "%s:%s", l, r);
88          free(l);
89          free(r);
90  
91          snprintf(dev, sizeof(dev), "/dev/%s", tty);
92  
93          // TODO: Deal with pppd bailing out after 99999 seconds of being started
94          // but not getting a connection
95          if (execl("/system/bin/pppd", "/system/bin/pppd", "-detach", dev, "115200",
96                    lr, "ms-dns", d1, "ms-dns", d2, "lcp-max-configure", "99999", (char *) NULL)) {
97              ALOGE("execl failed (%s)", strerror(errno));
98          }
99          free(lr);
100          free(d1);
101          free(d2);
102          ALOGE("Should never get here!");
103          return 0;
104      } else {
105          mPid = pid;
106      }
107      return 0;
108  }
109  
detachPppd(const char * tty)110  int PppController::detachPppd(const char *tty) {
111  
112      if (mPid == 0) {
113          ALOGE("PPPD already stopped");
114          return 0;
115      }
116  
117      ALOGD("Stopping PPPD services on port %s", tty);
118      kill(mPid, SIGTERM);
119      waitpid(mPid, NULL, 0);
120      mPid = 0;
121      ALOGD("PPPD services on port %s stopped", tty);
122      return 0;
123  }
124  
getTtyList()125  TtyCollection *PppController::getTtyList() {
126      updateTtyList();
127      return mTtys;
128  }
129  
updateTtyList()130  int PppController::updateTtyList() {
131      TtyCollection::iterator it;
132  
133      for (it = mTtys->begin(); it != mTtys->end(); ++it) {
134          free(*it);
135      }
136      mTtys->clear();
137  
138      DIR *d = opendir("/sys/class/tty");
139      if (!d) {
140          ALOGE("Error opening /sys/class/tty (%s)", strerror(errno));
141          return -1;
142      }
143  
144      struct dirent *de;
145      while ((de = readdir(d))) {
146          if (de->d_name[0] == '.')
147              continue;
148          if ((!strncmp(de->d_name, "tty", 3)) && (strlen(de->d_name) > 3)) {
149              mTtys->push_back(strdup(de->d_name));
150          }
151      }
152      closedir(d);
153      return 0;
154  }
155