/**
 * Copyright (c) 2016, 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.
 */

#define LOG_TAG "Netd"

#include <cinttypes>
#include <numeric>
#include <set>
#include <string>
#include <tuple>
#include <vector>

#include <android-base/file.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/Status.h>
#include <cutils/properties.h>
#include <log/log.h>
#include <netdutils/DumpWriter.h>
#include <utils/Errors.h>
#include <utils/String16.h>

#include "Controllers.h"
#include "Fwmark.h"
#include "InterfaceController.h"
#include "NetdNativeService.h"
#include "OemNetdListener.h"
#include "Permission.h"
#include "Process.h"
#include "RouteController.h"
#include "SockDiag.h"
#include "UidRanges.h"
#include "android/net/BnNetd.h"
#include "binder_utils/BinderUtil.h"
#include "binder_utils/NetdPermissions.h"
#include "netid_client.h"  // NETID_UNSET

using android::base::StringPrintf;
using android::base::WriteStringToFile;
using android::net::NativeNetworkType;
using android::net::TetherOffloadRuleParcel;
using android::net::TetherStatsParcel;
using android::net::UidRangeParcel;
using android::net::netd::aidl::NativeUidRangeConfig;
using android::netdutils::DumpWriter;
using android::netdutils::ScopedIndent;
using android::os::ParcelFileDescriptor;

namespace android {
namespace net {

namespace {
const char OPT_SHORT[] = "--short";

// The input permissions should be equivalent that this function would return ok if any of them is
// granted.
binder::Status checkAnyPermission(const std::vector<const char*>& permissions) {
    pid_t pid = IPCThreadState::self()->getCallingPid();
    uid_t uid = IPCThreadState::self()->getCallingUid();

    // TODO: Do the pure permission check in this function. Have another method
    // (e.g. checkNetworkStackPermission) to wrap AID_SYSTEM and
    // AID_NETWORK_STACK uid check.
    // If the caller is the system UID, don't check permissions.
    // Otherwise, if the system server's binder thread pool is full, and all the threads are
    // blocked on a thread that's waiting for us to complete, we deadlock. http://b/69389492
    //
    // From a security perspective, there is currently no difference, because:
    // 1. The system server has the NETWORK_STACK permission, which grants access to all the
    //    IPCs in this file.
    // 2. AID_SYSTEM always has all permissions. See ActivityManager#checkComponentPermission.
    if (uid == AID_SYSTEM) {
        return binder::Status::ok();
    }
    // AID_NETWORK_STACK own MAINLINE_NETWORK_STACK permission, don't IPC to system server to check
    // MAINLINE_NETWORK_STACK permission. Cross-process(netd, networkstack and system server)
    // deadlock: http://b/149766727
    if (uid == AID_NETWORK_STACK) {
        for (const char* permission : permissions) {
            if (std::strcmp(permission, PERM_MAINLINE_NETWORK_STACK) == 0) {
                return binder::Status::ok();
            }
        }
    }

    for (const char* permission : permissions) {
        if (checkPermission(String16(permission), pid, uid)) {
            return binder::Status::ok();
        }
    }

    auto err = StringPrintf("UID %d / PID %d does not have any of the following permissions: %s",
                            uid, pid, android::base::Join(permissions, ',').c_str());
    return binder::Status::fromExceptionCode(binder::Status::EX_SECURITY, err.c_str());
}

#define ENFORCE_ANY_PERMISSION(...)                                \
    do {                                                           \
        binder::Status status = checkAnyPermission({__VA_ARGS__}); \
        if (!status.isOk()) {                                      \
            return status;                                         \
        }                                                          \
    } while (0)

#define NETD_LOCKING_RPC(lock, ... /* permissions */) \
    ENFORCE_ANY_PERMISSION(__VA_ARGS__);              \
    std::lock_guard _lock(lock);

#define NETD_BIG_LOCK_RPC(... /* permissions */) NETD_LOCKING_RPC(gBigNetdLock, __VA_ARGS__)

#define RETURN_BINDER_STATUS_IF_NOT_OK(logEntry, res) \
    do {                                              \
        if (!isOk((res))) {                           \
            logErrorStatus((logEntry), (res));        \
            return asBinderStatus((res));             \
        }                                             \
    } while (0)

#define ENFORCE_NETWORK_STACK_PERMISSIONS() \
    ENFORCE_ANY_PERMISSION(PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK)

void logErrorStatus(netdutils::LogEntry& logEntry, const netdutils::Status& status) {
    gLog.log(logEntry.returns(status.code()).withAutomaticDuration());
}

binder::Status asBinderStatus(const netdutils::Status& status) {
    if (isOk(status)) {
        return binder::Status::ok();
    }
    return binder::Status::fromServiceSpecificError(status.code(), status.msg().c_str());
}

template <typename T>
binder::Status asBinderStatus(const base::Result<T> result) {
    if (result.ok()) return binder::Status::ok();

    return binder::Status::fromServiceSpecificError(result.error().code(),
                                                    result.error().message().c_str());
}

inline binder::Status statusFromErrcode(int ret) {
    if (ret) {
        return binder::Status::fromServiceSpecificError(-ret, strerror(-ret));
    }
    return binder::Status::ok();
}

bool contains(const Vector<String16>& words, const String16& word) {
    for (const auto& w : words) {
        if (w == word) return true;
    }

    return false;
}

}  // namespace

NetdNativeService::NetdNativeService() {
    // register log callback to BnNetd::logFunc
    BnNetd::logFunc = [](const auto& log) {
        binderCallLogFn(log, [](const std::string& msg) { gLog.info("%s", msg.c_str()); });
    };
}

status_t NetdNativeService::start() {
    IPCThreadState::self()->disableBackgroundScheduling(true);
    const status_t ret = BinderService<NetdNativeService>::publish();
    if (ret != android::OK) {
        return ret;
    }
    sp<ProcessState> ps(ProcessState::self());
    ps->startThreadPool();
    ps->giveThreadPoolName();

    return android::OK;
}

status_t NetdNativeService::dump(int fd, const Vector<String16> &args) {
    const binder::Status dump_permission = checkAnyPermission({PERM_DUMP});
    if (!dump_permission.isOk()) {
        const String8 msg(dump_permission.toString8());
        write(fd, msg.string(), msg.size());
        return PERMISSION_DENIED;
    }

    // This method does not grab any locks. If individual classes need locking
    // their dump() methods MUST handle locking appropriately.

    DumpWriter dw(fd);

    if (!args.isEmpty() && args[0] == TcpSocketMonitor::DUMP_KEYWORD) {
      dw.blankline();
      gCtls->tcpSocketMonitor.dump(dw);
      dw.blankline();
      return NO_ERROR;
    }

    if (!args.isEmpty() && args[0] == TrafficController::DUMP_KEYWORD) {
        dw.blankline();
        gCtls->trafficCtrl.dump(dw, true);
        dw.blankline();
        return NO_ERROR;
    }

    process::dump(dw);
    dw.blankline();
    gCtls->netCtrl.dump(dw);
    dw.blankline();

    gCtls->trafficCtrl.dump(dw, false);
    dw.blankline();

    gCtls->xfrmCtrl.dump(dw);
    dw.blankline();

    gCtls->clatdCtrl.dump(dw);
    dw.blankline();

    gCtls->tetherCtrl.dump(dw);
    dw.blankline();

    {
        ScopedIndent indentLog(dw);
        if (contains(args, String16(OPT_SHORT))) {
            dw.println("Log: <omitted>");
        } else {
            dw.println("Log:");
            ScopedIndent indentLogEntries(dw);
            gLog.forEachEntry([&dw](const std::string& entry) mutable { dw.println(entry); });
        }
        dw.blankline();
    }

    {
        ScopedIndent indentLog(dw);
        if (contains(args, String16(OPT_SHORT))) {
            dw.println("UnsolicitedLog: <omitted>");
        } else {
            dw.println("UnsolicitedLog:");
            ScopedIndent indentLogEntries(dw);
            gUnsolicitedLog.forEachEntry(
                    [&dw](const std::string& entry) mutable { dw.println(entry); });
        }
        dw.blankline();
    }

    return NO_ERROR;
}

binder::Status NetdNativeService::isAlive(bool *alive) {
    NETD_BIG_LOCK_RPC(PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);

    *alive = true;

    return binder::Status::ok();
}

binder::Status NetdNativeService::firewallReplaceUidChain(const std::string& chainName,
                                                          bool isAllowlist,
                                                          const std::vector<int32_t>& uids,
                                                          bool* ret) {
    NETD_LOCKING_RPC(gCtls->firewallCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    int err = gCtls->firewallCtrl.replaceUidChain(chainName, isAllowlist, uids);
    *ret = (err == 0);
    return binder::Status::ok();
}

binder::Status NetdNativeService::bandwidthEnableDataSaver(bool enable, bool *ret) {
    NETD_LOCKING_RPC(gCtls->bandwidthCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    int err = gCtls->bandwidthCtrl.enableDataSaver(enable);
    *ret = (err == 0);
    return binder::Status::ok();
}

binder::Status NetdNativeService::bandwidthSetInterfaceQuota(const std::string& ifName,
                                                             int64_t bytes) {
    NETD_LOCKING_RPC(gCtls->bandwidthCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    int res = gCtls->bandwidthCtrl.setInterfaceQuota(ifName, bytes);
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::bandwidthRemoveInterfaceQuota(const std::string& ifName) {
    NETD_LOCKING_RPC(gCtls->bandwidthCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    int res = gCtls->bandwidthCtrl.removeInterfaceQuota(ifName);
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::bandwidthSetInterfaceAlert(const std::string& ifName,
                                                             int64_t bytes) {
    NETD_LOCKING_RPC(gCtls->bandwidthCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    int res = gCtls->bandwidthCtrl.setInterfaceAlert(ifName, bytes);
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::bandwidthRemoveInterfaceAlert(const std::string& ifName) {
    NETD_LOCKING_RPC(gCtls->bandwidthCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    int res = gCtls->bandwidthCtrl.removeInterfaceAlert(ifName);
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::bandwidthSetGlobalAlert(int64_t bytes) {
    NETD_LOCKING_RPC(gCtls->bandwidthCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    int res = gCtls->bandwidthCtrl.setGlobalAlert(bytes);
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::bandwidthAddNaughtyApp(int32_t uid) {
    NETD_LOCKING_RPC(gCtls->bandwidthCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    std::vector<uint32_t> appUids = {static_cast<uint32_t>(abs(uid))};
    int res = gCtls->bandwidthCtrl.addNaughtyApps(appUids);
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::bandwidthRemoveNaughtyApp(int32_t uid) {
    NETD_LOCKING_RPC(gCtls->bandwidthCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    std::vector<uint32_t> appUids = {static_cast<uint32_t>(abs(uid))};
    int res = gCtls->bandwidthCtrl.removeNaughtyApps(appUids);
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::bandwidthAddNiceApp(int32_t uid) {
    NETD_LOCKING_RPC(gCtls->bandwidthCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    std::vector<uint32_t> appUids = {static_cast<uint32_t>(abs(uid))};
    int res = gCtls->bandwidthCtrl.addNiceApps(appUids);
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::bandwidthRemoveNiceApp(int32_t uid) {
    NETD_LOCKING_RPC(gCtls->bandwidthCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    std::vector<uint32_t> appUids = {static_cast<uint32_t>(abs(uid))};
    int res = gCtls->bandwidthCtrl.removeNiceApps(appUids);
    return statusFromErrcode(res);
}

// TODO: Remove this function when there are no users. Currently, it is still used by DNS resolver
// tests.
binder::Status NetdNativeService::networkCreatePhysical(int32_t netId, int32_t permission) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    int ret = gCtls->netCtrl.createPhysicalNetwork(netId, convertPermission(permission));
    return statusFromErrcode(ret);
}

// TODO: Remove this function when there are no users. Currently, it is still used by DNS resolver
// tests.
binder::Status NetdNativeService::networkCreateVpn(int32_t netId, bool secure) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    // The value of vpnType does not matter here, because it is not used in AOSP and is only
    // implemented by OEMs. Also, the RPC is going to deprecate. Just pick a value defined in INetd
    // as default.
    int ret = gCtls->netCtrl.createVirtualNetwork(netId, secure, NativeVpnType::LEGACY);
    return statusFromErrcode(ret);
}

binder::Status NetdNativeService::networkCreate(const NativeNetworkConfig& config) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    int ret = -EINVAL;
    if (config.networkType == NativeNetworkType::PHYSICAL) {
        ret = gCtls->netCtrl.createPhysicalNetwork(config.netId,
                                                   convertPermission(config.permission));
    } else if (config.networkType == NativeNetworkType::VIRTUAL) {
        ret = gCtls->netCtrl.createVirtualNetwork(config.netId, config.secure, config.vpnType);
    }
    return statusFromErrcode(ret);
}

binder::Status NetdNativeService::networkDestroy(int32_t netId) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    // NetworkController::destroyNetwork is thread-safe.
    const int ret = gCtls->netCtrl.destroyNetwork(netId);
    return statusFromErrcode(ret);
}

binder::Status NetdNativeService::networkAddInterface(int32_t netId, const std::string& iface) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    int ret = gCtls->netCtrl.addInterfaceToNetwork(netId, iface.c_str());
    return statusFromErrcode(ret);
}

binder::Status NetdNativeService::networkRemoveInterface(int32_t netId, const std::string& iface) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    int ret = gCtls->netCtrl.removeInterfaceFromNetwork(netId, iface.c_str());
    return statusFromErrcode(ret);
}

binder::Status NetdNativeService::networkAddUidRanges(
        int32_t netId, const std::vector<UidRangeParcel>& uidRangeArray) {
    // NetworkController::addUsersToNetwork is thread-safe.
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    int ret = gCtls->netCtrl.addUsersToNetwork(netId, UidRanges(uidRangeArray),
                                               UidRanges::DEFAULT_SUB_PRIORITY);
    return statusFromErrcode(ret);
}

binder::Status NetdNativeService::networkRemoveUidRanges(
        int32_t netId, const std::vector<UidRangeParcel>& uidRangeArray) {
    // NetworkController::removeUsersFromNetwork is thread-safe.
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    int ret = gCtls->netCtrl.removeUsersFromNetwork(netId, UidRanges(uidRangeArray),
                                                    UidRanges::DEFAULT_SUB_PRIORITY);
    return statusFromErrcode(ret);
}

binder::Status NetdNativeService::networkAddUidRangesParcel(const NativeUidRangeConfig& config) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    int ret = gCtls->netCtrl.addUsersToNetwork(config.netId, UidRanges(config.uidRanges),
                                               config.subPriority);
    return statusFromErrcode(ret);
}

binder::Status NetdNativeService::networkRemoveUidRangesParcel(const NativeUidRangeConfig& config) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    int ret = gCtls->netCtrl.removeUsersFromNetwork(config.netId, UidRanges(config.uidRanges),
                                                    config.subPriority);
    return statusFromErrcode(ret);
}

binder::Status NetdNativeService::networkRejectNonSecureVpn(
        bool add, const std::vector<UidRangeParcel>& uidRangeArray) {
    // TODO: elsewhere RouteController is only used from the tethering and network controllers, so
    // it should be possible to use the same lock as NetworkController. However, every call through
    // the CommandListener "network" command will need to hold this lock too, not just the ones that
    // read/modify network internal state (that is sufficient for ::dump() because it doesn't
    // look at routes, but it's not enough here).
    NETD_BIG_LOCK_RPC(PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    UidRanges uidRanges(uidRangeArray);

    int err;
    if (add) {
        err = RouteController::addUsersToRejectNonSecureNetworkRule(uidRanges);
    } else {
        err = RouteController::removeUsersFromRejectNonSecureNetworkRule(uidRanges);
    }
    return statusFromErrcode(err);
}

binder::Status NetdNativeService::socketDestroy(const std::vector<UidRangeParcel>& uids,
                                                const std::vector<int32_t>& skipUids) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();

    SockDiag sd;
    if (!sd.open()) {
        return binder::Status::fromServiceSpecificError(EIO,
                String8("Could not open SOCK_DIAG socket"));
    }

    UidRanges uidRanges(uids);
    int err = sd.destroySockets(uidRanges, std::set<uid_t>(skipUids.begin(), skipUids.end()),
                                true /* excludeLoopback */);
    if (err) {
        return binder::Status::fromServiceSpecificError(-err,
                String8::format("destroySockets: %s", strerror(-err)));
    }
    return binder::Status::ok();
}

binder::Status NetdNativeService::tetherApplyDnsInterfaces(bool *ret) {
    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    *ret = gCtls->tetherCtrl.applyDnsInterfaces();
    return binder::Status::ok();
}

namespace {

constexpr const int UNUSED_IFINDEX = 0;

void tetherAddStatsByInterface(TetherController::TetherStats* tetherStatsParcel,
                               const TetherController::TetherStats& tetherStats) {
    if (tetherStatsParcel->extIface == tetherStats.extIface) {
        tetherStatsParcel->rxBytes += tetherStats.rxBytes;
        tetherStatsParcel->rxPackets += tetherStats.rxPackets;
        tetherStatsParcel->txBytes += tetherStats.txBytes;
        tetherStatsParcel->txPackets += tetherStats.txPackets;
    }
}

TetherStatsParcel toTetherStatsParcel(const TetherController::TetherStats& stats) {
    TetherStatsParcel result;
    result.iface = stats.extIface;
    result.rxBytes = stats.rxBytes;
    result.rxPackets = stats.rxPackets;
    result.txBytes = stats.txBytes;
    result.txPackets = stats.txPackets;
    result.ifIndex = UNUSED_IFINDEX;
    return result;
}

void setTetherStatsParcelVecByInterface(std::vector<TetherStatsParcel>* tetherStatsVec,
                                        const TetherController::TetherStatsList& statsList) {
    std::map<std::string, TetherController::TetherStats> statsMap;
    for (const auto& stats : statsList) {
        auto iter = statsMap.find(stats.extIface);
        if (iter != statsMap.end()) {
            tetherAddStatsByInterface(&(iter->second), stats);
        } else {
            statsMap.insert(
                    std::pair<std::string, TetherController::TetherStats>(stats.extIface, stats));
        }
    }
    for (auto iter = statsMap.begin(); iter != statsMap.end(); iter++) {
        tetherStatsVec->push_back(toTetherStatsParcel(iter->second));
    }
}

std::vector<std::string> tetherStatsParcelVecToStringVec(std::vector<TetherStatsParcel>* tVec) {
    std::vector<std::string> result;
    for (const auto& t : *tVec) {
        result.push_back(StringPrintf("%s:%" PRId64 ",%" PRId64 ",%" PRId64 ",%" PRId64,
                                      t.iface.c_str(), t.rxBytes, t.rxPackets, t.txBytes,
                                      t.txPackets));
    }
    return result;
}

}  // namespace

binder::Status NetdNativeService::tetherGetStats(
        std::vector<TetherStatsParcel>* tetherStatsParcelVec) {
    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    const auto& statsList = gCtls->tetherCtrl.getTetherStats();
    if (!isOk(statsList)) {
        return asBinderStatus(statsList);
    }
    setTetherStatsParcelVecByInterface(tetherStatsParcelVec, statsList.value());
    auto statsResults = tetherStatsParcelVecToStringVec(tetherStatsParcelVec);
    return binder::Status::ok();
}

binder::Status NetdNativeService::interfaceAddAddress(const std::string &ifName,
        const std::string &addrString, int prefixLength) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    const int err = InterfaceController::addAddress(
            ifName.c_str(), addrString.c_str(), prefixLength);
    if (err != 0) {
        return binder::Status::fromServiceSpecificError(-err,
                String8::format("InterfaceController error: %s", strerror(-err)));
    }
    return binder::Status::ok();
}

binder::Status NetdNativeService::interfaceDelAddress(const std::string &ifName,
        const std::string &addrString, int prefixLength) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    const int err = InterfaceController::delAddress(
            ifName.c_str(), addrString.c_str(), prefixLength);
    if (err != 0) {
        return binder::Status::fromServiceSpecificError(-err,
                String8::format("InterfaceController error: %s", strerror(-err)));
    }
    return binder::Status::ok();
}

namespace {

std::tuple<binder::Status, const char*, const char*> getPathComponents(int32_t ipversion,
                                                                       int32_t category) {
    const char* ipversionStr = nullptr;
    switch (ipversion) {
        case INetd::IPV4:
            ipversionStr = "ipv4";
            break;
        case INetd::IPV6:
            ipversionStr = "ipv6";
            break;
        default:
            return {binder::Status::fromServiceSpecificError(EAFNOSUPPORT, "Bad IP version"),
                    nullptr, nullptr};
    }

    const char* whichStr = nullptr;
    switch (category) {
        case INetd::CONF:
            whichStr = "conf";
            break;
        case INetd::NEIGH:
            whichStr = "neigh";
            break;
        default:
            return {binder::Status::fromServiceSpecificError(EINVAL, "Bad category"), nullptr,
                    nullptr};
    }

    return {binder::Status::ok(), ipversionStr, whichStr};
}

}  // namespace

binder::Status NetdNativeService::getProcSysNet(int32_t ipversion, int32_t which,
                                                const std::string& ifname,
                                                const std::string& parameter, std::string* value) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    const auto pathParts = getPathComponents(ipversion, which);
    const auto& pathStatus = std::get<0>(pathParts);
    if (!pathStatus.isOk()) {
        return pathStatus;
    }

    const int err = InterfaceController::getParameter(std::get<1>(pathParts),
                                                      std::get<2>(pathParts), ifname.c_str(),
                                                      parameter.c_str(), value);
    return statusFromErrcode(err);
}

binder::Status NetdNativeService::setProcSysNet(int32_t ipversion, int32_t which,
                                                const std::string& ifname,
                                                const std::string& parameter,
                                                const std::string& value) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    const auto pathParts = getPathComponents(ipversion, which);
    const auto& pathStatus = std::get<0>(pathParts);
    if (!pathStatus.isOk()) {
        return pathStatus;
    }

    const int err = InterfaceController::setParameter(std::get<1>(pathParts),
                                                      std::get<2>(pathParts), ifname.c_str(),
                                                      parameter.c_str(), value.c_str());
    return statusFromErrcode(err);
}

binder::Status NetdNativeService::ipSecSetEncapSocketOwner(const ParcelFileDescriptor& socket,
                                                           int newUid) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();

    uid_t callerUid = IPCThreadState::self()->getCallingUid();
    return asBinderStatus(
            gCtls->xfrmCtrl.ipSecSetEncapSocketOwner(socket.get(), newUid, callerUid));
}

binder::Status NetdNativeService::ipSecAllocateSpi(
        int32_t transformId,
        const std::string& sourceAddress,
        const std::string& destinationAddress,
        int32_t inSpi,
        int32_t* outSpi) {
    // Necessary locking done in IpSecService and kernel
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    return asBinderStatus(gCtls->xfrmCtrl.ipSecAllocateSpi(
                    transformId,
                    sourceAddress,
                    destinationAddress,
                    inSpi,
                    outSpi));
}

binder::Status NetdNativeService::ipSecAddSecurityAssociation(
        int32_t transformId, int32_t mode, const std::string& sourceAddress,
        const std::string& destinationAddress, int32_t underlyingNetId, int32_t spi,
        int32_t markValue, int32_t markMask, const std::string& authAlgo,
        const std::vector<uint8_t>& authKey, int32_t authTruncBits, const std::string& cryptAlgo,
        const std::vector<uint8_t>& cryptKey, int32_t cryptTruncBits, const std::string& aeadAlgo,
        const std::vector<uint8_t>& aeadKey, int32_t aeadIcvBits, int32_t encapType,
        int32_t encapLocalPort, int32_t encapRemotePort, int32_t interfaceId) {
    // Necessary locking done in IpSecService and kernel
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    return asBinderStatus(gCtls->xfrmCtrl.ipSecAddSecurityAssociation(
            transformId, mode, sourceAddress, destinationAddress, underlyingNetId, spi, markValue,
            markMask, authAlgo, authKey, authTruncBits, cryptAlgo, cryptKey, cryptTruncBits,
            aeadAlgo, aeadKey, aeadIcvBits, encapType, encapLocalPort, encapRemotePort,
            interfaceId));
}

binder::Status NetdNativeService::ipSecDeleteSecurityAssociation(
        int32_t transformId, const std::string& sourceAddress,
        const std::string& destinationAddress, int32_t spi, int32_t markValue, int32_t markMask,
        int32_t interfaceId) {
    // Necessary locking done in IpSecService and kernel
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    return asBinderStatus(gCtls->xfrmCtrl.ipSecDeleteSecurityAssociation(
            transformId, sourceAddress, destinationAddress, spi, markValue, markMask, interfaceId));
}

binder::Status NetdNativeService::ipSecApplyTransportModeTransform(
        const ParcelFileDescriptor& socket, int32_t transformId, int32_t direction,
        const std::string& sourceAddress, const std::string& destinationAddress, int32_t spi) {
    // Necessary locking done in IpSecService and kernel
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    return asBinderStatus(gCtls->xfrmCtrl.ipSecApplyTransportModeTransform(
            socket.get(), transformId, direction, sourceAddress, destinationAddress, spi));
}

binder::Status NetdNativeService::ipSecRemoveTransportModeTransform(
        const ParcelFileDescriptor& socket) {
    // Necessary locking done in IpSecService and kernel
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    return asBinderStatus(gCtls->xfrmCtrl.ipSecRemoveTransportModeTransform(socket.get()));
}

binder::Status NetdNativeService::ipSecAddSecurityPolicy(int32_t transformId, int32_t selAddrFamily,
                                                         int32_t direction,
                                                         const std::string& tmplSrcAddress,
                                                         const std::string& tmplDstAddress,
                                                         int32_t spi, int32_t markValue,
                                                         int32_t markMask, int32_t interfaceId) {
    // Necessary locking done in IpSecService and kernel
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    return asBinderStatus(gCtls->xfrmCtrl.ipSecAddSecurityPolicy(
            transformId, selAddrFamily, direction, tmplSrcAddress, tmplDstAddress, spi, markValue,
            markMask, interfaceId));
}

binder::Status NetdNativeService::ipSecUpdateSecurityPolicy(
        int32_t transformId, int32_t selAddrFamily, int32_t direction,
        const std::string& tmplSrcAddress, const std::string& tmplDstAddress, int32_t spi,
        int32_t markValue, int32_t markMask, int32_t interfaceId) {
    // Necessary locking done in IpSecService and kernel
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    return asBinderStatus(gCtls->xfrmCtrl.ipSecUpdateSecurityPolicy(
            transformId, selAddrFamily, direction, tmplSrcAddress, tmplDstAddress, spi, markValue,
            markMask, interfaceId));
}

binder::Status NetdNativeService::ipSecDeleteSecurityPolicy(int32_t transformId,
                                                            int32_t selAddrFamily,
                                                            int32_t direction, int32_t markValue,
                                                            int32_t markMask, int32_t interfaceId) {
    // Necessary locking done in IpSecService and kernel
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    return asBinderStatus(gCtls->xfrmCtrl.ipSecDeleteSecurityPolicy(
            transformId, selAddrFamily, direction, markValue, markMask, interfaceId));
}

binder::Status NetdNativeService::ipSecAddTunnelInterface(const std::string& deviceName,
                                                          const std::string& localAddress,
                                                          const std::string& remoteAddress,
                                                          int32_t iKey, int32_t oKey,
                                                          int32_t interfaceId) {
    // Necessary locking done in IpSecService and kernel
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    netdutils::Status result = gCtls->xfrmCtrl.ipSecAddTunnelInterface(
            deviceName, localAddress, remoteAddress, iKey, oKey, interfaceId, false);
    return binder::Status::ok();
}

binder::Status NetdNativeService::ipSecUpdateTunnelInterface(const std::string& deviceName,
                                                             const std::string& localAddress,
                                                             const std::string& remoteAddress,
                                                             int32_t iKey, int32_t oKey,
                                                             int32_t interfaceId) {
    // Necessary locking done in IpSecService and kernel
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    netdutils::Status result = gCtls->xfrmCtrl.ipSecAddTunnelInterface(
            deviceName, localAddress, remoteAddress, iKey, oKey, interfaceId, true);
    return binder::Status::ok();
}

binder::Status NetdNativeService::ipSecRemoveTunnelInterface(const std::string& deviceName) {
    // Necessary locking done in IpSecService and kernel
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    netdutils::Status result = gCtls->xfrmCtrl.ipSecRemoveTunnelInterface(deviceName);
    return binder::Status::ok();
}

binder::Status NetdNativeService::setIPv6AddrGenMode(const std::string& ifName,
                                                     int32_t mode) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    return asBinderStatus(InterfaceController::setIPv6AddrGenMode(ifName, mode));
}

binder::Status NetdNativeService::wakeupAddInterface(const std::string& ifName,
                                                     const std::string& prefix, int32_t mark,
                                                     int32_t mask) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    return asBinderStatus(gCtls->wakeupCtrl.addInterface(ifName, prefix, mark, mask));
}

binder::Status NetdNativeService::wakeupDelInterface(const std::string& ifName,
                                                     const std::string& prefix, int32_t mark,
                                                     int32_t mask) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    return asBinderStatus(gCtls->wakeupCtrl.delInterface(ifName, prefix, mark, mask));
}

binder::Status NetdNativeService::trafficSwapActiveStatsMap() {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    return asBinderStatus(gCtls->trafficCtrl.swapActiveStatsMap());
}

binder::Status NetdNativeService::idletimerAddInterface(const std::string& ifName, int32_t timeout,
                                                        const std::string& classLabel) {
    NETD_LOCKING_RPC(gCtls->idletimerCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    int res =
            gCtls->idletimerCtrl.addInterfaceIdletimer(ifName.c_str(), timeout, classLabel.c_str());
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::idletimerRemoveInterface(const std::string& ifName,
                                                           int32_t timeout,
                                                           const std::string& classLabel) {
    NETD_LOCKING_RPC(gCtls->idletimerCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    int res = gCtls->idletimerCtrl.removeInterfaceIdletimer(ifName.c_str(), timeout,
                                                            classLabel.c_str());
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::strictUidCleartextPenalty(int32_t uid, int32_t policyPenalty) {
    NETD_LOCKING_RPC(gCtls->strictCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    StrictPenalty penalty;
    switch (policyPenalty) {
        case INetd::PENALTY_POLICY_REJECT:
            penalty = REJECT;
            break;
        case INetd::PENALTY_POLICY_LOG:
            penalty = LOG;
            break;
        case INetd::PENALTY_POLICY_ACCEPT:
            penalty = ACCEPT;
            break;
        default:
            return statusFromErrcode(-EINVAL);
            break;
    }
    int res = gCtls->strictCtrl.setUidCleartextPenalty((uid_t) uid, penalty);
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::clatdStart(const std::string& ifName,
                                             const std::string& nat64Prefix, std::string* v6Addr) {
    ENFORCE_ANY_PERMISSION(PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    int res = gCtls->clatdCtrl.startClatd(ifName.c_str(), nat64Prefix, v6Addr);
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::clatdStop(const std::string& ifName) {
    ENFORCE_ANY_PERMISSION(PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    int res = gCtls->clatdCtrl.stopClatd(ifName.c_str());
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::ipfwdEnabled(bool* status) {
    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    *status = (gCtls->tetherCtrl.getIpfwdRequesterList().size() > 0) ? true : false;
    return binder::Status::ok();
}

binder::Status NetdNativeService::ipfwdGetRequesterList(std::vector<std::string>* requesterList) {
    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    for (const auto& requester : gCtls->tetherCtrl.getIpfwdRequesterList()) {
        requesterList->push_back(requester);
    }
    return binder::Status::ok();
}

binder::Status NetdNativeService::ipfwdEnableForwarding(const std::string& requester) {
    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    int res = (gCtls->tetherCtrl.enableForwarding(requester.c_str())) ? 0 : -EREMOTEIO;
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::ipfwdDisableForwarding(const std::string& requester) {
    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    int res = (gCtls->tetherCtrl.disableForwarding(requester.c_str())) ? 0 : -EREMOTEIO;
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::ipfwdAddInterfaceForward(const std::string& fromIface,
                                                           const std::string& toIface) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    int res = RouteController::enableTethering(fromIface.c_str(), toIface.c_str());
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::ipfwdRemoveInterfaceForward(const std::string& fromIface,
                                                              const std::string& toIface) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    int res = RouteController::disableTethering(fromIface.c_str(), toIface.c_str());
    return statusFromErrcode(res);
}

namespace {

std::string addCurlyBrackets(const std::string& s) {
    return "{" + s + "}";
}

}  // namespace

binder::Status NetdNativeService::interfaceGetList(std::vector<std::string>* interfaceListResult) {
    NETD_LOCKING_RPC(InterfaceController::mutex, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    const auto& ifaceList = InterfaceController::getIfaceNames();

    interfaceListResult->clear();
    interfaceListResult->reserve(ifaceList.value().size());
    interfaceListResult->insert(end(*interfaceListResult), begin(ifaceList.value()),
                                end(ifaceList.value()));

    return binder::Status::ok();
}

std::string interfaceConfigurationParcelToString(const InterfaceConfigurationParcel& cfg) {
    std::vector<std::string> result{cfg.ifName, cfg.hwAddr, cfg.ipv4Addr,
                                    std::to_string(cfg.prefixLength)};
    result.insert(end(result), begin(cfg.flags), end(cfg.flags));
    return addCurlyBrackets(base::Join(result, ", "));
}

binder::Status NetdNativeService::interfaceGetCfg(
        const std::string& ifName, InterfaceConfigurationParcel* interfaceGetCfgResult) {
    NETD_LOCKING_RPC(InterfaceController::mutex, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(ifName);

    const auto& cfgRes = InterfaceController::getCfg(ifName);
    RETURN_BINDER_STATUS_IF_NOT_OK(entry, cfgRes);

    *interfaceGetCfgResult = cfgRes.value();
    gLog.log(entry.returns(interfaceConfigurationParcelToString(*interfaceGetCfgResult))
                     .withAutomaticDuration());
    return binder::Status::ok();
}

binder::Status NetdNativeService::interfaceSetCfg(const InterfaceConfigurationParcel& cfg) {
    NETD_LOCKING_RPC(InterfaceController::mutex, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    auto entry = gLog.newEntry()
                         .prettyFunction(__PRETTY_FUNCTION__)
                         .arg(interfaceConfigurationParcelToString(cfg));

    const auto& res = InterfaceController::setCfg(cfg);
    RETURN_BINDER_STATUS_IF_NOT_OK(entry, res);

    gLog.log(entry.withAutomaticDuration());
    return binder::Status::ok();
}

binder::Status NetdNativeService::interfaceSetIPv6PrivacyExtensions(const std::string& ifName,
                                                                    bool enable) {
    NETD_LOCKING_RPC(InterfaceController::mutex, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    int res = InterfaceController::setIPv6PrivacyExtensions(ifName.c_str(), enable);
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::interfaceClearAddrs(const std::string& ifName) {
    NETD_LOCKING_RPC(InterfaceController::mutex, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    int res = InterfaceController::clearAddrs(ifName.c_str());
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::interfaceSetEnableIPv6(const std::string& ifName, bool enable) {
    NETD_LOCKING_RPC(InterfaceController::mutex, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    int res = InterfaceController::setEnableIPv6(ifName.c_str(), enable);
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::interfaceSetMtu(const std::string& ifName, int32_t mtuValue) {
    NETD_LOCKING_RPC(InterfaceController::mutex, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    std::string mtu = std::to_string(mtuValue);
    int res = InterfaceController::setMtu(ifName.c_str(), mtu.c_str());
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::tetherStart(const std::vector<std::string>& dhcpRanges) {
    TetherConfigParcel config;
    config.usingLegacyDnsProxy = true;
    config.dhcpRanges = dhcpRanges;
    return tetherStartWithConfiguration(config);
}

binder::Status NetdNativeService::tetherStartWithConfiguration(const TetherConfigParcel& config) {
    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    if (config.dhcpRanges.size() % 2 == 1) {
        return statusFromErrcode(-EINVAL);
    }
    // TODO: Pass TetherConfigParcel directly.
    int res = gCtls->tetherCtrl.startTethering(config.usingLegacyDnsProxy, config.dhcpRanges);
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::tetherStop() {
    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    int res = gCtls->tetherCtrl.stopTethering();
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::tetherIsEnabled(bool* enabled) {
    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    *enabled = gCtls->tetherCtrl.isTetheringStarted();
    return binder::Status::ok();
}

binder::Status NetdNativeService::tetherInterfaceAdd(const std::string& ifName) {
    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    int res = gCtls->tetherCtrl.tetherInterface(ifName.c_str());
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::tetherInterfaceRemove(const std::string& ifName) {
    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    int res = gCtls->tetherCtrl.untetherInterface(ifName.c_str());
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::tetherInterfaceList(std::vector<std::string>* ifList) {
    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    for (const auto& ifname : gCtls->tetherCtrl.getTetheredInterfaceList()) {
        ifList->push_back(ifname);
    }
    return binder::Status::ok();
}

binder::Status NetdNativeService::tetherDnsSet(int32_t netId,
                                               const std::vector<std::string>& dnsAddrs) {
    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    int res = gCtls->tetherCtrl.setDnsForwarders(netId, dnsAddrs);
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::tetherDnsList(std::vector<std::string>* dnsList) {
    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    for (const auto& fwdr : gCtls->tetherCtrl.getDnsForwarders()) {
        dnsList->push_back(fwdr);
    }
    return binder::Status::ok();
}

binder::Status NetdNativeService::networkAddRouteParcel(int32_t netId,
                                                        const RouteInfoParcel& route) {
    // Public methods of NetworkController are thread-safe.
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    bool legacy = false;
    uid_t uid = 0;  // UID is only meaningful for legacy routes.

    // convert Parcel to parameters
    int res = gCtls->netCtrl.addRoute(netId, route.ifName.c_str(), route.destination.c_str(),
                                      route.nextHop.empty() ? nullptr : route.nextHop.c_str(),
                                      legacy, uid, route.mtu);
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::networkUpdateRouteParcel(int32_t netId,
                                                           const RouteInfoParcel& route) {
    // Public methods of NetworkController are thread-safe.
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    bool legacy = false;
    uid_t uid = 0;  // UID is only meaningful for legacy routes.

    // convert Parcel to parameters
    int res = gCtls->netCtrl.updateRoute(netId, route.ifName.c_str(), route.destination.c_str(),
                                         route.nextHop.empty() ? nullptr : route.nextHop.c_str(),
                                         legacy, uid, route.mtu);
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::networkRemoveRouteParcel(int32_t netId,
                                                           const RouteInfoParcel& route) {
    return networkRemoveRoute(netId, route.ifName, route.destination, route.nextHop);
}

binder::Status NetdNativeService::networkAddRoute(int32_t netId, const std::string& ifName,
                                                  const std::string& destination,
                                                  const std::string& nextHop) {
    // Public methods of NetworkController are thread-safe.
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    bool legacy = false;
    uid_t uid = 0;  // UID is only meaningful for legacy routes.
    int res = gCtls->netCtrl.addRoute(netId, ifName.c_str(), destination.c_str(),
                                      nextHop.empty() ? nullptr : nextHop.c_str(), legacy, uid, 0);
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::networkRemoveRoute(int32_t netId, const std::string& ifName,
                                                     const std::string& destination,
                                                     const std::string& nextHop) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    bool legacy = false;
    uid_t uid = 0;  // UID is only meaningful for legacy routes.
    int res = gCtls->netCtrl.removeRoute(netId, ifName.c_str(), destination.c_str(),
                                         nextHop.empty() ? nullptr : nextHop.c_str(), legacy, uid);
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::networkAddLegacyRoute(int32_t netId, const std::string& ifName,
                                                        const std::string& destination,
                                                        const std::string& nextHop, int32_t uid) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    bool legacy = true;
    int res = gCtls->netCtrl.addRoute(netId, ifName.c_str(), destination.c_str(),
                                      nextHop.empty() ? nullptr : nextHop.c_str(), legacy,
                                      (uid_t)uid, 0);
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::networkRemoveLegacyRoute(int32_t netId, const std::string& ifName,
                                                           const std::string& destination,
                                                           const std::string& nextHop,
                                                           int32_t uid) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    bool legacy = true;
    int res = gCtls->netCtrl.removeRoute(netId, ifName.c_str(), destination.c_str(),
                                         nextHop.empty() ? nullptr : nextHop.c_str(), legacy,
                                         (uid_t) uid);
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::networkGetDefault(int32_t* netId) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    *netId = gCtls->netCtrl.getDefaultNetwork();
    return binder::Status::ok();
}

binder::Status NetdNativeService::networkSetDefault(int32_t netId) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    int res = gCtls->netCtrl.setDefaultNetwork(netId);
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::networkClearDefault() {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    unsigned netId = NETID_UNSET;
    int res = gCtls->netCtrl.setDefaultNetwork(netId);
    return statusFromErrcode(res);
}

std::vector<uid_t> NetdNativeService::intsToUids(const std::vector<int32_t>& intUids) {
    return {begin(intUids), end(intUids)};
}

Permission NetdNativeService::convertPermission(int32_t permission) {
    switch (permission) {
        case INetd::PERMISSION_NETWORK:
            return Permission::PERMISSION_NETWORK;
        case INetd::PERMISSION_SYSTEM:
            return Permission::PERMISSION_SYSTEM;
        default:
            return Permission::PERMISSION_NONE;
    }
}

binder::Status NetdNativeService::networkSetPermissionForNetwork(int32_t netId,
                                                                 int32_t permission) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    std::vector<unsigned> netIds = {(unsigned) netId};
    int res = gCtls->netCtrl.setPermissionForNetworks(convertPermission(permission), netIds);
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::networkSetPermissionForUser(int32_t permission,
                                                              const std::vector<int32_t>& uids) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    gCtls->netCtrl.setPermissionForUsers(convertPermission(permission), intsToUids(uids));
    return binder::Status::ok();
}

binder::Status NetdNativeService::networkClearPermissionForUser(const std::vector<int32_t>& uids) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    Permission permission = Permission::PERMISSION_NONE;
    gCtls->netCtrl.setPermissionForUsers(permission, intsToUids(uids));
    return binder::Status::ok();
}

binder::Status NetdNativeService::networkSetProtectAllow(int32_t uid) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    std::vector<uid_t> uids = {(uid_t) uid};
    gCtls->netCtrl.allowProtect(uids);
    return binder::Status::ok();
}

binder::Status NetdNativeService::networkSetProtectDeny(int32_t uid) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    std::vector<uid_t> uids = {(uid_t) uid};
    gCtls->netCtrl.denyProtect(uids);
    return binder::Status::ok();
}

binder::Status NetdNativeService::networkCanProtect(int32_t uid, bool* ret) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    *ret = gCtls->netCtrl.canProtect((uid_t) uid);
    return binder::Status::ok();
}

binder::Status NetdNativeService::trafficSetNetPermForUids(int32_t permission,
                                                           const std::vector<int32_t>& uids) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    gCtls->trafficCtrl.setPermissionForUids(permission, intsToUids(uids));
    return binder::Status::ok();
}

binder::Status NetdNativeService::firewallSetFirewallType(int32_t firewallType) {
    NETD_LOCKING_RPC(gCtls->firewallCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    auto type = static_cast<FirewallType>(firewallType);

    int res = gCtls->firewallCtrl.setFirewallType(type);
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::firewallSetInterfaceRule(const std::string& ifName,
                                                           int32_t firewallRule) {
    NETD_LOCKING_RPC(gCtls->firewallCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    auto rule = static_cast<FirewallRule>(firewallRule);

    int res = gCtls->firewallCtrl.setInterfaceRule(ifName.c_str(), rule);
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::firewallSetUidRule(int32_t childChain, int32_t uid,
                                                     int32_t firewallRule) {
    NETD_LOCKING_RPC(gCtls->firewallCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    auto chain = static_cast<ChildChain>(childChain);
    auto rule = static_cast<FirewallRule>(firewallRule);

    int res = gCtls->firewallCtrl.setUidRule(chain, uid, rule);
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::firewallEnableChildChain(int32_t childChain, bool enable) {
    NETD_LOCKING_RPC(gCtls->firewallCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    auto chain = static_cast<ChildChain>(childChain);

    int res = gCtls->firewallCtrl.enableChildChains(chain, enable);
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::firewallAddUidInterfaceRules(const std::string& ifName,
                                                               const std::vector<int32_t>& uids) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();

    return asBinderStatus(gCtls->trafficCtrl.addUidInterfaceRules(
            RouteController::getIfIndex(ifName.c_str()), uids));
}

binder::Status NetdNativeService::firewallRemoveUidInterfaceRules(
        const std::vector<int32_t>& uids) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();

    return asBinderStatus(gCtls->trafficCtrl.removeUidInterfaceRules(uids));
}

binder::Status NetdNativeService::tetherAddForward(const std::string& intIface,
                                                   const std::string& extIface) {
    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);

    int res = gCtls->tetherCtrl.enableNat(intIface.c_str(), extIface.c_str());
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::tetherRemoveForward(const std::string& intIface,
                                                      const std::string& extIface) {
    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    int res = gCtls->tetherCtrl.disableNat(intIface.c_str(), extIface.c_str());
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::setTcpRWmemorySize(const std::string& rmemValues,
                                                     const std::string& wmemValues) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    if (!WriteStringToFile(rmemValues, TCP_RMEM_PROC_FILE)) {
        int ret = -errno;
        return statusFromErrcode(ret);
    }

    if (!WriteStringToFile(wmemValues, TCP_WMEM_PROC_FILE)) {
        int ret = -errno;
        return statusFromErrcode(ret);
    }
    return binder::Status::ok();
}

binder::Status NetdNativeService::registerUnsolicitedEventListener(
        const android::sp<android::net::INetdUnsolicitedEventListener>& listener) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    gCtls->eventReporter.registerUnsolEventListener(listener);
    return binder::Status::ok();
}

binder::Status NetdNativeService::getOemNetd(android::sp<android::IBinder>* listener) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    *listener = com::android::internal::net::OemNetdListener::getListener();

    return binder::Status::ok();
}

binder::Status NetdNativeService::getFwmarkForNetwork(int32_t netId, MarkMaskParcel* markMask) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();

    Fwmark fwmark;
    fwmark.netId = netId;
    markMask->mask = FWMARK_NET_ID_MASK;
    markMask->mark = fwmark.intValue;
    return binder::Status::ok();
}

// TODO: remark @deprecated in INetd.aidl.
binder::Status NetdNativeService::tetherOffloadRuleAdd(const TetherOffloadRuleParcel& /* rule */) {
    // deprecated
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    return binder::Status::fromExceptionCode(binder::Status::EX_UNSUPPORTED_OPERATION);
}

// TODO: remark @deprecated in INetd.aidl.
binder::Status NetdNativeService::tetherOffloadRuleRemove(
        const TetherOffloadRuleParcel& /* rule */) {
    // deprecated
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    return binder::Status::fromExceptionCode(binder::Status::EX_UNSUPPORTED_OPERATION);
}

// TODO: remark @deprecated in INetd.aidl.
binder::Status NetdNativeService::tetherOffloadGetStats(
        std::vector<TetherStatsParcel>* /* tetherStatsParcelVec */) {
    // deprecated
    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    return binder::Status::fromExceptionCode(binder::Status::EX_UNSUPPORTED_OPERATION);
}

// TODO: remark @deprecated in INetd.aidl.
binder::Status NetdNativeService::tetherOffloadSetInterfaceQuota(int /* ifIndex */,
                                                                 int64_t /* quotaBytes */) {
    // deprecated
    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    return binder::Status::fromExceptionCode(binder::Status::EX_UNSUPPORTED_OPERATION);
}

// TODO: remark @deprecated in INetd.aidl.
binder::Status NetdNativeService::tetherOffloadGetAndClearStats(
        int /* ifIndex */, android::net::TetherStatsParcel* /* tetherStats */) {
    // deprecated
    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    return binder::Status::fromExceptionCode(binder::Status::EX_UNSUPPORTED_OPERATION);
}

}  // namespace net
}  // namespace android
