1d5573d34c8fac49e16b20cf144486125bf940086San Mehat/*
2d5573d34c8fac49e16b20cf144486125bf940086San Mehat * Copyright (C) 2008 The Android Open Source Project
3d5573d34c8fac49e16b20cf144486125bf940086San Mehat *
4d5573d34c8fac49e16b20cf144486125bf940086San Mehat * Licensed under the Apache License, Version 2.0 (the "License");
5d5573d34c8fac49e16b20cf144486125bf940086San Mehat * you may not use this file except in compliance with the License.
6d5573d34c8fac49e16b20cf144486125bf940086San Mehat * You may obtain a copy of the License at
7d5573d34c8fac49e16b20cf144486125bf940086San Mehat *
8d5573d34c8fac49e16b20cf144486125bf940086San Mehat *      http://www.apache.org/licenses/LICENSE-2.0
9d5573d34c8fac49e16b20cf144486125bf940086San Mehat *
10d5573d34c8fac49e16b20cf144486125bf940086San Mehat * Unless required by applicable law or agreed to in writing, software
11d5573d34c8fac49e16b20cf144486125bf940086San Mehat * distributed under the License is distributed on an "AS IS" BASIS,
12d5573d34c8fac49e16b20cf144486125bf940086San Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d5573d34c8fac49e16b20cf144486125bf940086San Mehat * See the License for the specific language governing permissions and
14d5573d34c8fac49e16b20cf144486125bf940086San Mehat * limitations under the License.
15d5573d34c8fac49e16b20cf144486125bf940086San Mehat */
16d5573d34c8fac49e16b20cf144486125bf940086San Mehat
17d5573d34c8fac49e16b20cf144486125bf940086San Mehat#include <stdlib.h>
18d5573d34c8fac49e16b20cf144486125bf940086San Mehat#include <errno.h>
191881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat#include <fcntl.h>
20ff2c0d8c13457e43f0d4bf06d3177271aac104c1Olivier Bailly#include <string.h>
211881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat
22d5573d34c8fac49e16b20cf144486125bf940086San Mehat#include <sys/socket.h>
23d5573d34c8fac49e16b20cf144486125bf940086San Mehat#include <sys/stat.h>
241881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat#include <sys/types.h>
251881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat#include <sys/wait.h>
261881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat
271881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat#include <dirent.h>
281881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat
29d5573d34c8fac49e16b20cf144486125bf940086San Mehat#include <netinet/in.h>
30d5573d34c8fac49e16b20cf144486125bf940086San Mehat#include <arpa/inet.h>
31d5573d34c8fac49e16b20cf144486125bf940086San Mehat
32d5573d34c8fac49e16b20cf144486125bf940086San Mehat#define LOG_TAG "PppController"
33d5573d34c8fac49e16b20cf144486125bf940086San Mehat#include <cutils/log.h>
34d5573d34c8fac49e16b20cf144486125bf940086San Mehat
35d5573d34c8fac49e16b20cf144486125bf940086San Mehat#include "PppController.h"
36d5573d34c8fac49e16b20cf144486125bf940086San Mehat
37d5573d34c8fac49e16b20cf144486125bf940086San MehatPppController::PppController() {
38d5573d34c8fac49e16b20cf144486125bf940086San Mehat    mTtys = new TtyCollection();
39d5573d34c8fac49e16b20cf144486125bf940086San Mehat    mPid = 0;
40d5573d34c8fac49e16b20cf144486125bf940086San Mehat}
41d5573d34c8fac49e16b20cf144486125bf940086San Mehat
42d5573d34c8fac49e16b20cf144486125bf940086San MehatPppController::~PppController() {
43d5573d34c8fac49e16b20cf144486125bf940086San Mehat    TtyCollection::iterator it;
44d5573d34c8fac49e16b20cf144486125bf940086San Mehat
45d5573d34c8fac49e16b20cf144486125bf940086San Mehat    for (it = mTtys->begin(); it != mTtys->end(); ++it) {
46d5573d34c8fac49e16b20cf144486125bf940086San Mehat        free(*it);
47d5573d34c8fac49e16b20cf144486125bf940086San Mehat    }
48d5573d34c8fac49e16b20cf144486125bf940086San Mehat    mTtys->clear();
49d5573d34c8fac49e16b20cf144486125bf940086San Mehat}
50d5573d34c8fac49e16b20cf144486125bf940086San Mehat
51d5573d34c8fac49e16b20cf144486125bf940086San Mehatint PppController::attachPppd(const char *tty, struct in_addr local,
5274d8fdd307275bfdf95dcf61d9e6366e87da24ecRobert Greenwalt                              struct in_addr remote, struct in_addr dns1,
5374d8fdd307275bfdf95dcf61d9e6366e87da24ecRobert Greenwalt                              struct in_addr dns2) {
54d5573d34c8fac49e16b20cf144486125bf940086San Mehat    pid_t pid;
55d5573d34c8fac49e16b20cf144486125bf940086San Mehat
56d5573d34c8fac49e16b20cf144486125bf940086San Mehat    if (mPid) {
575ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Multiple PPPD instances not currently supported");
58d5573d34c8fac49e16b20cf144486125bf940086San Mehat        errno = EBUSY;
59d5573d34c8fac49e16b20cf144486125bf940086San Mehat        return -1;
60d5573d34c8fac49e16b20cf144486125bf940086San Mehat    }
61d5573d34c8fac49e16b20cf144486125bf940086San Mehat
621881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat    TtyCollection::iterator it;
631881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat    for (it = mTtys->begin(); it != mTtys->end(); ++it) {
641881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat        if (!strcmp(tty, *it)) {
651881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat            break;
661881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat        }
671881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat    }
681881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat    if (it == mTtys->end()) {
695ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Invalid tty '%s' specified", tty);
701881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat        errno = -EINVAL;
711881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat        return -1;
721881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat    }
731881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat
74d5573d34c8fac49e16b20cf144486125bf940086San Mehat    if ((pid = fork()) < 0) {
755ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("fork failed (%s)", strerror(errno));
76d5573d34c8fac49e16b20cf144486125bf940086San Mehat        return -1;
77d5573d34c8fac49e16b20cf144486125bf940086San Mehat    }
78d5573d34c8fac49e16b20cf144486125bf940086San Mehat
79d5573d34c8fac49e16b20cf144486125bf940086San Mehat    if (!pid) {
80d5573d34c8fac49e16b20cf144486125bf940086San Mehat        char *l = strdup(inet_ntoa(local));
81d5573d34c8fac49e16b20cf144486125bf940086San Mehat        char *r = strdup(inet_ntoa(remote));
8274d8fdd307275bfdf95dcf61d9e6366e87da24ecRobert Greenwalt        char *d1 = strdup(inet_ntoa(dns1));
8374d8fdd307275bfdf95dcf61d9e6366e87da24ecRobert Greenwalt        char *d2 = strdup(inet_ntoa(dns2));
84d5573d34c8fac49e16b20cf144486125bf940086San Mehat        char dev[32];
85d5573d34c8fac49e16b20cf144486125bf940086San Mehat        char *lr;
86d5573d34c8fac49e16b20cf144486125bf940086San Mehat
87d5573d34c8fac49e16b20cf144486125bf940086San Mehat        asprintf(&lr, "%s:%s", l, r);
88d5573d34c8fac49e16b20cf144486125bf940086San Mehat
891881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat        snprintf(dev, sizeof(dev), "/dev/%s", tty);
90d5573d34c8fac49e16b20cf144486125bf940086San Mehat
91d5573d34c8fac49e16b20cf144486125bf940086San Mehat        // TODO: Deal with pppd bailing out after 99999 seconds of being started
92d5573d34c8fac49e16b20cf144486125bf940086San Mehat        // but not getting a connection
9374d8fdd307275bfdf95dcf61d9e6366e87da24ecRobert Greenwalt        if (execl("/system/bin/pppd", "/system/bin/pppd", "-detach", dev, "115200",
9473ea55b52895727635705f18629406c58ca2044cRobert Greenwalt                  lr, "ms-dns", d1, "ms-dns", d2, "lcp-max-configure", "99999", (char *) NULL)) {
955ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block            ALOGE("execl failed (%s)", strerror(errno));
96d5573d34c8fac49e16b20cf144486125bf940086San Mehat        }
975ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Should never get here!");
98d5573d34c8fac49e16b20cf144486125bf940086San Mehat        return 0;
99d5573d34c8fac49e16b20cf144486125bf940086San Mehat    } else {
100d5573d34c8fac49e16b20cf144486125bf940086San Mehat        mPid = pid;
101d5573d34c8fac49e16b20cf144486125bf940086San Mehat    }
102d5573d34c8fac49e16b20cf144486125bf940086San Mehat    return 0;
103d5573d34c8fac49e16b20cf144486125bf940086San Mehat}
104d5573d34c8fac49e16b20cf144486125bf940086San Mehat
105d5573d34c8fac49e16b20cf144486125bf940086San Mehatint PppController::detachPppd(const char *tty) {
106d5573d34c8fac49e16b20cf144486125bf940086San Mehat
107d5573d34c8fac49e16b20cf144486125bf940086San Mehat    if (mPid == 0) {
1085ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("PPPD already stopped");
109d5573d34c8fac49e16b20cf144486125bf940086San Mehat        return 0;
110d5573d34c8fac49e16b20cf144486125bf940086San Mehat    }
111d5573d34c8fac49e16b20cf144486125bf940086San Mehat
1127b984e3f7e724f8a3547a707210319f3d479f261Steve Block    ALOGD("Stopping PPPD services on port %s", tty);
113d5573d34c8fac49e16b20cf144486125bf940086San Mehat    kill(mPid, SIGTERM);
1141881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat    waitpid(mPid, NULL, 0);
115d5573d34c8fac49e16b20cf144486125bf940086San Mehat    mPid = 0;
1167b984e3f7e724f8a3547a707210319f3d479f261Steve Block    ALOGD("PPPD services on port %s stopped", tty);
117d5573d34c8fac49e16b20cf144486125bf940086San Mehat    return 0;
118d5573d34c8fac49e16b20cf144486125bf940086San Mehat}
119d5573d34c8fac49e16b20cf144486125bf940086San Mehat
120d5573d34c8fac49e16b20cf144486125bf940086San MehatTtyCollection *PppController::getTtyList() {
1211881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat    updateTtyList();
122d5573d34c8fac49e16b20cf144486125bf940086San Mehat    return mTtys;
123d5573d34c8fac49e16b20cf144486125bf940086San Mehat}
124d5573d34c8fac49e16b20cf144486125bf940086San Mehat
1251881762f345d011d079ee318d31f0a8d8ee5891eSan Mehatint PppController::updateTtyList() {
1261881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat    TtyCollection::iterator it;
1271881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat
1281881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat    for (it = mTtys->begin(); it != mTtys->end(); ++it) {
1291881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat        free(*it);
1301881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat    }
1311881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat    mTtys->clear();
1321881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat
1331881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat    DIR *d = opendir("/sys/class/tty");
1341881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat    if (!d) {
1355ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Error opening /sys/class/tty (%s)", strerror(errno));
1361881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat        return -1;
1371881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat    }
1381881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat
1391881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat    struct dirent *de;
1401881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat    while ((de = readdir(d))) {
1411881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat        if (de->d_name[0] == '.')
1421881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat            continue;
1431881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat        if ((!strncmp(de->d_name, "tty", 3)) && (strlen(de->d_name) > 3)) {
1441881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat            mTtys->push_back(strdup(de->d_name));
1451881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat        }
1461881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat    }
1471881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat    closedir(d);
1481881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat    return 0;
1491881762f345d011d079ee318d31f0a8d8ee5891eSan Mehat}
150