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++) { |
JP Abgrall | 69261cb | 2014-06-19 18:35:24 -0700 | [diff] [blame] | 69 | if (!isalnum(name[i]) && (name[i] != '_') && (name[i] != '-') && (name[i] != ':')) { |
| 70 | return false; |
| 71 | } |
| 72 | } |
| 73 | |
| 74 | return true; |
| 75 | } |
Lorenzo Colitti | ba25df9 | 2014-06-18 00:22:17 +0900 | [diff] [blame] | 76 | |
cjybyjk | 7fd8535 | 2021-01-22 17:12:21 +0800 | [diff] [blame] | 77 | /* |
| 78 | * Check an MAC address for plausibility. This should e.g. help against |
| 79 | * directory traversal. |
| 80 | */ |
| 81 | bool isMACAddress(const std::string& mac) { |
| 82 | size_t i; |
| 83 | if ((mac.empty()) || (mac.size() != 17 /* strlen("aa:bb:cc:dd:ee:ff") == 17 */)) { |
| 84 | return false; |
| 85 | } |
| 86 | |
| 87 | for (i = 0; i < mac.size(); i+=3) { |
| 88 | if (!isxdigit(mac[i]) || !isxdigit(mac[i+1]) || (mac[i+2] != ':' && mac[i+2] != 0)) { |
| 89 | return false; |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | return true; |
| 94 | } |
| 95 | |
Lorenzo Colitti | ba25df9 | 2014-06-18 00:22:17 +0900 | [diff] [blame] | 96 | int parsePrefix(const char *prefix, uint8_t *family, void *address, int size, uint8_t *prefixlen) { |
| 97 | if (!prefix || !family || !address || !prefixlen) { |
| 98 | return -EFAULT; |
| 99 | } |
| 100 | |
| 101 | // Find the '/' separating address from prefix length. |
| 102 | const char *slash = strchr(prefix, '/'); |
| 103 | const char *prefixlenString = slash + 1; |
| 104 | if (!slash || !*prefixlenString) |
| 105 | return -EINVAL; |
| 106 | |
| 107 | // Convert the prefix length to a uint8_t. |
| 108 | char *endptr; |
| 109 | unsigned templen; |
| 110 | templen = strtoul(prefixlenString, &endptr, 10); |
| 111 | if (*endptr || templen > 255) { |
| 112 | return -EINVAL; |
| 113 | } |
| 114 | *prefixlen = templen; |
| 115 | |
| 116 | // Copy the address part of the prefix to a local buffer. We have to copy |
| 117 | // because inet_pton and getaddrinfo operate on null-terminated address |
| 118 | // strings, but prefix is const and has '/' after the address. |
| 119 | std::string addressString(prefix, slash - prefix); |
| 120 | |
| 121 | // Parse the address. |
| 122 | addrinfo *res; |
| 123 | addrinfo hints = { |
| 124 | .ai_flags = AI_NUMERICHOST, |
| 125 | }; |
Yi Kong | bdfd57e | 2018-07-25 13:26:10 -0700 | [diff] [blame] | 126 | int ret = getaddrinfo(addressString.c_str(), nullptr, &hints, &res); |
Lorenzo Colitti | ba25df9 | 2014-06-18 00:22:17 +0900 | [diff] [blame] | 127 | if (ret || !res) { |
| 128 | return -EINVAL; // getaddrinfo return values are not errno values. |
| 129 | } |
| 130 | |
| 131 | // Convert the address string to raw address bytes. |
| 132 | void *rawAddress; |
| 133 | int rawLength; |
| 134 | switch (res[0].ai_family) { |
| 135 | case AF_INET: { |
| 136 | if (*prefixlen > 32) { |
| 137 | return -EINVAL; |
| 138 | } |
| 139 | sockaddr_in *sin = (sockaddr_in *) res[0].ai_addr; |
| 140 | rawAddress = &sin->sin_addr; |
| 141 | rawLength = 4; |
| 142 | break; |
| 143 | } |
| 144 | case AF_INET6: { |
| 145 | if (*prefixlen > 128) { |
| 146 | return -EINVAL; |
| 147 | } |
| 148 | sockaddr_in6 *sin6 = (sockaddr_in6 *) res[0].ai_addr; |
| 149 | rawAddress = &sin6->sin6_addr; |
| 150 | rawLength = 16; |
| 151 | break; |
| 152 | } |
| 153 | default: { |
| 154 | freeaddrinfo(res); |
| 155 | return -EAFNOSUPPORT; |
| 156 | } |
| 157 | } |
| 158 | |
| 159 | if (rawLength > size) { |
| 160 | freeaddrinfo(res); |
| 161 | return -ENOSPC; |
| 162 | } |
| 163 | |
| 164 | *family = res[0].ai_family; |
| 165 | memcpy(address, rawAddress, rawLength); |
| 166 | freeaddrinfo(res); |
| 167 | |
| 168 | return rawLength; |
| 169 | } |
Lorenzo Colitti | 839d7d6 | 2017-04-03 15:37:19 +0900 | [diff] [blame] | 170 | |
| 171 | void blockSigpipe() { |
| 172 | sigset_t mask; |
| 173 | |
| 174 | sigemptyset(&mask); |
| 175 | sigaddset(&mask, SIGPIPE); |
Yi Kong | bdfd57e | 2018-07-25 13:26:10 -0700 | [diff] [blame] | 176 | if (sigprocmask(SIG_BLOCK, &mask, nullptr) != 0) |
Lorenzo Colitti | 839d7d6 | 2017-04-03 15:37:19 +0900 | [diff] [blame] | 177 | ALOGW("WARNING: SIGPIPE not blocked\n"); |
| 178 | } |
Lorenzo Colitti | 548bbd4 | 2017-08-28 23:05:12 +0900 | [diff] [blame] | 179 | |
| 180 | void setCloseOnExec(const char *sock) { |
| 181 | int fd = android_get_control_socket(sock); |
| 182 | int flags = fcntl(fd, F_GETFD, 0); |
| 183 | if (flags == -1) { |
| 184 | ALOGE("Can't get fd flags for control socket %s", sock); |
| 185 | flags = 0; |
| 186 | } |
| 187 | flags |= FD_CLOEXEC; |
| 188 | if (fcntl(fd, F_SETFD, flags) == -1) { |
| 189 | ALOGE("Can't set control socket %s to FD_CLOEXEC", sock); |
| 190 | } |
| 191 | } |