/*
 * Copyright (C) 2017 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 "TrafficController"
#include <inttypes.h>
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/in.h>
#include <linux/inet_diag.h>
#include <linux/netlink.h>
#include <linux/sock_diag.h>
#include <linux/unistd.h>
#include <net/if.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#include <mutex>
#include <unordered_set>
#include <vector>

#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <logwrap/logwrap.h>
#include <netdutils/StatusOr.h>

#include <netdutils/Misc.h>
#include <netdutils/Syscalls.h>
#include "TrafficController.h"
#include "bpf/BpfMap.h"

#include "DumpWriter.h"
#include "FirewallController.h"
#include "InterfaceController.h"
#include "NetlinkListener.h"
#include "qtaguid/qtaguid.h"

using namespace android::bpf;  // NOLINT(google-build-using-namespace): grandfathered

namespace android {
namespace net {

using base::StringPrintf;
using base::unique_fd;
using base::Join;
using netdutils::extract;
using netdutils::Slice;
using netdutils::sSyscalls;
using netdutils::Status;
using netdutils::statusFromErrno;
using netdutils::StatusOr;
using netdutils::status::ok;

constexpr int kSockDiagMsgType = SOCK_DIAG_BY_FAMILY;
constexpr int kSockDiagDoneMsgType = NLMSG_DONE;

StatusOr<std::unique_ptr<NetlinkListenerInterface>> makeSkDestroyListener() {
    const auto& sys = sSyscalls.get();
    ASSIGN_OR_RETURN(auto event, sys.eventfd(0, EFD_CLOEXEC));
    const int domain = AF_NETLINK;
    const int type = SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK;
    const int protocol = NETLINK_INET_DIAG;
    ASSIGN_OR_RETURN(auto sock, sys.socket(domain, type, protocol));

    sockaddr_nl addr = {
        .nl_family = AF_NETLINK,
        .nl_groups = 1 << (SKNLGRP_INET_TCP_DESTROY - 1) | 1 << (SKNLGRP_INET_UDP_DESTROY - 1) |
                     1 << (SKNLGRP_INET6_TCP_DESTROY - 1) | 1 << (SKNLGRP_INET6_UDP_DESTROY - 1)};
    RETURN_IF_NOT_OK(sys.bind(sock, addr));

    const sockaddr_nl kernel = {.nl_family = AF_NETLINK};
    RETURN_IF_NOT_OK(sys.connect(sock, kernel));

    std::unique_ptr<NetlinkListenerInterface> listener =
        std::make_unique<NetlinkListener>(std::move(event), std::move(sock));

    return listener;
}

Status changeOwnerAndMode(const char* path, gid_t group, const char* debugName, bool netdOnly) {
    int ret = chown(path, AID_ROOT, group);
    if (ret != 0) return statusFromErrno(errno, StringPrintf("change %s group failed", debugName));

    if (netdOnly) {
        ret = chmod(path, S_IRWXU);
    } else {
        // Allow both netd and system server to obtain map fd from the path.
        // chmod doesn't grant permission to all processes in that group to
        // read/write the bpf map. They still need correct sepolicy to
        // read/write the map.
        ret = chmod(path, S_IRWXU | S_IRGRP);
    }
    if (ret != 0) return statusFromErrno(errno, StringPrintf("change %s mode failed", debugName));
    return netdutils::status::ok;
}

TrafficController::TrafficController() {
    ebpfSupported = hasBpfSupport();
}

Status initialOwnerMap(BpfMap<uint32_t, uint8_t>& map) {
    map.clear();
    uint32_t mapSettingKey = UID_MAP_ENABLED;
    uint8_t defaultMapState = 0;
    return map.writeValue(mapSettingKey, defaultMapState, BPF_NOEXIST);
}

Status TrafficController::initMaps() {
    std::lock_guard<std::mutex> ownerMapGuard(mOwnerMatchMutex);
    RETURN_IF_NOT_OK(
        mCookieTagMap.getOrCreate(COOKIE_UID_MAP_SIZE, COOKIE_TAG_MAP_PATH, BPF_MAP_TYPE_HASH));

    RETURN_IF_NOT_OK(changeOwnerAndMode(COOKIE_TAG_MAP_PATH, AID_NET_BW_ACCT, "CookieTagMap",
                                        false));

    RETURN_IF_NOT_OK(mUidCounterSetMap.getOrCreate(UID_COUNTERSET_MAP_SIZE, UID_COUNTERSET_MAP_PATH,
                                                   BPF_MAP_TYPE_HASH));
    RETURN_IF_NOT_OK(changeOwnerAndMode(UID_COUNTERSET_MAP_PATH, AID_NET_BW_ACCT,
                                        "UidCounterSetMap", false));

    RETURN_IF_NOT_OK(
        mAppUidStatsMap.getOrCreate(UID_STATS_MAP_SIZE, APP_UID_STATS_MAP_PATH, BPF_MAP_TYPE_HASH));
    RETURN_IF_NOT_OK(
        changeOwnerAndMode(APP_UID_STATS_MAP_PATH, AID_NET_BW_STATS, "AppUidStatsMap", false));

    RETURN_IF_NOT_OK(
        mUidStatsMap.getOrCreate(UID_STATS_MAP_SIZE, UID_STATS_MAP_PATH, BPF_MAP_TYPE_HASH));
    RETURN_IF_NOT_OK(changeOwnerAndMode(UID_STATS_MAP_PATH, AID_NET_BW_STATS, "UidStatsMap",
                                        false));

    RETURN_IF_NOT_OK(
        mTagStatsMap.getOrCreate(TAG_STATS_MAP_SIZE, TAG_STATS_MAP_PATH, BPF_MAP_TYPE_HASH));
    RETURN_IF_NOT_OK(changeOwnerAndMode(TAG_STATS_MAP_PATH, AID_NET_BW_STATS, "TagStatsMap",
                                        false));

    RETURN_IF_NOT_OK(mIfaceIndexNameMap.getOrCreate(IFACE_INDEX_NAME_MAP_SIZE,
                                                    IFACE_INDEX_NAME_MAP_PATH, BPF_MAP_TYPE_HASH));
    RETURN_IF_NOT_OK(changeOwnerAndMode(IFACE_INDEX_NAME_MAP_PATH, AID_NET_BW_STATS,
                                        "IfaceIndexNameMap", false));

    RETURN_IF_NOT_OK(
        mDozableUidMap.getOrCreate(UID_OWNER_MAP_SIZE, DOZABLE_UID_MAP_PATH, BPF_MAP_TYPE_HASH));
    RETURN_IF_NOT_OK(changeOwnerAndMode(DOZABLE_UID_MAP_PATH, AID_ROOT, "DozableUidMap", true));
    RETURN_IF_NOT_OK(initialOwnerMap(mDozableUidMap));

    RETURN_IF_NOT_OK(
        mStandbyUidMap.getOrCreate(UID_OWNER_MAP_SIZE, STANDBY_UID_MAP_PATH, BPF_MAP_TYPE_HASH));
    RETURN_IF_NOT_OK(changeOwnerAndMode(STANDBY_UID_MAP_PATH, AID_ROOT, "StandbyUidMap", true));
    RETURN_IF_NOT_OK(initialOwnerMap(mStandbyUidMap));

    RETURN_IF_NOT_OK(mPowerSaveUidMap.getOrCreate(UID_OWNER_MAP_SIZE, POWERSAVE_UID_MAP_PATH,
                                                  BPF_MAP_TYPE_HASH));
    RETURN_IF_NOT_OK(changeOwnerAndMode(POWERSAVE_UID_MAP_PATH, AID_ROOT, "PowerSaveUidMap", true));
    RETURN_IF_NOT_OK(initialOwnerMap(mPowerSaveUidMap));

    RETURN_IF_NOT_OK(
        mIfaceStatsMap.getOrCreate(IFACE_STATS_MAP_SIZE, IFACE_STATS_MAP_PATH, BPF_MAP_TYPE_HASH));
    RETURN_IF_NOT_OK(changeOwnerAndMode(IFACE_STATS_MAP_PATH, AID_NET_BW_STATS, "IfaceStatsMap",
                                        false));

    RETURN_IF_NOT_OK(mBandwidthUidMap.getOrCreate(UID_OWNER_MAP_SIZE, BANDWIDTH_UID_MAP_PATH,
                                                  BPF_MAP_TYPE_HASH));
    RETURN_IF_NOT_OK(changeOwnerAndMode(BANDWIDTH_UID_MAP_PATH, AID_ROOT, "BandwidthUidMap", true));
    mBandwidthUidMap.clear();
    return netdutils::status::ok;
}

Status TrafficController::start() {

    if (!ebpfSupported) {
        return netdutils::status::ok;
    }

    /* When netd restart from a crash without total system reboot, the program
     * is still attached to the cgroup, detach it so the program can be freed
     * and we can load and attach new program into the target cgroup.
     *
     * TODO: Scrape existing socket when run-time restart and clean up the map
     * if the socket no longer exist
     */

    RETURN_IF_NOT_OK(initMaps());

    // Fetch the list of currently-existing interfaces. At this point NetlinkHandler is
    // already running, so it will call addInterface() when any new interface appears.
    std::map<std::string, uint32_t> ifacePairs;
    ASSIGN_OR_RETURN(ifacePairs, InterfaceController::getIfaceList());
    for (const auto& ifacePair:ifacePairs) {
        addInterface(ifacePair.first.c_str(), ifacePair.second);
    }


    auto result = makeSkDestroyListener();
    if (!isOk(result)) {
        ALOGE("Unable to create SkDestroyListener: %s", toString(result).c_str());
    } else {
        mSkDestroyListener = std::move(result.value());
    }
    // Rx handler extracts nfgenmsg looks up and invokes registered dispatch function.
    const auto rxHandler = [this](const nlmsghdr&, const Slice msg) {
        inet_diag_msg diagmsg = {};
        if (extract(msg, diagmsg) < sizeof(inet_diag_msg)) {
            ALOGE("unrecognized netlink message: %s", toString(msg).c_str());
            return;
        }
        uint64_t sock_cookie = static_cast<uint64_t>(diagmsg.id.idiag_cookie[0]) |
                               (static_cast<uint64_t>(diagmsg.id.idiag_cookie[1]) << 32);

        mCookieTagMap.deleteValue(sock_cookie);
    };
    expectOk(mSkDestroyListener->subscribe(kSockDiagMsgType, rxHandler));

    // In case multiple netlink message comes in as a stream, we need to handle the rxDone message
    // properly.
    const auto rxDoneHandler = [](const nlmsghdr&, const Slice msg) {
        // Ignore NLMSG_DONE  messages
        inet_diag_msg diagmsg = {};
        extract(msg, diagmsg);
    };
    expectOk(mSkDestroyListener->subscribe(kSockDiagDoneMsgType, rxDoneHandler));

    int* status = nullptr;

    std::vector<const char*> prog_args{
        "/system/bin/bpfloader",
    };
    int ret = access(BPF_INGRESS_PROG_PATH, R_OK);
    if (ret != 0 && errno == ENOENT) {
        prog_args.push_back((char*)"-i");
    }
    ret = access(BPF_EGRESS_PROG_PATH, R_OK);
    if (ret != 0 && errno == ENOENT) {
        prog_args.push_back((char*)"-e");
    }
    ret = access(XT_BPF_INGRESS_PROG_PATH, R_OK);
    if (ret != 0 && errno == ENOENT) {
        prog_args.push_back((char*)"-p");
    }
    ret = access(XT_BPF_EGRESS_PROG_PATH, R_OK);
    if (ret != 0 && errno == ENOENT) {
        prog_args.push_back((char*)"-m");
    }
    ret = access(XT_BPF_WHITELIST_PROG_PATH, R_OK);
    if (ret != 0 && errno == ENOENT) {
        prog_args.push_back((char*)"-w");
    }
    ret = access(XT_BPF_BLACKLIST_PROG_PATH, R_OK);
    if (ret != 0 && errno == ENOENT) {
        prog_args.push_back((char*)"-b");
    }

    if (prog_args.size() == 1) {
        // all program are loaded already.
        return netdutils::status::ok;
    }

    prog_args.push_back(nullptr);
    ret = android_fork_execvp(prog_args.size(), (char**)prog_args.data(), status, false, true);
    if (ret) {
        ret = errno;
        ALOGE("failed to execute %s: %s", prog_args[0], strerror(errno));
        return statusFromErrno(ret, "run bpf loader failed");
    }
    return netdutils::status::ok;
}

int TrafficController::tagSocket(int sockFd, uint32_t tag, uid_t uid) {
    if (!ebpfSupported) {
        if (legacy_tagSocket(sockFd, tag, uid)) return -errno;
        return 0;
    }

    uint64_t sock_cookie = getSocketCookie(sockFd);
    if (sock_cookie == NONEXISTENT_COOKIE) return -errno;
    UidTag newKey = {.uid = (uint32_t)uid, .tag = tag};

    // Update the tag information of a socket to the cookieUidMap. Use BPF_ANY
    // flag so it will insert a new entry to the map if that value doesn't exist
    // yet. And update the tag if there is already a tag stored. Since the eBPF
    // program in kernel only read this map, and is protected by rcu read lock. It
    // should be fine to cocurrently update the map while eBPF program is running.
    Status res = mCookieTagMap.writeValue(sock_cookie, newKey, BPF_ANY);
    if (!isOk(res)) {
        ALOGE("Failed to tag the socket: %s, fd: %d", strerror(res.code()),
              mCookieTagMap.getMap().get());
    }
    return -res.code();
}

int TrafficController::untagSocket(int sockFd) {
    if (!ebpfSupported) {
        if (legacy_untagSocket(sockFd)) return -errno;
        return 0;
    }
    uint64_t sock_cookie = getSocketCookie(sockFd);

    if (sock_cookie == NONEXISTENT_COOKIE) return -errno;
    Status res = mCookieTagMap.deleteValue(sock_cookie);
    if (!isOk(res)) {
        ALOGE("Failed to untag socket: %s\n", strerror(res.code()));
    }
    return -res.code();
}

int TrafficController::setCounterSet(int counterSetNum, uid_t uid) {
    if (counterSetNum < 0 || counterSetNum >= OVERFLOW_COUNTERSET) return -EINVAL;
    Status res;
    if (!ebpfSupported) {
        if (legacy_setCounterSet(counterSetNum, uid)) return -errno;
        return 0;
    }

    // The default counter set for all uid is 0, so deleting the current counterset for that uid
    // will automatically set it to 0.
    if (counterSetNum == 0) {
        Status res = mUidCounterSetMap.deleteValue(uid);
        if (isOk(res) || (!isOk(res) && res.code() == ENOENT)) {
            return 0;
        } else {
            ALOGE("Failed to delete the counterSet: %s\n", strerror(res.code()));
            return -res.code();
        }
    }
    uint8_t tmpCounterSetNum = (uint8_t)counterSetNum;
    res = mUidCounterSetMap.writeValue(uid, tmpCounterSetNum, BPF_ANY);
    if (!isOk(res)) {
        ALOGE("Failed to set the counterSet: %s, fd: %d", strerror(res.code()),
              mUidCounterSetMap.getMap().get());
        return -res.code();
    }
    return 0;
}

int TrafficController::deleteTagData(uint32_t tag, uid_t uid) {

    if (!ebpfSupported) {
        if (legacy_deleteTagData(tag, uid)) return -errno;
        return 0;
    }

    // First we go through the cookieTagMap to delete the target uid tag combination. Or delete all
    // the tags related to the uid if the tag is 0.
    const auto deleteMatchedCookieEntries = [uid, tag](const uint64_t& key, const UidTag& value,
                                                       BpfMap<uint64_t, UidTag>& map) {
        if (value.uid == uid && (value.tag == tag || tag == 0)) {
            Status res = map.deleteValue(key);
            if (isOk(res) || (res.code() == ENOENT)) {
                return netdutils::status::ok;
            }
            ALOGE("Failed to delete data(cookie = %" PRIu64 "): %s\n", key, strerror(res.code()));
        }
        // Move forward to next cookie in the map.
        return netdutils::status::ok;
    };
    mCookieTagMap.iterateWithValue(deleteMatchedCookieEntries);
    // Now we go through the Tag stats map and delete the data entry with correct uid and tag
    // combination. Or all tag stats under that uid if the target tag is 0.
    const auto deleteMatchedUidTagEntries = [uid, tag](const StatsKey& key,
                                                       BpfMap<StatsKey, StatsValue>& map) {
        if (key.uid == uid && (key.tag == tag || tag == 0)) {
            Status res = map.deleteValue(key);
            if (isOk(res) || (res.code() == ENOENT)) {
                //Entry is deleted, use the current key to get a new nextKey;
                return netdutils::status::ok;
            }
            ALOGE("Failed to delete data(uid=%u, tag=%u): %s\n", key.uid, key.tag,
                  strerror(res.code()));
        }
        return netdutils::status::ok;
    };
    mTagStatsMap.iterate(deleteMatchedUidTagEntries);
    // If the tag is not zero, we already deleted all the data entry required. If tag is 0, we also
    // need to delete the stats stored in uidStatsMap and counterSet map.
    if (tag != 0) return 0;

    Status res = mUidCounterSetMap.deleteValue(uid);
    if (!isOk(res) && res.code() != ENOENT) {
        ALOGE("Failed to delete counterSet data(uid=%u, tag=%u): %s\n", uid, tag,
              strerror(res.code()));
    }
    mUidStatsMap.iterate(deleteMatchedUidTagEntries);

    auto deleteAppUidStatsEntry = [uid](const uint32_t& key, BpfMap<uint32_t, StatsValue>& map) {
        if (key == uid) {
            Status res = map.deleteValue(key);
            if (isOk(res) || (res.code() == ENOENT)) {
                return netdutils::status::ok;
            }
            ALOGE("Failed to delete data(uid=%u): %s", key, strerror(res.code()));
        }
        return netdutils::status::ok;
    };
    mAppUidStatsMap.iterate(deleteAppUidStatsEntry);
    return 0;
}

int TrafficController::addInterface(const char* name, uint32_t ifaceIndex) {
    if (!ebpfSupported) return 0;

    IfaceValue iface;
    if (ifaceIndex == 0) {
        ALOGE("Unknown interface %s(%d)", name, ifaceIndex);
        return -1;
    }

    strlcpy(iface.name, name, sizeof(IfaceValue));
    Status res = mIfaceIndexNameMap.writeValue(ifaceIndex, iface, BPF_ANY);
    if (!isOk(res)) {
        ALOGE("Failed to add iface %s(%d): %s", name, ifaceIndex, strerror(res.code()));
        return -res.code();
    }
    return 0;
}

Status TrafficController::updateOwnerMapEntry(BpfMap<uint32_t, uint8_t>& map, uid_t uid,
                                              FirewallRule rule, FirewallType type) {
    if (uid == UID_MAP_ENABLED) {
        return statusFromErrno(-EINVAL, "This uid is reserved for map state");
    }

    if ((rule == ALLOW && type == WHITELIST) || (rule == DENY && type == BLACKLIST)) {
        uint8_t flag = (type == WHITELIST) ? BPF_PASS : BPF_DROP;
        RETURN_IF_NOT_OK(map.writeValue(uid, flag, BPF_ANY));
    } else if ((rule == ALLOW && type == BLACKLIST) || (rule == DENY && type == WHITELIST)) {
        RETURN_IF_NOT_OK(map.deleteValue(uid));
    } else {
        //Cannot happen.
        return statusFromErrno(-EINVAL, "");
    }
    return netdutils::status::ok;
}

BandwithMatchType TrafficController::jumpOpToMatch(BandwidthController::IptJumpOp jumpHandling) {
    switch (jumpHandling) {
        case BandwidthController::IptJumpReject:
            return BLACKLISTMATCH;
        case BandwidthController::IptJumpReturn:
            return WHITELISTMATCH;
        case BandwidthController::IptJumpNoAdd:
            return NO_MATCH;
    }
}

Status TrafficController::updateBandwidthUidMap(const std::vector<std::string>& appStrUids,
                                                BandwidthController::IptJumpOp jumpHandling,
                                                BandwidthController::IptOp op) {
    uint8_t command = jumpOpToMatch(jumpHandling);
    if (command == NO_MATCH) {
        return statusFromErrno(EINVAL, StringPrintf("invalid IptJumpOp: %d, command: %d",
                                                    jumpHandling, command));
    }
    for (const auto& appStrUid : appStrUids) {
        char* endPtr;
        long uid = strtol(appStrUid.c_str(), &endPtr, 10);
        if ((errno == ERANGE && (uid == LONG_MAX || uid == LONG_MIN)) ||
            (endPtr == appStrUid.c_str()) || (*endPtr != '\0')) {
               return statusFromErrno(errno, "invalid uid string:" + appStrUid);
        }

        auto match = mBandwidthUidMap.readValue(uid);
        if (op == BandwidthController::IptOpDelete) {
            if(!isOk(match)) {
                return statusFromErrno(EINVAL, StringPrintf("uid(%ld): %s does not exist in map",
                                                            uid, appStrUid.c_str()));
            }
            uint8_t newValue = match.value() & ~command;
            if (newValue == 0) {
                RETURN_IF_NOT_OK(mBandwidthUidMap.deleteValue((uint32_t)uid));
            } else {
                RETURN_IF_NOT_OK(mBandwidthUidMap.writeValue((uint32_t)uid, newValue, BPF_ANY));
            }
        } else if (op == BandwidthController::IptOpInsert) {
            uint8_t newValue = command;
            if (isOk(match)) {
                newValue |= match.value();
            }
            RETURN_IF_NOT_OK(mBandwidthUidMap.writeValue((uint32_t)uid, newValue, BPF_ANY));
        } else {
            // Cannot happen.
            return statusFromErrno(EINVAL, StringPrintf("invalid IptOp: %d, %d", op, command));
        }
    }
    return netdutils::status::ok;
}

int TrafficController::changeUidOwnerRule(ChildChain chain, uid_t uid, FirewallRule rule,
                                          FirewallType type) {
    std::lock_guard<std::mutex> guard(mOwnerMatchMutex);
    if (!ebpfSupported) {
        ALOGE("bpf is not set up, should use iptables rule");
        return -ENOSYS;
    }
    Status res;
    switch (chain) {
        case DOZABLE:
            res = updateOwnerMapEntry(mDozableUidMap, uid, rule, type);
            break;
        case STANDBY:
            res = updateOwnerMapEntry(mStandbyUidMap, uid, rule, type);
            break;
        case POWERSAVE:
            res = updateOwnerMapEntry(mPowerSaveUidMap, uid, rule, type);
            break;
        case NONE:
        default:
            return -EINVAL;
    }
    if (!isOk(res)) {
        ALOGE("change uid(%u) rule of %d failed: %s, rule: %d, type: %d", uid, chain,
              res.msg().c_str(), rule, type);
        return -res.code();
    }
    return 0;
}

Status TrafficController::replaceUidsInMap(BpfMap<uint32_t, uint8_t>& map,
                                           const std::vector<int32_t>& uids, FirewallRule rule,
                                           FirewallType type) {
    std::set<int32_t> uidSet(uids.begin(), uids.end());
    std::vector<uint32_t> uidsToDelete;
    auto getUidsToDelete = [&uidsToDelete, &uidSet](const uint32_t& key,
                                                    const BpfMap<uint32_t, uint8_t>&) {
        if (key != UID_MAP_ENABLED && uidSet.find((int32_t)key) == uidSet.end()) {
            uidsToDelete.push_back(key);
        }
        return netdutils::status::ok;
    };
    RETURN_IF_NOT_OK(map.iterate(getUidsToDelete));

    for(auto uid : uidsToDelete) {
        RETURN_IF_NOT_OK(map.deleteValue(uid));
    }

    for (auto uid : uids) {
        RETURN_IF_NOT_OK(updateOwnerMapEntry(map, uid, rule, type));
    }
    return netdutils::status::ok;
}

int TrafficController::replaceUidOwnerMap(const std::string& name, bool isWhitelist,
                                          const std::vector<int32_t>& uids) {
    std::lock_guard<std::mutex> guard(mOwnerMatchMutex);
    FirewallRule rule;
    FirewallType type;
    if (isWhitelist) {
        type = WHITELIST;
        rule = ALLOW;
    } else {
        type = BLACKLIST;
        rule = DENY;
    }
    Status res;
    if (!name.compare(FirewallController::LOCAL_DOZABLE)) {
        res = replaceUidsInMap(mDozableUidMap, uids, rule, type);
    } else if (!name.compare(FirewallController::LOCAL_STANDBY)) {
        res = replaceUidsInMap(mStandbyUidMap, uids, rule, type);
    } else if (!name.compare(FirewallController::LOCAL_POWERSAVE)) {
        res = replaceUidsInMap(mPowerSaveUidMap, uids, rule, type);
    } else {
        ALOGE("unknown chain name: %s", name.c_str());
        return -EINVAL;
    }
    if (!isOk(res)) {
        ALOGE("Failed to clean up chain: %s: %s", name.c_str(), res.msg().c_str());
        return -res.code();
    }
    return 0;
}

int TrafficController::toggleUidOwnerMap(ChildChain chain, bool enable) {
    std::lock_guard<std::mutex> guard(mOwnerMatchMutex);
    uint32_t keyUid = UID_MAP_ENABLED;
    uint8_t mapState = enable ? 1 : 0;
    Status res;
    switch (chain) {
        case DOZABLE:
            res = mDozableUidMap.writeValue(keyUid, mapState, BPF_EXIST);
            break;
        case STANDBY:
            res = mStandbyUidMap.writeValue(keyUid, mapState, BPF_EXIST);
            break;
        case POWERSAVE:
            res = mPowerSaveUidMap.writeValue(keyUid, mapState, BPF_EXIST);
            break;
        default:
            return -EINVAL;
    }
    if (!isOk(res)) {
        ALOGE("Failed to toggleUidOwnerMap(%d): %s", chain, res.msg().c_str());
    }
    return -res.code();
}

bool TrafficController::checkBpfStatsEnable() {
    return ebpfSupported;
}

std::string getProgramStatus(const char *path) {
    int ret = access(path, R_OK);
    if (ret == 0) {
        return StringPrintf("OK");
    }
    if (ret != 0 && errno == ENOENT) {
        return StringPrintf("program is missing at: %s", path);
    }
    return StringPrintf("check Program %s error: %s", path, strerror(errno));
}

std::string getMapStatus(const base::unique_fd& map_fd, const char* path) {
    if (map_fd.get() < 0) {
        return StringPrintf("map fd lost");
    }
    if (access(path, F_OK) != 0) {
        return StringPrintf("map not pinned to location: %s", path);
    }
    return StringPrintf("OK");
}

void dumpBpfMap(const std::string& mapName, DumpWriter& dw, const std::string& header) {
    dw.blankline();
    dw.println("%s:", mapName.c_str());
    if (!header.empty()) {
        dw.println(header);
    }
}

const String16 TrafficController::DUMP_KEYWORD = String16("trafficcontroller");

void TrafficController::dump(DumpWriter& dw, bool verbose) {
    std::lock_guard<std::mutex> ownerMapGuard(mOwnerMatchMutex);
    ScopedIndent indentTop(dw);
    dw.println("TrafficController");

    ScopedIndent indentPreBpfModule(dw);
    dw.println("BPF module status: %s", ebpfSupported? "ON" : "OFF");

    if (!ebpfSupported) {
        return;
    }

    dw.blankline();
    dw.println("mCookieTagMap status: %s",
               getMapStatus(mCookieTagMap.getMap(), COOKIE_TAG_MAP_PATH).c_str());
    dw.println("mUidCounterSetMap status: %s",
               getMapStatus(mUidCounterSetMap.getMap(), UID_COUNTERSET_MAP_PATH).c_str());
    dw.println("mAppUidStatsMap status: %s",
               getMapStatus(mAppUidStatsMap.getMap(), APP_UID_STATS_MAP_PATH).c_str());
    dw.println("mUidStatsMap status: %s",
               getMapStatus(mUidStatsMap.getMap(), UID_STATS_MAP_PATH).c_str());
    dw.println("mTagStatsMap status: %s",
               getMapStatus(mTagStatsMap.getMap(), TAG_STATS_MAP_PATH).c_str());
    dw.println("mIfaceIndexNameMap status: %s",
               getMapStatus(mIfaceIndexNameMap.getMap(), IFACE_INDEX_NAME_MAP_PATH).c_str());
    dw.println("mIfaceStatsMap status: %s",
               getMapStatus(mIfaceStatsMap.getMap(), IFACE_STATS_MAP_PATH).c_str());
    dw.println("mDozableUidMap status: %s",
               getMapStatus(mDozableUidMap.getMap(), DOZABLE_UID_MAP_PATH).c_str());
    dw.println("mStandbyUidMap status: %s",
               getMapStatus(mStandbyUidMap.getMap(), STANDBY_UID_MAP_PATH).c_str());
    dw.println("mPowerSaveUidMap status: %s",
               getMapStatus(mPowerSaveUidMap.getMap(), POWERSAVE_UID_MAP_PATH).c_str());
    dw.println("mBandwidthUidMap status: %s",
               getMapStatus(mBandwidthUidMap.getMap(), BANDWIDTH_UID_MAP_PATH).c_str());

    dw.blankline();
    dw.println("Cgroup ingress program status: %s",
               getProgramStatus(BPF_INGRESS_PROG_PATH).c_str());
    dw.println("Cgroup egress program status: %s", getProgramStatus(BPF_EGRESS_PROG_PATH).c_str());
    dw.println("xt_bpf ingress program status: %s",
               getProgramStatus(XT_BPF_INGRESS_PROG_PATH).c_str());
    dw.println("xt_bpf egress program status: %s",
               getProgramStatus(XT_BPF_EGRESS_PROG_PATH).c_str());
    dw.println("xt_bpf bandwidth whitelist program status: %s",
               getProgramStatus(XT_BPF_WHITELIST_PROG_PATH).c_str());
    dw.println("xt_bpf bandwidth blacklist program status: %s",
               getProgramStatus(XT_BPF_BLACKLIST_PROG_PATH).c_str());

    if (!verbose) {
        return;
    }

    dw.blankline();
    dw.println("BPF map content:");

    ScopedIndent indentForMapContent(dw);

    // Print CookieTagMap content.
    dumpBpfMap("mCookieTagMap", dw, "");
    const auto printCookieTagInfo = [&dw](const uint64_t& key, const UidTag& value,
                                          const BpfMap<uint64_t, UidTag>&) {
        dw.println("cookie=%" PRIu64 " tag=0x%x uid=%u", key, value.tag, value.uid);
        return netdutils::status::ok;
    };
    Status res = mCookieTagMap.iterateWithValue(printCookieTagInfo);
    if (!isOk(res)) {
        dw.println("mCookieTagMap print end with error: %s", res.msg().c_str());
    }

    // Print UidCounterSetMap Content
    dumpBpfMap("mUidCounterSetMap", dw, "");
    const auto printUidInfo = [&dw](const uint32_t& key, const uint8_t& value,
                                    const BpfMap<uint32_t, uint8_t>&) {
        dw.println("%u %u", key, value);
        return netdutils::status::ok;
    };
    res = mUidCounterSetMap.iterateWithValue(printUidInfo);
    if (!isOk(res)) {
        dw.println("mUidCounterSetMap print end with error: %s", res.msg().c_str());
    }

    // Print AppUidStatsMap content
    std::string appUidStatsHeader = StringPrintf("uid rxBytes rxPackets txBytes txPackets");
    dumpBpfMap("mAppUidStatsMap:", dw, appUidStatsHeader);
    auto printAppUidStatsInfo = [&dw](const uint32_t& key, const StatsValue& value,
                                      const BpfMap<uint32_t, StatsValue>&) {
        dw.println("%u %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64, key, value.rxBytes,
                   value.rxPackets, value.txBytes, value.txPackets);
        return netdutils::status::ok;
    };
    res = mAppUidStatsMap.iterateWithValue(printAppUidStatsInfo);
    if (!res.ok()) {
        dw.println("mAppUidStatsMap print end with error: %s", res.msg().c_str());
    }

    // Print uidStatsMap content
    std::string statsHeader = StringPrintf("ifaceIndex ifaceName tag_hex uid_int cnt_set rxBytes"
                                           " rxPackets txBytes txPackets");
    dumpBpfMap("mUidStatsMap", dw, statsHeader);
    const auto printStatsInfo = [&dw, this](const StatsKey& key, const StatsValue& value,
                                            const BpfMap<StatsKey, StatsValue>&) {
        uint32_t ifIndex = key.ifaceIndex;
        auto ifname = mIfaceIndexNameMap.readValue(ifIndex);
        if (!isOk(ifname)) {
            strlcpy(ifname.value().name, "unknown", sizeof(IfaceValue));
        }
        dw.println("%u %s 0x%x %u %u %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64, ifIndex,
                   ifname.value().name, key.tag, key.uid, key.counterSet, value.rxBytes,
                   value.rxPackets, value.txBytes, value.txPackets);
        return netdutils::status::ok;
    };
    res = mUidStatsMap.iterateWithValue(printStatsInfo);
    if (!isOk(res)) {
        dw.println("mUidStatsMap print end with error: %s", res.msg().c_str());
    }

    // Print TagStatsMap content.
    dumpBpfMap("mTagStatsMap", dw, statsHeader);
    res = mTagStatsMap.iterateWithValue(printStatsInfo);
    if (!isOk(res)) {
        dw.println("mTagStatsMap print end with error: %s", res.msg().c_str());
    }

    // Print ifaceIndexToNameMap content.
    dumpBpfMap("mIfaceIndexNameMap", dw, "");
    const auto printIfaceNameInfo = [&dw](const uint32_t& key, const IfaceValue& value,
                                          const BpfMap<uint32_t, IfaceValue>&) {
        const char* ifname = value.name;
        dw.println("ifaceIndex=%u ifaceName=%s", key, ifname);
        return netdutils::status::ok;
    };
    res = mIfaceIndexNameMap.iterateWithValue(printIfaceNameInfo);
    if (!isOk(res)) {
        dw.println("mIfaceIndexNameMap print end with error: %s", res.msg().c_str());
    }

    // Print ifaceStatsMap content
    std::string ifaceStatsHeader = StringPrintf("ifaceIndex ifaceName rxBytes rxPackets txBytes"
                                                " txPackets");
    dumpBpfMap("mIfaceStatsMap:", dw, ifaceStatsHeader);
    const auto printIfaceStatsInfo = [&dw, this](const uint32_t& key, const StatsValue& value,
                                                 const BpfMap<uint32_t, StatsValue>&) {
        auto ifname = mIfaceIndexNameMap.readValue(key);
        if (!isOk(ifname)) {
            strlcpy(ifname.value().name, "unknown", sizeof(IfaceValue));
        }
        dw.println("%u %s %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64, key, ifname.value().name,
                   value.rxBytes, value.rxPackets, value.txBytes, value.txPackets);
        return netdutils::status::ok;
    };
    res = mIfaceStatsMap.iterateWithValue(printIfaceStatsInfo);
    if (!isOk(res)) {
        dw.println("mIfaceStatsMap print end with error: %s", res.msg().c_str());
    }

    // Print owner match uid maps
    dumpBpfMap("mDozableUidMap", dw, "");
    res = mDozableUidMap.iterateWithValue(printUidInfo);
    if (!isOk(res)) {
        dw.println("mDozableUidMap print end with error: %s", res.msg().c_str());
    }

    dumpBpfMap("mStandbyUidMap", dw, "");
    res = mStandbyUidMap.iterateWithValue(printUidInfo);
    if (!isOk(res)) {
        dw.println("mDozableUidMap print end with error: %s", res.msg().c_str());
    }

    dumpBpfMap("mPowerSaveUidMap", dw, "");
    res = mPowerSaveUidMap.iterateWithValue(printUidInfo);
    if (!isOk(res)) {
        dw.println("mDozableUidMap print end with error: %s", res.msg().c_str());
    }

    dumpBpfMap("mBandwidthUidMap", dw, "");
    res = mBandwidthUidMap.iterateWithValue(printUidInfo);
    if (!isOk(res)) {
        dw.println("mBandwidthUidMap print end with error: %s", res.msg().c_str());
    }
}

}  // namespace net
}  // namespace android
