blob: 58b2f64ba65aac0a306333fc5be0682d641e9d99 [file] [log] [blame]
Robert Greenwaltc4621772012-01-31 12:46:45 -08001/*
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
Dan Albertaa1be2b2015-01-06 09:36:17 -080017#include <ctype.h>
18#include <errno.h>
Lorenzo Colitti70afde62013-03-04 17:58:40 +090019#include <fcntl.h>
Lorenzo Colittiba25df92014-06-18 00:22:17 +090020#include <netdb.h>
Dan Albertaa1be2b2015-01-06 09:36:17 -080021#include <net/if.h>
Lorenzo Colittiba25df92014-06-18 00:22:17 +090022#include <netinet/in.h>
Ben Schwartze7601812017-04-28 16:38:29 -040023#include <openssl/ssl.h>
Lorenzo Colittiba25df92014-06-18 00:22:17 +090024#include <stdlib.h>
Jeff Sharkey8e188ed2012-07-12 18:32:03 -070025#include <string.h>
Rom Lemarchand838ef642013-01-24 15:14:41 -080026#include <sys/wait.h>
Jeff Sharkey8e188ed2012-07-12 18:32:03 -070027
Jeff Sharkeybec6d042012-09-06 15:45:56 -070028#define LOG_TAG "Netd"
29
Lorenzo Colittic1306ea2017-03-27 05:52:31 +090030#include <android-base/stringprintf.h>
Jeff Sharkey8e188ed2012-07-12 18:32:03 -070031#include <cutils/log.h>
Rom Lemarchand838ef642013-01-24 15:14:41 -080032#include <logwrap/logwrap.h>
Jeff Sharkey8e188ed2012-07-12 18:32:03 -070033
Narayan Kamatha5ace892017-01-06 15:10:02 +000034#include "Controllers.h"
Robert Greenwaltc4621772012-01-31 12:46:45 -080035#include "NetdConstants.h"
Narayan Kamatha5ace892017-01-06 15:10:02 +000036#include "IptablesRestoreController.h"
Robert Greenwaltc4621772012-01-31 12:46:45 -080037
Ben Schwartze7601812017-04-28 16:38:29 -040038const size_t SHA256_SIZE = EVP_MD_size(EVP_sha256());
39
Robert Greenwaltc4621772012-01-31 12:46:45 -080040const char * const OEM_SCRIPT_PATH = "/system/bin/oem-iptables-init.sh";
41const char * const IPTABLES_PATH = "/system/bin/iptables";
JP Abgrall0031cea2012-04-17 16:38:23 -070042const char * const IP6TABLES_PATH = "/system/bin/ip6tables";
Robert Greenwaltc4621772012-01-31 12:46:45 -080043const char * const TC_PATH = "/system/bin/tc";
44const char * const IP_PATH = "/system/bin/ip";
45const char * const ADD = "add";
46const char * const DEL = "del";
Jeff Sharkey8e188ed2012-07-12 18:32:03 -070047
Rom Lemarchand838ef642013-01-24 15:14:41 -080048static void logExecError(const char* argv[], int res, int status) {
Jeff Sharkey8e188ed2012-07-12 18:32:03 -070049 const char** argp = argv;
50 std::string args = "";
51 while (*argp) {
52 args += *argp;
53 args += ' ';
54 argp++;
55 }
Rom Lemarchand838ef642013-01-24 15:14:41 -080056 ALOGE("exec() res=%d, status=%d for %s", res, status, args.c_str());
57}
58
59static int execIptablesCommand(int argc, const char *argv[], bool silent) {
60 int res;
61 int status;
62
63 res = android_fork_execvp(argc, (char **)argv, &status, false,
64 !silent);
65 if (res || !WIFEXITED(status) || WEXITSTATUS(status)) {
66 if (!silent) {
67 logExecError(argv, res, status);
68 }
69 if (res)
70 return res;
71 if (!WIFEXITED(status))
72 return ECHILD;
73 }
74 return WEXITSTATUS(status);
Jeff Sharkey8e188ed2012-07-12 18:32:03 -070075}
76
77static int execIptables(IptablesTarget target, bool silent, va_list args) {
78 /* Read arguments from incoming va_list; we expect the list to be NULL terminated. */
79 std::list<const char*> argsList;
80 argsList.push_back(NULL);
81 const char* arg;
Amith Yamasani390e4ea2015-04-25 19:08:57 -070082
83 // Wait to avoid failure due to another process holding the lock
84 argsList.push_back("-w");
85
Jeff Sharkey8e188ed2012-07-12 18:32:03 -070086 do {
87 arg = va_arg(args, const char *);
88 argsList.push_back(arg);
89 } while (arg);
90
91 int i = 0;
92 const char* argv[argsList.size()];
93 std::list<const char*>::iterator it;
94 for (it = argsList.begin(); it != argsList.end(); it++, i++) {
95 argv[i] = *it;
96 }
97
98 int res = 0;
99 if (target == V4 || target == V4V6) {
100 argv[0] = IPTABLES_PATH;
Rom Lemarchand838ef642013-01-24 15:14:41 -0800101 res |= execIptablesCommand(argsList.size(), argv, silent);
Jeff Sharkey8e188ed2012-07-12 18:32:03 -0700102 }
103 if (target == V6 || target == V4V6) {
104 argv[0] = IP6TABLES_PATH;
Rom Lemarchand838ef642013-01-24 15:14:41 -0800105 res |= execIptablesCommand(argsList.size(), argv, silent);
Jeff Sharkey8e188ed2012-07-12 18:32:03 -0700106 }
107 return res;
108}
109
110int execIptables(IptablesTarget target, ...) {
111 va_list args;
112 va_start(args, target);
113 int res = execIptables(target, false, args);
114 va_end(args);
115 return res;
116}
117
118int execIptablesSilently(IptablesTarget target, ...) {
119 va_list args;
120 va_start(args, target);
121 int res = execIptables(target, true, args);
122 va_end(args);
123 return res;
124}
Lorenzo Colitti70afde62013-03-04 17:58:40 +0900125
Lorenzo Colitticd283772017-01-31 19:00:49 +0900126int execIptablesRestoreWithOutput(IptablesTarget target, const std::string& commands,
127 std::string *output) {
128 return android::net::gCtls->iptablesRestoreCtrl.execute(target, commands, output);
129}
130
Lorenzo Colitti89faa342016-02-26 11:38:47 +0900131int execIptablesRestore(IptablesTarget target, const std::string& commands) {
Lorenzo Colitticd283772017-01-31 19:00:49 +0900132 return execIptablesRestoreWithOutput(target, commands, nullptr);
Lorenzo Colitti89faa342016-02-26 11:38:47 +0900133}
134
Lorenzo Colittic1306ea2017-03-27 05:52:31 +0900135int execIptablesRestoreCommand(IptablesTarget target, const std::string& table,
136 const std::string& command, std::string *output) {
137 std::string fullCmd = android::base::StringPrintf("*%s\n%s\nCOMMIT\n", table.c_str(),
138 command.c_str());
139 return execIptablesRestoreWithOutput(target, fullCmd, output);
140}
141
JP Abgrall69261cb2014-06-19 18:35:24 -0700142/*
143 * Check an interface name for plausibility. This should e.g. help against
144 * directory traversal.
145 */
Joel Scherpelzbcad6612017-05-30 10:55:11 +0900146bool isIfaceName(const std::string& name) {
JP Abgrall69261cb2014-06-19 18:35:24 -0700147 size_t i;
Joel Scherpelzbcad6612017-05-30 10:55:11 +0900148 if ((name.empty()) || (name.size() > IFNAMSIZ)) {
JP Abgrall69261cb2014-06-19 18:35:24 -0700149 return false;
150 }
151
152 /* First character must be alphanumeric */
153 if (!isalnum(name[0])) {
154 return false;
155 }
156
Joel Scherpelzbcad6612017-05-30 10:55:11 +0900157 for (i = 1; i < name.size(); i++) {
JP Abgrall69261cb2014-06-19 18:35:24 -0700158 if (!isalnum(name[i]) && (name[i] != '_') && (name[i] != '-') && (name[i] != ':')) {
159 return false;
160 }
161 }
162
163 return true;
164}
Lorenzo Colittiba25df92014-06-18 00:22:17 +0900165
166int parsePrefix(const char *prefix, uint8_t *family, void *address, int size, uint8_t *prefixlen) {
167 if (!prefix || !family || !address || !prefixlen) {
168 return -EFAULT;
169 }
170
171 // Find the '/' separating address from prefix length.
172 const char *slash = strchr(prefix, '/');
173 const char *prefixlenString = slash + 1;
174 if (!slash || !*prefixlenString)
175 return -EINVAL;
176
177 // Convert the prefix length to a uint8_t.
178 char *endptr;
179 unsigned templen;
180 templen = strtoul(prefixlenString, &endptr, 10);
181 if (*endptr || templen > 255) {
182 return -EINVAL;
183 }
184 *prefixlen = templen;
185
186 // Copy the address part of the prefix to a local buffer. We have to copy
187 // because inet_pton and getaddrinfo operate on null-terminated address
188 // strings, but prefix is const and has '/' after the address.
189 std::string addressString(prefix, slash - prefix);
190
191 // Parse the address.
192 addrinfo *res;
193 addrinfo hints = {
194 .ai_flags = AI_NUMERICHOST,
195 };
196 int ret = getaddrinfo(addressString.c_str(), NULL, &hints, &res);
197 if (ret || !res) {
198 return -EINVAL; // getaddrinfo return values are not errno values.
199 }
200
201 // Convert the address string to raw address bytes.
202 void *rawAddress;
203 int rawLength;
204 switch (res[0].ai_family) {
205 case AF_INET: {
206 if (*prefixlen > 32) {
207 return -EINVAL;
208 }
209 sockaddr_in *sin = (sockaddr_in *) res[0].ai_addr;
210 rawAddress = &sin->sin_addr;
211 rawLength = 4;
212 break;
213 }
214 case AF_INET6: {
215 if (*prefixlen > 128) {
216 return -EINVAL;
217 }
218 sockaddr_in6 *sin6 = (sockaddr_in6 *) res[0].ai_addr;
219 rawAddress = &sin6->sin6_addr;
220 rawLength = 16;
221 break;
222 }
223 default: {
224 freeaddrinfo(res);
225 return -EAFNOSUPPORT;
226 }
227 }
228
229 if (rawLength > size) {
230 freeaddrinfo(res);
231 return -ENOSPC;
232 }
233
234 *family = res[0].ai_family;
235 memcpy(address, rawAddress, rawLength);
236 freeaddrinfo(res);
237
238 return rawLength;
239}
Lorenzo Colitti839d7d62017-04-03 15:37:19 +0900240
241void blockSigpipe() {
242 sigset_t mask;
243
244 sigemptyset(&mask);
245 sigaddset(&mask, SIGPIPE);
246 if (sigprocmask(SIG_BLOCK, &mask, NULL) != 0)
247 ALOGW("WARNING: SIGPIPE not blocked\n");
248}