/**
 * 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 <set>
#include <vector>

#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <cutils/properties.h>
#include <log/log.h>
#include <utils/Errors.h>
#include <utils/String16.h>

#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include "android/net/BnNetd.h"

#include <openssl/base64.h>

#include "Controllers.h"
#include "DumpWriter.h"
#include "EventReporter.h"
#include "InterfaceController.h"
#include "NetdConstants.h"
#include "NetdNativeService.h"
#include "Process.h"
#include "RouteController.h"
#include "SockDiag.h"
#include "UidRanges.h"

using android::base::StringPrintf;
using android::os::PersistableBundle;

namespace android {
namespace net {

namespace {

const char CONNECTIVITY_INTERNAL[] = "android.permission.CONNECTIVITY_INTERNAL";
const char NETWORK_STACK[] = "android.permission.NETWORK_STACK";
const char DUMP[] = "android.permission.DUMP";
const char OPT_SHORT[] = "--short";

binder::Status checkPermission(const char *permission) {
    pid_t pid;
    uid_t uid;

    if (checkCallingPermission(String16(permission), (int32_t *) &pid, (int32_t *) &uid)) {
        return binder::Status::ok();
    } else {
        auto err = StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, permission);
        return binder::Status::fromExceptionCode(binder::Status::EX_SECURITY, String8(err.c_str()));
    }
}

#define ENFORCE_DEBUGGABLE() {                              \
    char value[PROPERTY_VALUE_MAX + 1];                     \
    if (property_get("ro.debuggable", value, nullptr) != 1  \
            || value[0] != '1') {                           \
        return binder::Status::fromExceptionCode(           \
            binder::Status::EX_SECURITY,                    \
            String8("Not available in production builds.")  \
        );                                                  \
    }                                                       \
}

#define ENFORCE_PERMISSION(permission) {                    \
    binder::Status status = checkPermission((permission));  \
    if (!status.isOk()) {                                   \
        return status;                                      \
    }                                                       \
}

#define NETD_LOCKING_RPC(permission, lock)                  \
    ENFORCE_PERMISSION(permission);                         \
    std::lock_guard<std::mutex> _lock(lock);

#define NETD_BIG_LOCK_RPC(permission) NETD_LOCKING_RPC((permission), gBigNetdLock)

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

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 = checkPermission(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();

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

    return NO_ERROR;
}

binder::Status NetdNativeService::isAlive(bool *alive) {
    NETD_BIG_LOCK_RPC(CONNECTIVITY_INTERNAL);
    auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__);

    *alive = true;

    gLog.log(entry.returns(*alive));
    return binder::Status::ok();
}

binder::Status NetdNativeService::firewallReplaceUidChain(const std::string& chainName,
        bool isWhitelist, const std::vector<int32_t>& uids, bool *ret) {
    NETD_LOCKING_RPC(CONNECTIVITY_INTERNAL, gCtls->firewallCtrl.lock);
    auto entry = gLog.newEntry()
                         .prettyFunction(__PRETTY_FUNCTION__)
                         .arg(chainName)
                         .arg(isWhitelist)
                         .arg(uids);

    int err = gCtls->firewallCtrl.replaceUidChain(chainName, isWhitelist, uids);
    *ret = (err == 0);

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

binder::Status NetdNativeService::bandwidthEnableDataSaver(bool enable, bool *ret) {
    NETD_LOCKING_RPC(CONNECTIVITY_INTERNAL, gCtls->bandwidthCtrl.lock);
    auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(enable);

    int err = gCtls->bandwidthCtrl.enableDataSaver(enable);
    *ret = (err == 0);
    gLog.log(entry.returns(*ret).withAutomaticDuration());
    return binder::Status::ok();
}

binder::Status NetdNativeService::networkCreatePhysical(int32_t netId,
        const std::string& permission) {
    ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
    auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(netId).arg(permission);
    int ret = gCtls->netCtrl.createPhysicalNetwork(netId, stringToPermission(permission.c_str()));
    gLog.log(entry.returns(ret).withAutomaticDuration());
    return statusFromErrcode(ret);
}

binder::Status NetdNativeService::networkCreateVpn(int32_t netId, bool hasDns, bool secure) {
    ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
    int ret = gCtls->netCtrl.createVirtualNetwork(netId, hasDns, secure);
    return statusFromErrcode(ret);
}

binder::Status NetdNativeService::networkDestroy(int32_t netId) {
    ENFORCE_PERMISSION(NETWORK_STACK);
    // Both of these functions manage their own locking internally.
    const int ret = gCtls->netCtrl.destroyNetwork(netId);
    gCtls->resolverCtrl.clearDnsServers(netId);
    return statusFromErrcode(ret);
}

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

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

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

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

binder::Status NetdNativeService::networkRejectNonSecureVpn(bool add,
        const std::vector<UidRange>& 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(CONNECTIVITY_INTERNAL);

    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<UidRange>& uids,
        const std::vector<int32_t>& skipUids) {

    ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);

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

// Parse a base64 encoded string into a vector of bytes.
// On failure, return an empty vector.
static std::vector<uint8_t> parseBase64(const std::string& input) {
    std::vector<uint8_t> decoded;
    size_t out_len;
    if (EVP_DecodedLength(&out_len, input.size()) != 1) {
        return decoded;
    }
    // out_len is now an upper bound on the output length.
    decoded.resize(out_len);
    if (EVP_DecodeBase64(decoded.data(), &out_len, decoded.size(),
            reinterpret_cast<const uint8_t*>(input.data()), input.size()) == 1) {
        // Possibly shrink the vector if the actual output was smaller than the bound.
        decoded.resize(out_len);
    } else {
        decoded.clear();
    }
    if (out_len != SHA256_SIZE) {
        decoded.clear();
    }
    return decoded;
}

binder::Status NetdNativeService::setResolverConfiguration(int32_t netId,
        const std::vector<std::string>& servers, const std::vector<std::string>& domains,
        const std::vector<int32_t>& params, const std::string& tlsName,
        const std::vector<std::string>& tlsServers,
        const std::vector<std::string>& tlsFingerprints) {
    // This function intentionally does not lock within Netd, as Bionic is thread-safe.
    ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
    auto entry = gLog.newEntry()
                         .prettyFunction(__PRETTY_FUNCTION__)
                         .arg(netId)
                         .arg(servers)
                         .arg(domains)
                         .arg(params)
                         .arg(tlsName)
                         .arg(tlsServers)
                         .arg(tlsFingerprints);

    std::set<std::vector<uint8_t>> decoded_fingerprints;
    for (const std::string& fingerprint : tlsFingerprints) {
        std::vector<uint8_t> decoded = parseBase64(fingerprint);
        if (decoded.empty()) {
            return binder::Status::fromServiceSpecificError(EINVAL,
                    String8::format("ResolverController error: bad fingerprint"));
        }
        decoded_fingerprints.emplace(decoded);
    }

    int err = gCtls->resolverCtrl.setResolverConfiguration(netId, servers, domains, params,
            tlsName, tlsServers, decoded_fingerprints);
    gLog.log(entry.returns(err).withAutomaticDuration());
    if (err != 0) {
        return binder::Status::fromServiceSpecificError(-err,
                String8::format("ResolverController error: %s", strerror(-err)));
    }
    return binder::Status::ok();
}

binder::Status NetdNativeService::getResolverInfo(int32_t netId,
        std::vector<std::string>* servers, std::vector<std::string>* domains,
        std::vector<int32_t>* params, std::vector<int32_t>* stats) {
    // This function intentionally does not lock within Netd, as Bionic is thread-safe.
    ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);

    int err = gCtls->resolverCtrl.getResolverInfo(netId, servers, domains, params, stats);
    if (err != 0) {
        return binder::Status::fromServiceSpecificError(-err,
                String8::format("ResolverController error: %s", strerror(-err)));
    }
    return binder::Status::ok();
}

binder::Status NetdNativeService::tetherApplyDnsInterfaces(bool *ret) {
    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->tetherCtrl.lock);

    *ret = gCtls->tetherCtrl.applyDnsInterfaces();
    return binder::Status::ok();
}

namespace {

void tetherAddStats(PersistableBundle *bundle, const TetherController::TetherStats& stats) {
    String16 iface = String16(stats.extIface.c_str());
    std::vector<int64_t> statsVector(INetd::TETHER_STATS_ARRAY_SIZE);

    bundle->getLongVector(iface, &statsVector);
    if (statsVector.size() == 0) {
        for (int i = 0; i < INetd::TETHER_STATS_ARRAY_SIZE; i++) statsVector.push_back(0);
    }

    statsVector[INetd::TETHER_STATS_RX_BYTES]   += stats.rxBytes;
    statsVector[INetd::TETHER_STATS_RX_PACKETS] += stats.rxPackets;
    statsVector[INetd::TETHER_STATS_TX_BYTES]   += stats.txBytes;
    statsVector[INetd::TETHER_STATS_TX_PACKETS] += stats.txPackets;

    bundle->putLongVector(iface, statsVector);
}

}  // namespace

binder::Status NetdNativeService::tetherGetStats(PersistableBundle *bundle) {
    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->tetherCtrl.lock);

    const auto& statsList = gCtls->tetherCtrl.getTetherStats();
    if (!isOk(statsList)) {
        return asBinderStatus(statsList);
    }

    for (const auto& stats : statsList.value()) {
        tetherAddStats(bundle, stats);
    }

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

binder::Status NetdNativeService::interfaceAddAddress(const std::string &ifName,
        const std::string &addrString, int prefixLength) {
    ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);

    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_PERMISSION(CONNECTIVITY_INTERNAL);

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

binder::Status NetdNativeService::setProcSysNet(
        int32_t family, int32_t which, const std::string &ifname, const std::string &parameter,
        const std::string &value) {
    ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);

    const char *familyStr;
    switch (family) {
        case INetd::IPV4:
            familyStr = "ipv4";
            break;
        case INetd::IPV6:
            familyStr = "ipv6";
            break;
        default:
            return binder::Status::fromServiceSpecificError(EAFNOSUPPORT, String8("Bad family"));
    }

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

    const int err = InterfaceController::setParameter(
            familyStr, whichStr, ifname.c_str(), parameter.c_str(),
            value.c_str());
    if (err != 0) {
        return binder::Status::fromServiceSpecificError(-err,
                String8::format("ResolverController error: %s", strerror(-err)));
    }
    return binder::Status::ok();
}

binder::Status NetdNativeService::getMetricsReportingLevel(int *reportingLevel) {
    // This function intentionally does not lock, since the only thing it does is one read from an
    // atomic_int.
    ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
    ENFORCE_DEBUGGABLE();

    *reportingLevel = gCtls->eventReporter.getMetricsReportingLevel();
    return binder::Status::ok();
}

binder::Status NetdNativeService::setMetricsReportingLevel(const int reportingLevel) {
    // This function intentionally does not lock, since the only thing it does is one write to an
    // atomic_int.
    ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
    ENFORCE_DEBUGGABLE();

    return (gCtls->eventReporter.setMetricsReportingLevel(reportingLevel) == 0)
            ? binder::Status::ok()
            : binder::Status::fromExceptionCode(binder::Status::EX_ILLEGAL_ARGUMENT);
}

binder::Status NetdNativeService::ipSecSetEncapSocketOwner(const android::base::unique_fd& socket,
                                                      int newUid) {
    ENFORCE_PERMISSION(NETWORK_STACK)
    gLog.log("ipSecSetEncapSocketOwner()");

    uid_t callerUid = IPCThreadState::self()->getCallingUid();
    return asBinderStatus(gCtls->xfrmCtrl.ipSecSetEncapSocketOwner(socket, 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_PERMISSION(CONNECTIVITY_INTERNAL);
    gLog.log("ipSecAllocateSpi()");
    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) {
    // Necessary locking done in IpSecService and kernel
    ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
    gLog.log("ipSecAddSecurityAssociation()");
    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));
}

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

binder::Status NetdNativeService::ipSecApplyTransportModeTransform(
        const android::base::unique_fd& 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_PERMISSION(CONNECTIVITY_INTERNAL);
    gLog.log("ipSecApplyTransportModeTransform()");
    return asBinderStatus(gCtls->xfrmCtrl.ipSecApplyTransportModeTransform(
                    socket,
                    transformId,
                    direction,
                    sourceAddress,
                    destinationAddress,
                    spi));
}

binder::Status NetdNativeService::ipSecRemoveTransportModeTransform(
            const android::base::unique_fd& socket) {
    // Necessary locking done in IpSecService and kernel
    ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
    gLog.log("ipSecRemoveTransportModeTransform()");
    return asBinderStatus(gCtls->xfrmCtrl.ipSecRemoveTransportModeTransform(
                    socket));
}

binder::Status NetdNativeService::ipSecAddSecurityPolicy(
        int32_t transformId,
        int32_t direction,
        const std::string& sourceAddress,
        const std::string& destinationAddress,
        int32_t spi,
        int32_t markValue,
        int32_t markMask){
    // Necessary locking done in IpSecService and kernel
    ENFORCE_PERMISSION(NETWORK_STACK);
    gLog.log("ipSecAddSecurityPolicy()");
    return asBinderStatus(gCtls->xfrmCtrl.ipSecAddSecurityPolicy(
                    transformId,
                    direction,
                    sourceAddress,
                    destinationAddress,
                    spi,
                    markValue,
                    markMask));
}

binder::Status NetdNativeService::ipSecUpdateSecurityPolicy(
        int32_t transformId,
        int32_t direction,
        const std::string& sourceAddress,
        const std::string& destinationAddress,
        int32_t spi,
        int32_t markValue,
        int32_t markMask){
    // Necessary locking done in IpSecService and kernel
    ENFORCE_PERMISSION(NETWORK_STACK);
    gLog.log("ipSecAddSecurityPolicy()");
    return asBinderStatus(gCtls->xfrmCtrl.ipSecUpdateSecurityPolicy(
                    transformId,
                    direction,
                    sourceAddress,
                    destinationAddress,
                    spi,
                    markValue,
                    markMask));
}

binder::Status NetdNativeService::ipSecDeleteSecurityPolicy(
        int32_t transformId,
        int32_t direction,
        const std::string& sourceAddress,
        const std::string& destinationAddress,
        int32_t markValue,
        int32_t markMask){
    // Necessary locking done in IpSecService and kernel
    ENFORCE_PERMISSION(NETWORK_STACK);
    gLog.log("ipSecAddSecurityPolicy()");
    return asBinderStatus(gCtls->xfrmCtrl.ipSecDeleteSecurityPolicy(
                    transformId,
                    direction,
                    sourceAddress,
                    destinationAddress,
                    markValue,
                    markMask));
}

binder::Status NetdNativeService::addVirtualTunnelInterface(
        const std::string& deviceName,
        const std::string& localAddress,
        const std::string& remoteAddress,
        int32_t iKey,
        int32_t oKey) {
    // Necessary locking done in IpSecService and kernel
    ENFORCE_PERMISSION(NETWORK_STACK);
    gLog.log("addVirtualTunnelInterface()");
    int ret = gCtls->xfrmCtrl.addVirtualTunnelInterface(
                             deviceName,
                             localAddress,
                             remoteAddress,
                             iKey,
                             oKey,
                             false);

    return (ret == 0) ? binder::Status::ok() :
                        asBinderStatus(netdutils::statusFromErrno(
                                       ret, "Error in creating virtual tunnel interface."));
}

binder::Status NetdNativeService::updateVirtualTunnelInterface(
        const std::string& deviceName,
        const std::string& localAddress,
        const std::string& remoteAddress,
        int32_t iKey,
        int32_t oKey) {
    // Necessary locking done in IpSecService and kernel
    ENFORCE_PERMISSION(NETWORK_STACK);
    gLog.log("updateVirtualTunnelInterface()");
    int ret = gCtls->xfrmCtrl.addVirtualTunnelInterface(
                             deviceName,
                             localAddress,
                             remoteAddress,
                             iKey,
                             oKey,
                             true);

    return (ret == 0) ? binder::Status::ok() :
                        asBinderStatus(netdutils::statusFromErrno(
                                       ret, "Error in updating virtual tunnel interface."));
}

binder::Status NetdNativeService::removeVirtualTunnelInterface(const std::string& deviceName) {
    // Necessary locking done in IpSecService and kernel
    ENFORCE_PERMISSION(NETWORK_STACK);
    gLog.log("removeVirtualTunnelInterface()");
    int ret = gCtls->xfrmCtrl.removeVirtualTunnelInterface(deviceName);

    return (ret == 0) ? binder::Status::ok() :
                        asBinderStatus(netdutils::statusFromErrno(
                                       ret, "Error in removing virtual tunnel interface."));
}

binder::Status NetdNativeService::setIPv6AddrGenMode(const std::string& ifName,
                                                     int32_t mode) {
    ENFORCE_PERMISSION(NETWORK_STACK);
    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_PERMISSION(NETWORK_STACK);
    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_PERMISSION(NETWORK_STACK);
    return asBinderStatus(gCtls->wakeupCtrl.delInterface(ifName, prefix, mark, mask));
}

binder::Status NetdNativeService::trafficCheckBpfStatsEnable(bool* ret) {
    ENFORCE_PERMISSION(NETWORK_STACK);
    *ret = gCtls->trafficCtrl.checkBpfStatsEnable();
    return binder::Status::ok();
}

binder::Status NetdNativeService::idletimerAddInterface(const std::string& ifName, int32_t timeout,
                                                        const std::string& classLabel) {
    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->idletimerCtrl.lock);
    auto entry = gLog.newEntry()
                         .prettyFunction(__PRETTY_FUNCTION__)
                         .arg(ifName)
                         .arg(timeout)
                         .arg(classLabel);
    int res =
            gCtls->idletimerCtrl.addInterfaceIdletimer(ifName.c_str(), timeout, classLabel.c_str());
    gLog.log(entry.returns(res).withAutomaticDuration());
    return statusFromErrcode(res);
}

binder::Status NetdNativeService::idletimerRemoveInterface(const std::string& ifName,
                                                           int32_t timeout,
                                                           const std::string& classLabel) {
    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->idletimerCtrl.lock);
    auto entry = gLog.newEntry()
                         .prettyFunction(__PRETTY_FUNCTION__)
                         .arg(ifName)
                         .arg(timeout)
                         .arg(classLabel);
    int res = gCtls->idletimerCtrl.removeInterfaceIdletimer(ifName.c_str(), timeout,
                                                            classLabel.c_str());
    gLog.log(entry.returns(res).withAutomaticDuration());
    return statusFromErrcode(res);
}
}  // namespace net
}  // namespace android
