/*
 * 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 <dirent.h>
#include <errno.h>
#include <malloc.h>
#include <net/if.h>
#include <sys/socket.h>

#include <functional>

#define LOG_TAG "InterfaceController"
#include <android-base/file.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <cutils/log.h>
#include <logwrap/logwrap.h>
#include <netutils/ifc.h>

#include <android/net/INetd.h>
#include <netdutils/Misc.h>
#include <netdutils/Slice.h>
#include <netdutils/Syscalls.h>

#include "InterfaceController.h"
#include "RouteController.h"

using android::base::ReadFileToString;
using android::base::StringPrintf;
using android::base::WriteStringToFile;
using android::net::INetd;
using android::net::RouteController;
using android::netdutils::isOk;
using android::netdutils::Status;
using android::netdutils::StatusOr;
using android::netdutils::makeSlice;
using android::netdutils::sSyscalls;
using android::netdutils::status::ok;
using android::netdutils::statusFromErrno;
using android::netdutils::toString;

namespace {

const char ipv6_proc_path[] = "/proc/sys/net/ipv6/conf";

const char ipv4_neigh_conf_dir[] = "/proc/sys/net/ipv4/neigh";

const char ipv6_neigh_conf_dir[] = "/proc/sys/net/ipv6/neigh";

const char proc_net_path[] = "/proc/sys/net";
const char sys_net_path[] = "/sys/class/net";

constexpr int kRouteInfoMinPrefixLen = 48;

// RFC 7421 prefix length.
constexpr int kRouteInfoMaxPrefixLen = 64;

// Property used to persist RFC 7217 stable secret. Protected by SELinux policy.
const char kStableSecretProperty[] = "persist.netd.stable_secret";

// RFC 7217 stable secret on linux is formatted as an IPv6 address.
// This function uses 128 bits of high quality entropy to generate an
// address for this purpose. This function should be not be called
// frequently.
StatusOr<std::string> randomIPv6Address() {
    in6_addr addr = {};
    const auto& sys = sSyscalls.get();
    ASSIGN_OR_RETURN(auto fd, sys.open("/dev/random", O_RDONLY));
    RETURN_IF_NOT_OK(sys.read(fd, makeSlice(addr)));
    return toString(addr);
}

inline bool isNormalPathComponent(const char *component) {
    return (strcmp(component, ".") != 0) &&
           (strcmp(component, "..") != 0) &&
           (strchr(component, '/') == nullptr);
}

inline bool isAddressFamilyPathComponent(const char *component) {
    return strcmp(component, "ipv4") == 0 || strcmp(component, "ipv6") == 0;
}

inline bool isInterfaceName(const char *name) {
    return isNormalPathComponent(name) &&
           (strcmp(name, "default") != 0) &&
           (strcmp(name, "all") != 0);
}

int writeValueToPath(
        const char* dirname, const char* subdirname, const char* basename,
        const char* value) {
    std::string path(StringPrintf("%s/%s/%s", dirname, subdirname, basename));
    return WriteStringToFile(value, path) ? 0 : -1;
}

// Run @fn on each interface as well as 'default' in the path @dirname.
void forEachInterface(const std::string& dirname,
                      std::function<void(const std::string& path, const std::string& iface)> fn) {
    // Run on default, which controls the behavior of any interfaces that are created in the future.
    fn(dirname, "default");
    DIR* dir = opendir(dirname.c_str());
    if (!dir) {
        ALOGE("Can't list %s: %s", dirname.c_str(), strerror(errno));
        return;
    }
    while (true) {
        const dirent *ent = readdir(dir);
        if (!ent) {
            break;
        }
        if ((ent->d_type != DT_DIR) || !isInterfaceName(ent->d_name)) {
            continue;
        }
        fn(dirname, ent->d_name);
    }
    closedir(dir);
}

void setOnAllInterfaces(const char* dirname, const char* basename, const char* value) {
    auto fn = [basename, value](const std::string& path, const std::string& iface) {
        writeValueToPath(path.c_str(), iface.c_str(), basename, value);
    };
    forEachInterface(dirname, fn);
}

void setIPv6UseOutgoingInterfaceAddrsOnly(const char *value) {
    setOnAllInterfaces(ipv6_proc_path, "use_oif_addrs_only", value);
}

std::string getParameterPathname(
        const char *family, const char *which, const char *interface, const char *parameter) {
    if (!isAddressFamilyPathComponent(family)) {
        errno = EAFNOSUPPORT;
        return "";
    } else if (!isNormalPathComponent(which) ||
               !isInterfaceName(interface) ||
               !isNormalPathComponent(parameter)) {
        errno = EINVAL;
        return "";
    }

    return StringPrintf("%s/%s/%s/%s/%s", proc_net_path, family, which, interface, parameter);
}

void setAcceptIPv6RIO(int min, int max) {
    auto fn = [min, max](const std::string& prefix, const std::string& iface) {
        int rv = writeValueToPath(prefix.c_str(), iface.c_str(), "accept_ra_rt_info_min_plen",
                                  std::to_string(min).c_str());
        if (rv != 0) {
            // Only update max_plen if the write to min_plen succeeded. This ordering will prevent
            // RIOs from being accepted unless both min and max are written successfully.
            return;
        }
        writeValueToPath(prefix.c_str(), iface.c_str(), "accept_ra_rt_info_max_plen",
                         std::to_string(max).c_str());
    };
    forEachInterface(ipv6_proc_path, fn);
}

// Ideally this function would return StatusOr<std::string>, however
// there is no safe value for dflt that will always differ from the
// stored property. Bugs code could conceivably end up persisting the
// reserved value resulting in surprising behavior.
std::string getProperty(const std::string& key, const std::string& dflt) {
    return android::base::GetProperty(key, dflt);
};

Status setProperty(const std::string& key, const std::string& val) {
    // SetProperty does not dependably set errno to a meaningful value. Use our own error code so
    // callers don't get confused.
    return android::base::SetProperty(key, val)
        ? ok
        : statusFromErrno(EREMOTEIO, "SetProperty failed, see libc logs");
};


}  // namespace

android::netdutils::Status InterfaceController::enableStablePrivacyAddresses(
        const std::string& iface, GetPropertyFn getProperty, SetPropertyFn setProperty) {
    const auto& sys = sSyscalls.get();
    const std::string procTarget = std::string(ipv6_proc_path) + "/" + iface + "/stable_secret";
    auto procFd = sys.open(procTarget, O_CLOEXEC | O_WRONLY);

    // Devices with old kernels (typically < 4.4) don't support
    // RFC 7217 stable privacy addresses.
    if (equalToErrno(procFd, ENOENT)) {
        return statusFromErrno(EOPNOTSUPP,
                               "Failed to open stable_secret. Assuming unsupported kernel version");
    }

    // If stable_secret exists but we can't open it, something strange is going on.
    RETURN_IF_NOT_OK(procFd);

    const char kUninitialized[] = "uninitialized";
    const auto oldSecret = getProperty(kStableSecretProperty, kUninitialized);
    std::string secret = oldSecret;

    // Generate a new secret if no persistent property existed.
    if (oldSecret == kUninitialized) {
        ASSIGN_OR_RETURN(secret, randomIPv6Address());
    }

    // Ask the OS to generate SLAAC addresses on iface using secret.
    RETURN_IF_NOT_OK(sys.write(procFd.value(), makeSlice(secret)));

    // Don't persist an existing secret.
    if (oldSecret != kUninitialized) {
        return ok;
    }

    return setProperty(kStableSecretProperty, secret);
}

void InterfaceController::initializeAll() {
    // Initial IPv6 settings.
    // By default, accept_ra is set to 1 (accept RAs unless forwarding is on) on all interfaces.
    // This causes RAs to work or not work based on whether forwarding is on, and causes routes
    // learned from RAs to go away when forwarding is turned on. Make this behaviour predictable
    // by always setting accept_ra to 2.
    setAcceptRA("2");

    // Accept RIOs with prefix length in the closed interval [48, 64].
    setAcceptIPv6RIO(kRouteInfoMinPrefixLen, kRouteInfoMaxPrefixLen);

    setAcceptRARouteTable(-RouteController::ROUTE_TABLE_OFFSET_FROM_INDEX);

    // Enable optimistic DAD for IPv6 addresses on all interfaces.
    setIPv6OptimisticMode("1");

    // Reduce the ARP/ND base reachable time from the default (30sec) to 15sec.
    setBaseReachableTimeMs(15 * 1000);

    // When sending traffic via a given interface use only addresses configured
       // on that interface as possible source addresses.
    setIPv6UseOutgoingInterfaceAddrsOnly("1");
}

int InterfaceController::setEnableIPv6(const char *interface, const int on) {
    if (!isIfaceName(interface)) {
        errno = ENOENT;
        return -1;
    }
    // When disable_ipv6 changes from 1 to 0, the kernel starts autoconf.
    // When disable_ipv6 changes from 0 to 1, the kernel clears all autoconf
    // addresses and routes and disables IPv6 on the interface.
    const char *disable_ipv6 = on ? "0" : "1";
    return writeValueToPath(ipv6_proc_path, interface, "disable_ipv6", disable_ipv6);
}

// Changes to addrGenMode will not fully take effect until the next
// time disable_ipv6 transitions from 1 to 0.
Status InterfaceController::setIPv6AddrGenMode(const std::string& interface, int mode) {
    if (!isIfaceName(interface)) {
        return statusFromErrno(ENOENT, "invalid iface name: " + interface);
    }

    switch (mode) {
        case INetd::IPV6_ADDR_GEN_MODE_EUI64:
            // Ignore return value. If /proc/.../stable_secret is
            // missing we're probably in EUI64 mode already.
            writeValueToPath(ipv6_proc_path, interface.c_str(), "stable_secret", "");
            break;
        case INetd::IPV6_ADDR_GEN_MODE_STABLE_PRIVACY: {
            return enableStablePrivacyAddresses(interface, getProperty, setProperty);
        }
        case INetd::IPV6_ADDR_GEN_MODE_NONE:
        case INetd::IPV6_ADDR_GEN_MODE_RANDOM:
        default:
            return statusFromErrno(EOPNOTSUPP, "unsupported addrGenMode");
    }

    return ok;
}

int InterfaceController::setAcceptIPv6Ra(const char *interface, const int on) {
    if (!isIfaceName(interface)) {
        errno = ENOENT;
        return -1;
    }
    // Because forwarding can be enabled even when tethering is off, we always
    // use mode "2" (accept RAs, even if forwarding is enabled).
    const char *accept_ra = on ? "2" : "0";
    return writeValueToPath(ipv6_proc_path, interface, "accept_ra", accept_ra);
}

int InterfaceController::setAcceptIPv6Dad(const char *interface, const int on) {
    if (!isIfaceName(interface)) {
        errno = ENOENT;
        return -1;
    }
    const char *accept_dad = on ? "1" : "0";
    return writeValueToPath(ipv6_proc_path, interface, "accept_dad", accept_dad);
}

int InterfaceController::setIPv6DadTransmits(const char *interface, const char *value) {
    if (!isIfaceName(interface)) {
        errno = ENOENT;
        return -1;
    }
    return writeValueToPath(ipv6_proc_path, interface, "dad_transmits", value);
}

int InterfaceController::setIPv6PrivacyExtensions(const char *interface, const int on) {
    if (!isIfaceName(interface)) {
        errno = ENOENT;
        return -1;
    }
    // 0: disable IPv6 privacy addresses
    // 2: enable IPv6 privacy addresses and prefer them over non-privacy ones.
    return writeValueToPath(ipv6_proc_path, interface, "use_tempaddr", on ? "2" : "0");
}

void InterfaceController::setAcceptRA(const char *value) {
    setOnAllInterfaces(ipv6_proc_path, "accept_ra", value);
}

// |tableOrOffset| is interpreted as:
//     If == 0: default. Routes go into RT6_TABLE_MAIN.
//     If > 0: user set. Routes go into the specified table.
//     If < 0: automatic. The absolute value is intepreted as an offset and added to the interface
//             ID to get the table. If it's set to -1000, routes from interface ID 5 will go into
//             table 1005, etc.
void InterfaceController::setAcceptRARouteTable(int tableOrOffset) {
    std::string value(StringPrintf("%d", tableOrOffset));
    setOnAllInterfaces(ipv6_proc_path, "accept_ra_rt_table", value.c_str());
}

int InterfaceController::setMtu(const char *interface, const char *mtu)
{
    if (!isIfaceName(interface)) {
        errno = ENOENT;
        return -1;
    }
    return writeValueToPath(sys_net_path, interface, "mtu", mtu);
}

int InterfaceController::addAddress(const char *interface,
        const char *addrString, int prefixLength) {
    return ifc_add_address(interface, addrString, prefixLength);
}

int InterfaceController::delAddress(const char *interface,
        const char *addrString, int prefixLength) {
    return ifc_del_address(interface, addrString, prefixLength);
}

int InterfaceController::getParameter(
        const char *family, const char *which, const char *interface, const char *parameter,
        std::string *value) {
    const std::string path(getParameterPathname(family, which, interface, parameter));
    if (path.empty()) {
        return -errno;
    }
    return ReadFileToString(path, value) ? 0 : -errno;
}

int InterfaceController::setParameter(
        const char *family, const char *which, const char *interface, const char *parameter,
        const char *value) {
    const std::string path(getParameterPathname(family, which, interface, parameter));
    if (path.empty()) {
        return -errno;
    }
    return WriteStringToFile(value, path) ? 0 : -errno;
}

void InterfaceController::setBaseReachableTimeMs(unsigned int millis) {
    std::string value(StringPrintf("%u", millis));
    setOnAllInterfaces(ipv4_neigh_conf_dir, "base_reachable_time_ms", value.c_str());
    setOnAllInterfaces(ipv6_neigh_conf_dir, "base_reachable_time_ms", value.c_str());
}

void InterfaceController::setIPv6OptimisticMode(const char *value) {
    setOnAllInterfaces(ipv6_proc_path, "optimistic_dad", value);
    setOnAllInterfaces(ipv6_proc_path, "use_optimistic", value);
}

StatusOr<std::vector<std::string>> InterfaceController::getIfaceNames() {
    std::vector<std::string> ifaceNames;
    DIR* d;
    struct dirent* de;

    if (!(d = opendir("/sys/class/net"))) {
        return statusFromErrno(errno, "Cannot open iface directory");
    }
    while ((de = readdir(d))) {
        if (de->d_name[0] == '.') continue;
        ifaceNames.push_back(std::string(de->d_name));
    }
    closedir(d);
    return ifaceNames;
}

StatusOr<std::map<std::string, uint32_t>> InterfaceController::getIfaceList() {
    std::map<std::string, uint32_t> ifacePairs;

    ASSIGN_OR_RETURN(auto ifaceNames, getIfaceNames());

    for (const auto& name : ifaceNames) {
        uint32_t ifaceIndex = if_nametoindex(name.c_str());
        if (ifaceIndex) {
            ifacePairs.insert(std::pair<std::string, uint32_t>(name, ifaceIndex));
        }
    }
    return ifacePairs;
}
