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