Home | History | Annotate | Download | only in netd
      1 /*
      2  * Copyright (C) 2012 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 <fcntl.h>
     18 #include <string.h>
     19 #include <sys/wait.h>
     20 
     21 #define LOG_TAG "Netd"
     22 
     23 #include <cutils/log.h>
     24 #include <logwrap/logwrap.h>
     25 
     26 #include "NetdConstants.h"
     27 
     28 const char * const OEM_SCRIPT_PATH = "/system/bin/oem-iptables-init.sh";
     29 const char * const IPTABLES_PATH = "/system/bin/iptables";
     30 const char * const IP6TABLES_PATH = "/system/bin/ip6tables";
     31 const char * const TC_PATH = "/system/bin/tc";
     32 const char * const IP_PATH = "/system/bin/ip";
     33 const char * const ADD = "add";
     34 const char * const DEL = "del";
     35 
     36 static void logExecError(const char* argv[], int res, int status) {
     37     const char** argp = argv;
     38     std::string args = "";
     39     while (*argp) {
     40         args += *argp;
     41         args += ' ';
     42         argp++;
     43     }
     44     ALOGE("exec() res=%d, status=%d for %s", res, status, args.c_str());
     45 }
     46 
     47 static int execIptablesCommand(int argc, const char *argv[], bool silent) {
     48     int res;
     49     int status;
     50 
     51     res = android_fork_execvp(argc, (char **)argv, &status, false,
     52         !silent);
     53     if (res || !WIFEXITED(status) || WEXITSTATUS(status)) {
     54         if (!silent) {
     55             logExecError(argv, res, status);
     56         }
     57         if (res)
     58             return res;
     59         if (!WIFEXITED(status))
     60             return ECHILD;
     61     }
     62     return WEXITSTATUS(status);
     63 }
     64 
     65 static int execIptables(IptablesTarget target, bool silent, va_list args) {
     66     /* Read arguments from incoming va_list; we expect the list to be NULL terminated. */
     67     std::list<const char*> argsList;
     68     argsList.push_back(NULL);
     69     const char* arg;
     70     do {
     71         arg = va_arg(args, const char *);
     72         argsList.push_back(arg);
     73     } while (arg);
     74 
     75     int i = 0;
     76     const char* argv[argsList.size()];
     77     std::list<const char*>::iterator it;
     78     for (it = argsList.begin(); it != argsList.end(); it++, i++) {
     79         argv[i] = *it;
     80     }
     81 
     82     int res = 0;
     83     if (target == V4 || target == V4V6) {
     84         argv[0] = IPTABLES_PATH;
     85         res |= execIptablesCommand(argsList.size(), argv, silent);
     86     }
     87     if (target == V6 || target == V4V6) {
     88         argv[0] = IP6TABLES_PATH;
     89         res |= execIptablesCommand(argsList.size(), argv, silent);
     90     }
     91     return res;
     92 }
     93 
     94 int execIptables(IptablesTarget target, ...) {
     95     va_list args;
     96     va_start(args, target);
     97     int res = execIptables(target, false, args);
     98     va_end(args);
     99     return res;
    100 }
    101 
    102 int execIptablesSilently(IptablesTarget target, ...) {
    103     va_list args;
    104     va_start(args, target);
    105     int res = execIptables(target, true, args);
    106     va_end(args);
    107     return res;
    108 }
    109 
    110 int writeFile(const char *path, const char *value, int size) {
    111     int fd = open(path, O_WRONLY);
    112     if (fd < 0) {
    113         ALOGE("Failed to open %s: %s", path, strerror(errno));
    114         return -1;
    115     }
    116 
    117     if (write(fd, value, size) != size) {
    118         ALOGE("Failed to write %s: %s", path, strerror(errno));
    119         close(fd);
    120         return -1;
    121     }
    122     close(fd);
    123     return 0;
    124 }
    125 
    126 int readFile(const char *path, char *buf, int *sizep)
    127 {
    128     int fd = open(path, O_RDONLY);
    129     int size;
    130 
    131     if (fd < 0) {
    132         ALOGE("Failed to open %s: %s", path, strerror(errno));
    133         return -1;
    134     }
    135 
    136     size = read(fd, buf, *sizep);
    137     if (size < 0) {
    138         ALOGE("Failed to write %s: %s", path, strerror(errno));
    139         close(fd);
    140         return -1;
    141     }
    142     *sizep = size;
    143     close(fd);
    144     return 0;
    145 }
    146