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 37 PppController::PppController() { 38 mTtys = new TtyCollection(); 39 mPid = 0; 40 } 41 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 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 89 snprintf(dev, sizeof(dev), "/dev/%s", tty); 90 91 // TODO: Deal with pppd bailing out after 99999 seconds of being started 92 // but not getting a connection 93 if (execl("/system/bin/pppd", "/system/bin/pppd", "-detach", dev, "115200", 94 lr, "ms-dns", d1, "ms-dns", d2, "lcp-max-configure", "99999", (char *) NULL)) { 95 ALOGE("execl failed (%s)", strerror(errno)); 96 } 97 ALOGE("Should never get here!"); 98 return 0; 99 } else { 100 mPid = pid; 101 } 102 return 0; 103 } 104 105 int PppController::detachPppd(const char *tty) { 106 107 if (mPid == 0) { 108 ALOGE("PPPD already stopped"); 109 return 0; 110 } 111 112 ALOGD("Stopping PPPD services on port %s", tty); 113 kill(mPid, SIGTERM); 114 waitpid(mPid, NULL, 0); 115 mPid = 0; 116 ALOGD("PPPD services on port %s stopped", tty); 117 return 0; 118 } 119 120 TtyCollection *PppController::getTtyList() { 121 updateTtyList(); 122 return mTtys; 123 } 124 125 int PppController::updateTtyList() { 126 TtyCollection::iterator it; 127 128 for (it = mTtys->begin(); it != mTtys->end(); ++it) { 129 free(*it); 130 } 131 mTtys->clear(); 132 133 DIR *d = opendir("/sys/class/tty"); 134 if (!d) { 135 ALOGE("Error opening /sys/class/tty (%s)", strerror(errno)); 136 return -1; 137 } 138 139 struct dirent *de; 140 while ((de = readdir(d))) { 141 if (de->d_name[0] == '.') 142 continue; 143 if ((!strncmp(de->d_name, "tty", 3)) && (strlen(de->d_name) > 3)) { 144 mTtys->push_back(strdup(de->d_name)); 145 } 146 } 147 closedir(d); 148 return 0; 149 } 150