/* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <ctype.h> #include <errno.h> #include <fcntl.h> #include <netdb.h> #include <net/if.h> #include <netinet/in.h> #include <openssl/ssl.h> #include <stdlib.h> #include <string.h> #include <sys/wait.h> #define LOG_TAG "Netd" #include <android-base/stringprintf.h> #include <cutils/log.h> #include <cutils/sockets.h> #include <logwrap/logwrap.h> #include "Controllers.h" #include "NetdConstants.h" #include "IptablesRestoreController.h" const size_t SHA256_SIZE = EVP_MD_size(EVP_sha256()); const char * const OEM_SCRIPT_PATH = "/system/bin/oem-iptables-init.sh"; const char * const ADD = "add"; const char * const DEL = "del"; int execIptablesRestoreWithOutput(IptablesTarget target, const std::string& commands, std::string *output) { return android::net::gCtls->iptablesRestoreCtrl.execute(target, commands, output); } int execIptablesRestore(IptablesTarget target, const std::string& commands) { return execIptablesRestoreWithOutput(target, commands, nullptr); } int execIptablesRestoreCommand(IptablesTarget target, const std::string& table, const std::string& command, std::string *output) { std::string fullCmd = android::base::StringPrintf("*%s\n%s\nCOMMIT\n", table.c_str(), command.c_str()); return execIptablesRestoreWithOutput(target, fullCmd, output); } /* * Check an interface name for plausibility. This should e.g. help against * directory traversal. */ bool isIfaceName(const std::string& name) { size_t i; if ((name.empty()) || (name.size() > IFNAMSIZ)) { return false; } /* First character must be alphanumeric */ if (!isalnum(name[0])) { return false; } for (i = 1; i < name.size(); i++) { if (!isalnum(name[i]) && (name[i] != '_') && (name[i] != '-') && (name[i] != ':')) { return false; } } return true; } int parsePrefix(const char *prefix, uint8_t *family, void *address, int size, uint8_t *prefixlen) { if (!prefix || !family || !address || !prefixlen) { return -EFAULT; } // Find the '/' separating address from prefix length. const char *slash = strchr(prefix, '/'); const char *prefixlenString = slash + 1; if (!slash || !*prefixlenString) return -EINVAL; // Convert the prefix length to a uint8_t. char *endptr; unsigned templen; templen = strtoul(prefixlenString, &endptr, 10); if (*endptr || templen > 255) { return -EINVAL; } *prefixlen = templen; // Copy the address part of the prefix to a local buffer. We have to copy // because inet_pton and getaddrinfo operate on null-terminated address // strings, but prefix is const and has '/' after the address. std::string addressString(prefix, slash - prefix); // Parse the address. addrinfo *res; addrinfo hints = { .ai_flags = AI_NUMERICHOST, }; int ret = getaddrinfo(addressString.c_str(), NULL, &hints, &res); if (ret || !res) { return -EINVAL; // getaddrinfo return values are not errno values. } // Convert the address string to raw address bytes. void *rawAddress; int rawLength; switch (res[0].ai_family) { case AF_INET: { if (*prefixlen > 32) { return -EINVAL; } sockaddr_in *sin = (sockaddr_in *) res[0].ai_addr; rawAddress = &sin->sin_addr; rawLength = 4; break; } case AF_INET6: { if (*prefixlen > 128) { return -EINVAL; } sockaddr_in6 *sin6 = (sockaddr_in6 *) res[0].ai_addr; rawAddress = &sin6->sin6_addr; rawLength = 16; break; } default: { freeaddrinfo(res); return -EAFNOSUPPORT; } } if (rawLength > size) { freeaddrinfo(res); return -ENOSPC; } *family = res[0].ai_family; memcpy(address, rawAddress, rawLength); freeaddrinfo(res); return rawLength; } void blockSigpipe() { sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGPIPE); if (sigprocmask(SIG_BLOCK, &mask, NULL) != 0) ALOGW("WARNING: SIGPIPE not blocked\n"); } void setCloseOnExec(const char *sock) { int fd = android_get_control_socket(sock); int flags = fcntl(fd, F_GETFD, 0); if (flags == -1) { ALOGE("Can't get fd flags for control socket %s", sock); flags = 0; } flags |= FD_CLOEXEC; if (fcntl(fd, F_SETFD, flags) == -1) { ALOGE("Can't set control socket %s to FD_CLOEXEC", sock); } }