10da73fcecc30140439f856118056df8908609627Daniel Drown/*
20da73fcecc30140439f856118056df8908609627Daniel Drown * Copyright (C) 2008 The Android Open Source Project
30da73fcecc30140439f856118056df8908609627Daniel Drown *
40da73fcecc30140439f856118056df8908609627Daniel Drown * Licensed under the Apache License, Version 2.0 (the "License");
50da73fcecc30140439f856118056df8908609627Daniel Drown * you may not use this file except in compliance with the License.
60da73fcecc30140439f856118056df8908609627Daniel Drown * You may obtain a copy of the License at
70da73fcecc30140439f856118056df8908609627Daniel Drown *
80da73fcecc30140439f856118056df8908609627Daniel Drown *      http://www.apache.org/licenses/LICENSE-2.0
90da73fcecc30140439f856118056df8908609627Daniel Drown *
100da73fcecc30140439f856118056df8908609627Daniel Drown * Unless required by applicable law or agreed to in writing, software
110da73fcecc30140439f856118056df8908609627Daniel Drown * distributed under the License is distributed on an "AS IS" BASIS,
120da73fcecc30140439f856118056df8908609627Daniel Drown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130da73fcecc30140439f856118056df8908609627Daniel Drown * See the License for the specific language governing permissions and
140da73fcecc30140439f856118056df8908609627Daniel Drown * limitations under the License.
150da73fcecc30140439f856118056df8908609627Daniel Drown */
16ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti#include <map>
17ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti#include <string>
18ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti
190da73fcecc30140439f856118056df8908609627Daniel Drown#include <unistd.h>
200da73fcecc30140439f856118056df8908609627Daniel Drown#include <errno.h>
210da73fcecc30140439f856118056df8908609627Daniel Drown#include <sys/types.h>
220da73fcecc30140439f856118056df8908609627Daniel Drown#include <sys/wait.h>
230da73fcecc30140439f856118056df8908609627Daniel Drown
240da73fcecc30140439f856118056df8908609627Daniel Drown#define LOG_TAG "ClatdController"
250da73fcecc30140439f856118056df8908609627Daniel Drown#include <cutils/log.h>
260da73fcecc30140439f856118056df8908609627Daniel Drown
27ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti#include <resolv_netid.h>
28ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti
2969261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall#include "NetdConstants.h"
300da73fcecc30140439f856118056df8908609627Daniel Drown#include "ClatdController.h"
3145d3dd0ad99d566ea589d9d5d37102ef35ca8fb2Lorenzo Colitti#include "Fwmark.h"
3284c1d035fdef996602ab8878d952c4fcb1f6963dPaul Jensen#include "NetdConstants.h"
3384c1d035fdef996602ab8878d952c4fcb1f6963dPaul Jensen#include "NetworkController.h"
340da73fcecc30140439f856118056df8908609627Daniel Drown
35ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colittistatic const char* kClatdPath = "/system/bin/clatd";
36ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti
3784c1d035fdef996602ab8878d952c4fcb1f6963dPaul JensenClatdController::ClatdController(NetworkController* controller)
38ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti        : mNetCtrl(controller) {
390da73fcecc30140439f856118056df8908609627Daniel Drown}
400da73fcecc30140439f856118056df8908609627Daniel Drown
410da73fcecc30140439f856118056df8908609627Daniel DrownClatdController::~ClatdController() {
420da73fcecc30140439f856118056df8908609627Daniel Drown}
430da73fcecc30140439f856118056df8908609627Daniel Drown
44ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti// Returns the PID of the clatd running on interface |interface|, or 0 if clatd is not running on
45ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti// |interface|.
46ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colittipid_t ClatdController::getClatdPid(char* interface) {
47ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti    auto it = mClatdPids.find(interface);
48ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti    return (it == mClatdPids.end() ? 0 : it->second);
49ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti}
50ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti
51ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colittiint ClatdController::startClatd(char* interface) {
52ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti    pid_t pid = getClatdPid(interface);
530da73fcecc30140439f856118056df8908609627Daniel Drown
54ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti    if (pid != 0) {
55ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti        ALOGE("clatd pid=%d already started on %s", pid, interface);
560da73fcecc30140439f856118056df8908609627Daniel Drown        errno = EBUSY;
570da73fcecc30140439f856118056df8908609627Daniel Drown        return -1;
580da73fcecc30140439f856118056df8908609627Daniel Drown    }
590da73fcecc30140439f856118056df8908609627Daniel Drown
602e5fa934741dbf8be9729e1250f6cf37b8d9027fLorenzo Colitti    // Pass in the interface, a netid to use for DNS lookups, and a fwmark for outgoing packets.
612e5fa934741dbf8be9729e1250f6cf37b8d9027fLorenzo Colitti    unsigned netId = mNetCtrl->getNetworkForInterface(interface);
622e5fa934741dbf8be9729e1250f6cf37b8d9027fLorenzo Colitti    if (netId == NETID_UNSET) {
632e5fa934741dbf8be9729e1250f6cf37b8d9027fLorenzo Colitti        ALOGE("interface %s not assigned to any netId", interface);
642e5fa934741dbf8be9729e1250f6cf37b8d9027fLorenzo Colitti        errno = ENODEV;
652e5fa934741dbf8be9729e1250f6cf37b8d9027fLorenzo Colitti        return -1;
662e5fa934741dbf8be9729e1250f6cf37b8d9027fLorenzo Colitti    }
672e5fa934741dbf8be9729e1250f6cf37b8d9027fLorenzo Colitti
682e5fa934741dbf8be9729e1250f6cf37b8d9027fLorenzo Colitti    char netIdString[UINT32_STRLEN];
692e5fa934741dbf8be9729e1250f6cf37b8d9027fLorenzo Colitti    snprintf(netIdString, sizeof(netIdString), "%u", netId);
702e5fa934741dbf8be9729e1250f6cf37b8d9027fLorenzo Colitti
712e5fa934741dbf8be9729e1250f6cf37b8d9027fLorenzo Colitti    Fwmark fwmark;
722e5fa934741dbf8be9729e1250f6cf37b8d9027fLorenzo Colitti    fwmark.netId = netId;
732e5fa934741dbf8be9729e1250f6cf37b8d9027fLorenzo Colitti    fwmark.explicitlySelected = true;
742e5fa934741dbf8be9729e1250f6cf37b8d9027fLorenzo Colitti    fwmark.protectedFromVpn = true;
752e5fa934741dbf8be9729e1250f6cf37b8d9027fLorenzo Colitti    fwmark.permission = PERMISSION_SYSTEM;
762e5fa934741dbf8be9729e1250f6cf37b8d9027fLorenzo Colitti
772e5fa934741dbf8be9729e1250f6cf37b8d9027fLorenzo Colitti    char fwmarkString[UINT32_HEX_STRLEN];
782e5fa934741dbf8be9729e1250f6cf37b8d9027fLorenzo Colitti    snprintf(fwmarkString, sizeof(fwmarkString), "0x%x", fwmark.intValue);
792e5fa934741dbf8be9729e1250f6cf37b8d9027fLorenzo Colitti
80ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti    ALOGD("starting clatd on %s", interface);
8169261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall
82ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti    std::string progname("clatd-");
83ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti    progname += interface;
840da73fcecc30140439f856118056df8908609627Daniel Drown
850da73fcecc30140439f856118056df8908609627Daniel Drown    if ((pid = fork()) < 0) {
860da73fcecc30140439f856118056df8908609627Daniel Drown        ALOGE("fork failed (%s)", strerror(errno));
870da73fcecc30140439f856118056df8908609627Daniel Drown        return -1;
880da73fcecc30140439f856118056df8908609627Daniel Drown    }
890da73fcecc30140439f856118056df8908609627Daniel Drown
900da73fcecc30140439f856118056df8908609627Daniel Drown    if (!pid) {
9184c1d035fdef996602ab8878d952c4fcb1f6963dPaul Jensen        char *args[] = {
92ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti            (char *) progname.c_str(),
9345d3dd0ad99d566ea589d9d5d37102ef35ca8fb2Lorenzo Colitti            (char *) "-i",
9484c1d035fdef996602ab8878d952c4fcb1f6963dPaul Jensen            interface,
9545d3dd0ad99d566ea589d9d5d37102ef35ca8fb2Lorenzo Colitti            (char *) "-n",
9645d3dd0ad99d566ea589d9d5d37102ef35ca8fb2Lorenzo Colitti            netIdString,
9745d3dd0ad99d566ea589d9d5d37102ef35ca8fb2Lorenzo Colitti            (char *) "-m",
9845d3dd0ad99d566ea589d9d5d37102ef35ca8fb2Lorenzo Colitti            fwmarkString,
9984c1d035fdef996602ab8878d952c4fcb1f6963dPaul Jensen            NULL
10084c1d035fdef996602ab8878d952c4fcb1f6963dPaul Jensen        };
1010da73fcecc30140439f856118056df8908609627Daniel Drown
102ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti        if (execv(kClatdPath, args)) {
1030da73fcecc30140439f856118056df8908609627Daniel Drown            ALOGE("execv failed (%s)", strerror(errno));
1042e5fa934741dbf8be9729e1250f6cf37b8d9027fLorenzo Colitti            _exit(1);
1050da73fcecc30140439f856118056df8908609627Daniel Drown        }
1060da73fcecc30140439f856118056df8908609627Daniel Drown        ALOGE("Should never get here!");
1072e5fa934741dbf8be9729e1250f6cf37b8d9027fLorenzo Colitti        _exit(1);
1080da73fcecc30140439f856118056df8908609627Daniel Drown    } else {
109ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti        mClatdPids[interface] = pid;
110ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti        ALOGD("clatd started on %s", interface);
1110da73fcecc30140439f856118056df8908609627Daniel Drown    }
1120da73fcecc30140439f856118056df8908609627Daniel Drown
1130da73fcecc30140439f856118056df8908609627Daniel Drown    return 0;
1140da73fcecc30140439f856118056df8908609627Daniel Drown}
1150da73fcecc30140439f856118056df8908609627Daniel Drown
116ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colittiint ClatdController::stopClatd(char* interface) {
117ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti    pid_t pid = getClatdPid(interface);
118ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti
119ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti    if (pid == 0) {
1200da73fcecc30140439f856118056df8908609627Daniel Drown        ALOGE("clatd already stopped");
1210da73fcecc30140439f856118056df8908609627Daniel Drown        return -1;
1220da73fcecc30140439f856118056df8908609627Daniel Drown    }
1230da73fcecc30140439f856118056df8908609627Daniel Drown
124ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti    ALOGD("Stopping clatd pid=%d on %s", pid, interface);
1250da73fcecc30140439f856118056df8908609627Daniel Drown
126ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti    kill(pid, SIGTERM);
127ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti    waitpid(pid, NULL, 0);
128ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti    mClatdPids.erase(interface);
1290da73fcecc30140439f856118056df8908609627Daniel Drown
130ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti    ALOGD("clatd on %s stopped", interface);
1310da73fcecc30140439f856118056df8908609627Daniel Drown
1320da73fcecc30140439f856118056df8908609627Daniel Drown    return 0;
1330da73fcecc30140439f856118056df8908609627Daniel Drown}
1340da73fcecc30140439f856118056df8908609627Daniel Drown
135ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colittibool ClatdController::isClatdStarted(char* interface) {
1360da73fcecc30140439f856118056df8908609627Daniel Drown    pid_t waitpid_status;
137ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti    pid_t pid = getClatdPid(interface);
138ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti    if (pid == 0) {
1390da73fcecc30140439f856118056df8908609627Daniel Drown        return false;
1400da73fcecc30140439f856118056df8908609627Daniel Drown    }
141ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti    waitpid_status = waitpid(pid, NULL, WNOHANG);
142ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti    if (waitpid_status != 0) {
143ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti        mClatdPids.erase(interface);  // child exited, don't call waitpid on it again
1440da73fcecc30140439f856118056df8908609627Daniel Drown    }
1450da73fcecc30140439f856118056df8908609627Daniel Drown    return waitpid_status == 0; // 0 while child is running
1460da73fcecc30140439f856118056df8908609627Daniel Drown}
147