/**
 * 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 <netdutils/Utils.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::TetherStatsParcel;
using android::net::UidRangeParcel;
using android::net::netd::aidl::NativeUidRangeConfig;
using android::netdutils::DumpWriter;
using android::netdutils::getIfaceNames;
using android::netdutils::ScopedIndent;
using android::os::ParcelFileDescriptor;

namespace android {
namespace net {

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

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

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.c_str(), 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;
    }

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

    gCtls->xfrmCtrl.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&, bool,
                                                          const std::vector<int32_t>&, bool*) {
    DEPRECATED;
}

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

binder::Status NetdNativeService::bandwidthRemoveNaughtyApp(int32_t) {
    DEPRECATED;
}

binder::Status NetdNativeService::bandwidthAddNiceApp(int32_t) {
    DEPRECATED;
}

binder::Status NetdNativeService::bandwidthRemoveNiceApp(int32_t) {
    DEPRECATED;
}

// 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),
                                                   false /* local */);
    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,
                                                  false /* excludeLocalRoutes */);
    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), false /* isLocalNetwork */);
    } else if (config.networkType == NativeNetworkType::PHYSICAL_LOCAL) {
        ret = gCtls->netCtrl.createPhysicalNetwork(
                config.netId, convertPermission(config.permission), true /* isLocalNetwork */);
    } else if (config.networkType == NativeNetworkType::VIRTUAL) {
        ret = gCtls->netCtrl.createVirtualNetwork(config.netId, config.secure, config.vpnType,
                                                  config.excludeLocalRoutes);
    }
    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::SUB_PRIORITY_HIGHEST);
    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::SUB_PRIORITY_HIGHEST);
    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();
    return asBinderStatus(gCtls->xfrmCtrl.ipSecAddTunnelInterface(
            deviceName, localAddress, remoteAddress, iKey, oKey, interfaceId, false));
}

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();
    return asBinderStatus(gCtls->xfrmCtrl.ipSecAddTunnelInterface(
            deviceName, localAddress, remoteAddress, iKey, oKey, interfaceId, true));
}

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

binder::Status NetdNativeService::ipSecMigrate(const IpSecMigrateInfoParcel& migrateInfo) {
    // Necessary locking done in IpSecService and kernel
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    return asBinderStatus(gCtls->xfrmCtrl.ipSecMigrate(
            migrateInfo.requestId, migrateInfo.selAddrFamily, migrateInfo.direction,
            migrateInfo.oldSourceAddress, migrateInfo.oldDestinationAddress,
            migrateInfo.newSourceAddress, migrateInfo.newDestinationAddress,
            migrateInfo.interfaceId));
}

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() {
    DEPRECATED;
}

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 */) {
    DEPRECATED;
}

binder::Status NetdNativeService::clatdStop(const std::string& /* ifName */) {
    DEPRECATED;
}

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 = 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();
    gCtls->netCtrl.allowProtect((uid_t)uid, NETID_UNSET);
    return binder::Status::ok();
}

binder::Status NetdNativeService::networkSetProtectDeny(int32_t uid) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    gCtls->netCtrl.denyProtect((uid_t)uid, NETID_UNSET);
    return binder::Status::ok();
}

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

binder::Status NetdNativeService::networkAllowBypassVpnOnNetwork(bool allow, int32_t uid,
                                                                 int32_t netId) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    int err;
    if (allow) {
        err = gCtls->netCtrl.allowProtect((uid_t)uid, netId);
    } else {
        err = gCtls->netCtrl.denyProtect((uid_t)uid, netId);
    }
    return statusFromErrcode(err);
}

binder::Status NetdNativeService::trafficSetNetPermForUids(int32_t, const std::vector<int32_t>&) {
    DEPRECATED;
}

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, int32_t, int32_t) {
    DEPRECATED;
}

binder::Status NetdNativeService::firewallEnableChildChain(int32_t, bool) {
    DEPRECATED;
}

binder::Status NetdNativeService::firewallAddUidInterfaceRules(const std::string&,
                                                               const std::vector<int32_t>&) {
    DEPRECATED;
}

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

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

binder::Status NetdNativeService::tetherOffloadRuleAdd(const TetherOffloadRuleParcel& /* rule */) {
    DEPRECATED;
}

binder::Status NetdNativeService::tetherOffloadRuleRemove(
        const TetherOffloadRuleParcel& /* rule */) {
    DEPRECATED;
}

binder::Status NetdNativeService::tetherOffloadGetStats(
        std::vector<TetherStatsParcel>* /* tetherStatsParcelVec */) {
    DEPRECATED;
}

binder::Status NetdNativeService::tetherOffloadSetInterfaceQuota(int /* ifIndex */,
                                                                 int64_t /* quotaBytes */) {
    DEPRECATED;
}

binder::Status NetdNativeService::tetherOffloadGetAndClearStats(
        int /* ifIndex */, android::net::TetherStatsParcel* /* tetherStats */) {
    DEPRECATED;
}

binder::Status NetdNativeService::setNetworkAllowlist(
        const std::vector<NativeUidRangeConfig>& rangeConfigs) {
    ENFORCE_NETWORK_STACK_PERMISSIONS();
    return statusFromErrcode(gCtls->netCtrl.setNetworkAllowlist(rangeConfigs));
}

}  // namespace net
}  // namespace android
