PppController.cpp revision 1881762f345d011d079ee318d31f0a8d8ee5891e
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 21#include <sys/socket.h> 22#include <sys/stat.h> 23#include <sys/types.h> 24#include <sys/wait.h> 25 26#include <dirent.h> 27 28#include <netinet/in.h> 29#include <arpa/inet.h> 30 31#define LOG_TAG "PppController" 32#include <cutils/log.h> 33 34#include "PppController.h" 35 36extern "C" int logwrap(int argc, const char **argv, int background); 37 38PppController::PppController() { 39 mTtys = new TtyCollection(); 40 mPid = 0; 41} 42 43PppController::~PppController() { 44 TtyCollection::iterator it; 45 46 for (it = mTtys->begin(); it != mTtys->end(); ++it) { 47 free(*it); 48 } 49 mTtys->clear(); 50} 51 52int PppController::attachPppd(const char *tty, struct in_addr local, 53 struct in_addr remote) { 54 pid_t pid; 55 56 if (mPid) { 57 LOGE("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 LOGE("Invalid tty '%s' specified", tty); 70 errno = -EINVAL; 71 return -1; 72 } 73 74 if ((pid = fork()) < 0) { 75 LOGE("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 dev[32]; 83 char *lr; 84 85 asprintf(&lr, "%s:%s", l, r); 86 87 snprintf(dev, sizeof(dev), "/dev/%s", tty); 88 89 // TODO: Deal with pppd bailing out after 99999 seconds of being started 90 // but not getting a connection 91 if (execl("/system/bin/pppd", "/system/bin/pppd", "-detach", dev, 92 "115200", lr, "debug", "lcp-max-configure", "99999", (char *) NULL)) { 93 LOGE("execl failed (%s)", strerror(errno)); 94 } 95 LOGE("Should never get here!"); 96 return 0; 97 } else { 98 mPid = pid; 99 } 100 return 0; 101} 102 103int PppController::detachPppd(const char *tty) { 104 105 if (mPid == 0) { 106 LOGE("PPPD already stopped"); 107 return 0; 108 } 109 110 LOGD("Stopping PPPD services on port %s", tty); 111 kill(mPid, SIGTERM); 112 waitpid(mPid, NULL, 0); 113 mPid = 0; 114 LOGD("PPPD services on port %s stopped", tty); 115 return 0; 116} 117 118TtyCollection *PppController::getTtyList() { 119 updateTtyList(); 120 return mTtys; 121} 122 123int PppController::updateTtyList() { 124 TtyCollection::iterator it; 125 126 for (it = mTtys->begin(); it != mTtys->end(); ++it) { 127 free(*it); 128 } 129 mTtys->clear(); 130 131 DIR *d = opendir("/sys/class/tty"); 132 if (!d) { 133 LOGE("Error opening /sys/class/tty (%s)", strerror(errno)); 134 return -1; 135 } 136 137 struct dirent *de; 138 while ((de = readdir(d))) { 139 if (de->d_name[0] == '.') 140 continue; 141 if ((!strncmp(de->d_name, "tty", 3)) && (strlen(de->d_name) > 3)) { 142 mTtys->push_back(strdup(de->d_name)); 143 } 144 } 145 closedir(d); 146 return 0; 147} 148 149