NetdConstants.cpp revision 69261cb65186e27dfbdc1e3eec796437f9968ff9
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#include <ctype.h> 21#include <net/if.h> 22 23#define LOG_TAG "Netd" 24 25#include <cutils/log.h> 26#include <logwrap/logwrap.h> 27 28#include "NetdConstants.h" 29 30const char * const OEM_SCRIPT_PATH = "/system/bin/oem-iptables-init.sh"; 31const char * const IPTABLES_PATH = "/system/bin/iptables"; 32const char * const IP6TABLES_PATH = "/system/bin/ip6tables"; 33const char * const TC_PATH = "/system/bin/tc"; 34const char * const IP_PATH = "/system/bin/ip"; 35const char * const ADD = "add"; 36const char * const DEL = "del"; 37 38static void logExecError(const char* argv[], int res, int status) { 39 const char** argp = argv; 40 std::string args = ""; 41 while (*argp) { 42 args += *argp; 43 args += ' '; 44 argp++; 45 } 46 ALOGE("exec() res=%d, status=%d for %s", res, status, args.c_str()); 47} 48 49static int execIptablesCommand(int argc, const char *argv[], bool silent) { 50 int res; 51 int status; 52 53 res = android_fork_execvp(argc, (char **)argv, &status, false, 54 !silent); 55 if (res || !WIFEXITED(status) || WEXITSTATUS(status)) { 56 if (!silent) { 57 logExecError(argv, res, status); 58 } 59 if (res) 60 return res; 61 if (!WIFEXITED(status)) 62 return ECHILD; 63 } 64 return WEXITSTATUS(status); 65} 66 67static int execIptables(IptablesTarget target, bool silent, va_list args) { 68 /* Read arguments from incoming va_list; we expect the list to be NULL terminated. */ 69 std::list<const char*> argsList; 70 argsList.push_back(NULL); 71 const char* arg; 72 do { 73 arg = va_arg(args, const char *); 74 argsList.push_back(arg); 75 } while (arg); 76 77 int i = 0; 78 const char* argv[argsList.size()]; 79 std::list<const char*>::iterator it; 80 for (it = argsList.begin(); it != argsList.end(); it++, i++) { 81 argv[i] = *it; 82 } 83 84 int res = 0; 85 if (target == V4 || target == V4V6) { 86 argv[0] = IPTABLES_PATH; 87 res |= execIptablesCommand(argsList.size(), argv, silent); 88 } 89 if (target == V6 || target == V4V6) { 90 argv[0] = IP6TABLES_PATH; 91 res |= execIptablesCommand(argsList.size(), argv, silent); 92 } 93 return res; 94} 95 96int execIptables(IptablesTarget target, ...) { 97 va_list args; 98 va_start(args, target); 99 int res = execIptables(target, false, args); 100 va_end(args); 101 return res; 102} 103 104int execIptablesSilently(IptablesTarget target, ...) { 105 va_list args; 106 va_start(args, target); 107 int res = execIptables(target, true, args); 108 va_end(args); 109 return res; 110} 111 112int writeFile(const char *path, const char *value, int size) { 113 int fd = open(path, O_WRONLY); 114 if (fd < 0) { 115 ALOGE("Failed to open %s: %s", path, strerror(errno)); 116 return -1; 117 } 118 119 if (write(fd, value, size) != size) { 120 ALOGE("Failed to write %s: %s", path, strerror(errno)); 121 close(fd); 122 return -1; 123 } 124 close(fd); 125 return 0; 126} 127 128int readFile(const char *path, char *buf, int *sizep) 129{ 130 int fd = open(path, O_RDONLY); 131 int size; 132 133 if (fd < 0) { 134 ALOGE("Failed to open %s: %s", path, strerror(errno)); 135 return -1; 136 } 137 138 size = read(fd, buf, *sizep); 139 if (size < 0) { 140 ALOGE("Failed to write %s: %s", path, strerror(errno)); 141 close(fd); 142 return -1; 143 } 144 *sizep = size; 145 close(fd); 146 return 0; 147} 148 149/* 150 * Check an interface name for plausibility. This should e.g. help against 151 * directory traversal. 152 */ 153bool isIfaceName(const char *name) { 154 size_t i; 155 size_t name_len = strlen(name); 156 if ((name_len == 0) || (name_len > IFNAMSIZ)) { 157 return false; 158 } 159 160 /* First character must be alphanumeric */ 161 if (!isalnum(name[0])) { 162 return false; 163 } 164 165 for (i = 1; i < name_len; i++) { 166 if (!isalnum(name[i]) && (name[i] != '_') && (name[i] != '-') && (name[i] != ':')) { 167 return false; 168 } 169 } 170 171 return true; 172} 173