ClatdController.cpp revision 69261cb65186e27dfbdc1e3eec796437f9968ff9
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#include <unistd.h> 17#include <errno.h> 18#include <sys/types.h> 19#include <sys/wait.h> 20 21#define LOG_TAG "ClatdController" 22#include <cutils/log.h> 23 24#include "NetdConstants.h" 25#include "ClatdController.h" 26#include "Fwmark.h" 27#include "NetdConstants.h" 28#include "NetworkController.h" 29 30ClatdController::ClatdController(NetworkController* controller) 31 : mNetCtrl(controller), mClatdPid(0) { 32} 33 34ClatdController::~ClatdController() { 35} 36 37int ClatdController::startClatd(char *interface) { 38 pid_t pid; 39 40 if(mClatdPid != 0) { 41 ALOGE("clatd already running"); 42 errno = EBUSY; 43 return -1; 44 } 45 46 if (!isIfaceName(interface)) { 47 errno = ENOENT; 48 return -1; 49 } 50 51 ALOGD("starting clatd"); 52 53 if ((pid = fork()) < 0) { 54 ALOGE("fork failed (%s)", strerror(errno)); 55 return -1; 56 } 57 58 if (!pid) { 59 // Pass in the interface, a netid to use for DNS lookups, and a fwmark for outgoing packets. 60 unsigned netId = mNetCtrl->getNetworkId(interface); 61 char netIdString[UINT32_STRLEN]; 62 snprintf(netIdString, sizeof(netIdString), "%u", netId); 63 64 Fwmark fwmark = { netId, true, true, PERMISSION_CONNECTIVITY_INTERNAL }; 65 char fwmarkString[UINT32_HEX_STRLEN]; 66 snprintf(fwmarkString, sizeof(fwmarkString), "0x%x", fwmark.intValue); 67 68 char *args[] = { 69 (char *) "/system/bin/clatd", 70 (char *) "-i", 71 interface, 72 (char *) "-n", 73 netIdString, 74 (char *) "-m", 75 fwmarkString, 76 NULL 77 }; 78 79 if (execv(args[0], args)) { 80 ALOGE("execv failed (%s)", strerror(errno)); 81 } 82 ALOGE("Should never get here!"); 83 _exit(0); 84 } else { 85 mClatdPid = pid; 86 ALOGD("clatd started"); 87 } 88 89 return 0; 90} 91 92int ClatdController::stopClatd() { 93 if (mClatdPid == 0) { 94 ALOGE("clatd already stopped"); 95 return -1; 96 } 97 98 ALOGD("Stopping clatd"); 99 100 kill(mClatdPid, SIGTERM); 101 waitpid(mClatdPid, NULL, 0); 102 mClatdPid = 0; 103 104 ALOGD("clatd stopped"); 105 106 return 0; 107} 108 109bool ClatdController::isClatdStarted() { 110 pid_t waitpid_status; 111 if(mClatdPid == 0) { 112 return false; 113 } 114 waitpid_status = waitpid(mClatdPid, NULL, WNOHANG); 115 if(waitpid_status != 0) { 116 mClatdPid = 0; // child exited, don't call waitpid on it again 117 } 118 return waitpid_status == 0; // 0 while child is running 119} 120