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 37PppController::PppController() { 38 mTtys = new TtyCollection(); 39 mPid = 0; 40} 41 42PppController::~PppController() { 43 TtyCollection::iterator it; 44 45 for (it = mTtys->begin(); it != mTtys->end(); ++it) { 46 free(*it); 47 } 48 mTtys->clear(); 49} 50 51int 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 110int 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 125TtyCollection *PppController::getTtyList() { 126 updateTtyList(); 127 return mTtys; 128} 129 130int 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