/*
 * 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 <stdlib.h>
#include <string.h>
#include <sys/wait.h>

#define LOG_TAG "Netd"

#include <android-base/stringprintf.h>
#include <cutils/sockets.h>
#include <log/log.h>

#include "Controllers.h"
#include "NetdConstants.h"
#include "IptablesRestoreController.h"

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] != ':') && (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(), nullptr, &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, nullptr) != 0) ALOGW("WARNING: SIGPIPE not blocked");
}

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);
    }
}

// SIGTERM with timeout first, if fail, SIGKILL
void stopProcess(int pid, const char* processName) {
    int err = kill(pid, SIGTERM);
    if (err) {
        err = errno;
    }
    if (err == ESRCH) {
        // This means that someone else inside netd called this helper function,
        // which is a programming error. There's no point in calling waitpid() here since we
        // know that the process is gone.
        ALOGE("%s child process %d unexpectedly disappeared", processName, pid);
        return;
    }
    if (err) {
        ALOGE("Error killing %s child process %d: %s", processName, pid, strerror(err));
    }
    int status = 0;
    int ret = 0;
    for (int count = 0; ret == 0 && count < 50; count++) {
        usleep(100000); // sleep 0.1s to wait for process stop.
        ret = waitpid(pid, &status, WNOHANG);
    }
    if (ret == 0) {
        ALOGE("Failed to SIGTERM %s pid=%d, try SIGKILL", processName, pid);
        kill(pid, SIGKILL);
        ret = waitpid(pid, &status, 0);
    }
    if (ret == -1) {
        ALOGE("Error waiting for %s child process %d: %s", processName, pid, strerror(errno));
    } else {
        ALOGD("%s process %d terminated status=%d", processName, pid, status);
    }
}
