Robert Greenwalt | c462177 | 2012-01-31 12:46:45 -0800 | [diff] [blame] | 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 | |
Dan Albert | aa1be2b | 2015-01-06 09:36:17 -0800 | [diff] [blame] | 17 | #include <ctype.h> |
| 18 | #include <errno.h> |
Lorenzo Colitti | 70afde6 | 2013-03-04 17:58:40 +0900 | [diff] [blame] | 19 | #include <fcntl.h> |
Lorenzo Colitti | ba25df9 | 2014-06-18 00:22:17 +0900 | [diff] [blame] | 20 | #include <netdb.h> |
Dan Albert | aa1be2b | 2015-01-06 09:36:17 -0800 | [diff] [blame] | 21 | #include <net/if.h> |
Lorenzo Colitti | ba25df9 | 2014-06-18 00:22:17 +0900 | [diff] [blame] | 22 | #include <netinet/in.h> |
| 23 | #include <stdlib.h> |
Jeff Sharkey | 8e188ed | 2012-07-12 18:32:03 -0700 | [diff] [blame] | 24 | #include <string.h> |
Rom Lemarchand | 838ef64 | 2013-01-24 15:14:41 -0800 | [diff] [blame] | 25 | #include <sys/wait.h> |
Jeff Sharkey | 8e188ed | 2012-07-12 18:32:03 -0700 | [diff] [blame] | 26 | |
Jeff Sharkey | bec6d04 | 2012-09-06 15:45:56 -0700 | [diff] [blame] | 27 | #define LOG_TAG "Netd" |
| 28 | |
Lorenzo Colitti | c1306ea | 2017-03-27 05:52:31 +0900 | [diff] [blame] | 29 | #include <android-base/stringprintf.h> |
Lorenzo Colitti | 548bbd4 | 2017-08-28 23:05:12 +0900 | [diff] [blame] | 30 | #include <cutils/sockets.h> |
Logan Chien | 3f46148 | 2018-04-23 14:31:32 +0800 | [diff] [blame] | 31 | #include <log/log.h> |
Jeff Sharkey | 8e188ed | 2012-07-12 18:32:03 -0700 | [diff] [blame] | 32 | |
Narayan Kamath | a5ace89 | 2017-01-06 15:10:02 +0000 | [diff] [blame] | 33 | #include "Controllers.h" |
Robert Greenwalt | c462177 | 2012-01-31 12:46:45 -0800 | [diff] [blame] | 34 | #include "NetdConstants.h" |
Narayan Kamath | a5ace89 | 2017-01-06 15:10:02 +0000 | [diff] [blame] | 35 | #include "IptablesRestoreController.h" |
Robert Greenwalt | c462177 | 2012-01-31 12:46:45 -0800 | [diff] [blame] | 36 | |
Lorenzo Colitti | cd28377 | 2017-01-31 19:00:49 +0900 | [diff] [blame] | 37 | int execIptablesRestoreWithOutput(IptablesTarget target, const std::string& commands, |
| 38 | std::string *output) { |
| 39 | return android::net::gCtls->iptablesRestoreCtrl.execute(target, commands, output); |
| 40 | } |
| 41 | |
Lorenzo Colitti | 89faa34 | 2016-02-26 11:38:47 +0900 | [diff] [blame] | 42 | int execIptablesRestore(IptablesTarget target, const std::string& commands) { |
Lorenzo Colitti | cd28377 | 2017-01-31 19:00:49 +0900 | [diff] [blame] | 43 | return execIptablesRestoreWithOutput(target, commands, nullptr); |
Lorenzo Colitti | 89faa34 | 2016-02-26 11:38:47 +0900 | [diff] [blame] | 44 | } |
| 45 | |
Lorenzo Colitti | c1306ea | 2017-03-27 05:52:31 +0900 | [diff] [blame] | 46 | int execIptablesRestoreCommand(IptablesTarget target, const std::string& table, |
| 47 | const std::string& command, std::string *output) { |
| 48 | std::string fullCmd = android::base::StringPrintf("*%s\n%s\nCOMMIT\n", table.c_str(), |
| 49 | command.c_str()); |
| 50 | return execIptablesRestoreWithOutput(target, fullCmd, output); |
| 51 | } |
| 52 | |
JP Abgrall | 69261cb | 2014-06-19 18:35:24 -0700 | [diff] [blame] | 53 | /* |
| 54 | * Check an interface name for plausibility. This should e.g. help against |
| 55 | * directory traversal. |
| 56 | */ |
Joel Scherpelz | bcad661 | 2017-05-30 10:55:11 +0900 | [diff] [blame] | 57 | bool isIfaceName(const std::string& name) { |
JP Abgrall | 69261cb | 2014-06-19 18:35:24 -0700 | [diff] [blame] | 58 | size_t i; |
Joel Scherpelz | bcad661 | 2017-05-30 10:55:11 +0900 | [diff] [blame] | 59 | if ((name.empty()) || (name.size() > IFNAMSIZ)) { |
JP Abgrall | 69261cb | 2014-06-19 18:35:24 -0700 | [diff] [blame] | 60 | return false; |
| 61 | } |
| 62 | |
| 63 | /* First character must be alphanumeric */ |
| 64 | if (!isalnum(name[0])) { |
| 65 | return false; |
| 66 | } |
| 67 | |
Joel Scherpelz | bcad661 | 2017-05-30 10:55:11 +0900 | [diff] [blame] | 68 | for (i = 1; i < name.size(); i++) { |
Pavan Kumar M | 133675e | 2020-09-21 21:29:55 +0530 | [diff] [blame] | 69 | if (!isalnum(name[i]) && (name[i] != '_') && (name[i] != '-') |
| 70 | && (name[i] != ':') && (name[i] != '.')) { |
JP Abgrall | 69261cb | 2014-06-19 18:35:24 -0700 | [diff] [blame] | 71 | return false; |
| 72 | } |
| 73 | } |
| 74 | |
| 75 | return true; |
| 76 | } |
Lorenzo Colitti | ba25df9 | 2014-06-18 00:22:17 +0900 | [diff] [blame] | 77 | |
| 78 | int parsePrefix(const char *prefix, uint8_t *family, void *address, int size, uint8_t *prefixlen) { |
| 79 | if (!prefix || !family || !address || !prefixlen) { |
| 80 | return -EFAULT; |
| 81 | } |
| 82 | |
| 83 | // Find the '/' separating address from prefix length. |
| 84 | const char *slash = strchr(prefix, '/'); |
| 85 | const char *prefixlenString = slash + 1; |
| 86 | if (!slash || !*prefixlenString) |
| 87 | return -EINVAL; |
| 88 | |
| 89 | // Convert the prefix length to a uint8_t. |
| 90 | char *endptr; |
| 91 | unsigned templen; |
| 92 | templen = strtoul(prefixlenString, &endptr, 10); |
| 93 | if (*endptr || templen > 255) { |
| 94 | return -EINVAL; |
| 95 | } |
| 96 | *prefixlen = templen; |
| 97 | |
| 98 | // Copy the address part of the prefix to a local buffer. We have to copy |
| 99 | // because inet_pton and getaddrinfo operate on null-terminated address |
| 100 | // strings, but prefix is const and has '/' after the address. |
| 101 | std::string addressString(prefix, slash - prefix); |
| 102 | |
| 103 | // Parse the address. |
| 104 | addrinfo *res; |
| 105 | addrinfo hints = { |
| 106 | .ai_flags = AI_NUMERICHOST, |
| 107 | }; |
Yi Kong | bdfd57e | 2018-07-25 13:26:10 -0700 | [diff] [blame] | 108 | int ret = getaddrinfo(addressString.c_str(), nullptr, &hints, &res); |
Lorenzo Colitti | ba25df9 | 2014-06-18 00:22:17 +0900 | [diff] [blame] | 109 | if (ret || !res) { |
| 110 | return -EINVAL; // getaddrinfo return values are not errno values. |
| 111 | } |
| 112 | |
| 113 | // Convert the address string to raw address bytes. |
| 114 | void *rawAddress; |
| 115 | int rawLength; |
| 116 | switch (res[0].ai_family) { |
| 117 | case AF_INET: { |
| 118 | if (*prefixlen > 32) { |
| 119 | return -EINVAL; |
| 120 | } |
| 121 | sockaddr_in *sin = (sockaddr_in *) res[0].ai_addr; |
| 122 | rawAddress = &sin->sin_addr; |
| 123 | rawLength = 4; |
| 124 | break; |
| 125 | } |
| 126 | case AF_INET6: { |
| 127 | if (*prefixlen > 128) { |
| 128 | return -EINVAL; |
| 129 | } |
| 130 | sockaddr_in6 *sin6 = (sockaddr_in6 *) res[0].ai_addr; |
| 131 | rawAddress = &sin6->sin6_addr; |
| 132 | rawLength = 16; |
| 133 | break; |
| 134 | } |
| 135 | default: { |
| 136 | freeaddrinfo(res); |
| 137 | return -EAFNOSUPPORT; |
| 138 | } |
| 139 | } |
| 140 | |
| 141 | if (rawLength > size) { |
| 142 | freeaddrinfo(res); |
| 143 | return -ENOSPC; |
| 144 | } |
| 145 | |
| 146 | *family = res[0].ai_family; |
| 147 | memcpy(address, rawAddress, rawLength); |
| 148 | freeaddrinfo(res); |
| 149 | |
| 150 | return rawLength; |
| 151 | } |
Lorenzo Colitti | 839d7d6 | 2017-04-03 15:37:19 +0900 | [diff] [blame] | 152 | |
| 153 | void blockSigpipe() { |
| 154 | sigset_t mask; |
| 155 | |
| 156 | sigemptyset(&mask); |
| 157 | sigaddset(&mask, SIGPIPE); |
Maciej Żenczykowski | 5a58ba3 | 2022-06-17 02:41:23 -0700 | [diff] [blame] | 158 | if (sigprocmask(SIG_BLOCK, &mask, nullptr) != 0) ALOGW("WARNING: SIGPIPE not blocked"); |
Lorenzo Colitti | 839d7d6 | 2017-04-03 15:37:19 +0900 | [diff] [blame] | 159 | } |
Lorenzo Colitti | 548bbd4 | 2017-08-28 23:05:12 +0900 | [diff] [blame] | 160 | |
| 161 | void setCloseOnExec(const char *sock) { |
| 162 | int fd = android_get_control_socket(sock); |
| 163 | int flags = fcntl(fd, F_GETFD, 0); |
| 164 | if (flags == -1) { |
| 165 | ALOGE("Can't get fd flags for control socket %s", sock); |
| 166 | flags = 0; |
| 167 | } |
| 168 | flags |= FD_CLOEXEC; |
| 169 | if (fcntl(fd, F_SETFD, flags) == -1) { |
| 170 | ALOGE("Can't set control socket %s to FD_CLOEXEC", sock); |
| 171 | } |
| 172 | } |
WeiZhang | 4f3dffb | 2021-11-30 00:32:46 -0600 | [diff] [blame] | 173 | |
| 174 | // SIGTERM with timeout first, if fail, SIGKILL |
| 175 | void stopProcess(int pid, const char* processName) { |
| 176 | int err = kill(pid, SIGTERM); |
| 177 | if (err) { |
| 178 | err = errno; |
| 179 | } |
| 180 | if (err == ESRCH) { |
| 181 | // This means that someone else inside netd called this helper function, |
| 182 | // which is a programming error. There's no point in calling waitpid() here since we |
| 183 | // know that the process is gone. |
| 184 | ALOGE("%s child process %d unexpectedly disappeared", processName, pid); |
| 185 | return; |
| 186 | } |
| 187 | if (err) { |
| 188 | ALOGE("Error killing %s child process %d: %s", processName, pid, strerror(err)); |
| 189 | } |
| 190 | int status = 0; |
| 191 | int ret = 0; |
| 192 | for (int count = 0; ret == 0 && count < 50; count++) { |
| 193 | usleep(100000); // sleep 0.1s to wait for process stop. |
| 194 | ret = waitpid(pid, &status, WNOHANG); |
| 195 | } |
| 196 | if (ret == 0) { |
| 197 | ALOGE("Failed to SIGTERM %s pid=%d, try SIGKILL", processName, pid); |
| 198 | kill(pid, SIGKILL); |
| 199 | ret = waitpid(pid, &status, 0); |
| 200 | } |
| 201 | if (ret == -1) { |
| 202 | ALOGE("Error waiting for %s child process %d: %s", processName, pid, strerror(errno)); |
| 203 | } else { |
| 204 | ALOGD("%s process %d terminated status=%d", processName, pid, status); |
| 205 | } |
| 206 | } |