/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#define LOG_TAG "Netd"

#include <log/log.h>

#include <android-base/parseint.h>
#include <android-base/strings.h>
#include <netutils/ifc.h>
#include <sysutils/NetlinkEvent.h>
#include "Controllers.h"
#include "NetlinkHandler.h"
#include "NetlinkManager.h"
#include "SockDiag.h"

#include <charconv>

#define BINDER_RETRY(exp)                                                       \
    ({                                                                          \
        bool res = true;                                                        \
        for (int attempt = 0; /*nop*/; ++attempt) {                             \
            auto _rc = (exp);                                                   \
            if (_rc.exceptionCode() == binder::Status::EX_TRANSACTION_FAILED && \
                attempt < RETRY_ATTEMPTS) {                                     \
                usleep(RETRY_INTERVAL_MICRO_S);                                 \
            } else {                                                            \
                res = _rc.isOk();                                               \
                break;                                                          \
            }                                                                   \
        }                                                                       \
        res;                                                                    \
    })

#define LOG_EVENT_FUNC(retry, func, ...)                                                    \
    do {                                                                                    \
        const auto listenerMap = gCtls->eventReporter.getNetdUnsolicitedEventListenerMap(); \
        for (auto& listener : listenerMap) {                                                \
            auto entry = gUnsolicitedLog.newEntry().function(#func).args(__VA_ARGS__);      \
            if (retry(listener.first->func(__VA_ARGS__))) {                                 \
                gUnsolicitedLog.log(entry.withAutomaticDuration());                         \
            }                                                                               \
        }                                                                                   \
    } while (0)

namespace android {
namespace net {

constexpr int RETRY_ATTEMPTS = 2;
constexpr int RETRY_INTERVAL_MICRO_S = 100000;

NetlinkHandler::NetlinkHandler(NetlinkManager *nm, int listenerSocket,
                               int format) :
                        NetlinkListener(listenerSocket, format) {
    mNm = nm;
}

NetlinkHandler::~NetlinkHandler() {
}

int NetlinkHandler::start() {
    return this->startListener();
}

int NetlinkHandler::stop() {
    return this->stopListener();
}

static long parseIfIndex(const char* ifIndex) {
    if (ifIndex == nullptr) {
        return 0;
    }
    long ifaceIndex = strtol(ifIndex, nullptr, 10);
    // strtol returns 0 on error, which is fine because 0 is not a valid ifindex.
    if (errno == ERANGE && (ifaceIndex == LONG_MAX || ifaceIndex == LONG_MIN)) {
        return 0;
    }
    return ifaceIndex;
}

void NetlinkHandler::onEvent(NetlinkEvent *evt) {
    const char *subsys = evt->getSubsystem();
    if (!subsys) {
        ALOGW("No subsystem found in netlink event");
        return;
    }

    if (!strcmp(subsys, "net")) {
        NetlinkEvent::Action action = evt->getAction();
        const char *iface = evt->findParam("INTERFACE") ?: "";
        if (action == NetlinkEvent::Action::kAdd) {
            notifyInterfaceAdded(iface);
        } else if (action == NetlinkEvent::Action::kRemove) {
            notifyInterfaceRemoved(iface);
        } else if (action == NetlinkEvent::Action::kChange) {
            evt->dump();
            notifyInterfaceChanged("nana", true);
        } else if (action == NetlinkEvent::Action::kLinkUp) {
            notifyInterfaceLinkChanged(iface, true);
        } else if (action == NetlinkEvent::Action::kLinkDown) {
            notifyInterfaceLinkChanged(iface, false);
        } else if (action == NetlinkEvent::Action::kAddressUpdated ||
                   action == NetlinkEvent::Action::kAddressRemoved) {
            const char *address = evt->findParam("ADDRESS");
            const char *flags = evt->findParam("FLAGS");
            const char *scope = evt->findParam("SCOPE");
            const char *ifIndex = evt->findParam("IFINDEX");
            char addrstr[INET6_ADDRSTRLEN + strlen("/128")];
            strlcpy(addrstr, address, sizeof(addrstr));
            char *slash = strchr(addrstr, '/');
            if (slash) {
                *slash = '\0';
            }

            long ifaceIndex = parseIfIndex(ifIndex);
            if (!ifaceIndex) {
                ALOGE("invalid interface index: %s(%s)", iface, ifIndex);
            }
            const bool addrUpdated = (action == NetlinkEvent::Action::kAddressUpdated);
            if (addrUpdated) {
                gCtls->netCtrl.addInterfaceAddress(ifaceIndex, address);
            } else {  // action == NetlinkEvent::Action::kAddressRemoved
                bool shouldDestroy = gCtls->netCtrl.removeInterfaceAddress(ifaceIndex, address);
                if (shouldDestroy) {
                    SockDiag sd;
                    if (sd.open()) {
                        // Pass the interface index iff. destroying sockets on a link-local address.
                        // This cannot use an interface name as the interface might no longer exist.
                        int destroyIfaceIndex =
                                std::string_view(addrstr).starts_with("fe80:") ? ifaceIndex : 0;
                        int ret = sd.destroySockets(addrstr, destroyIfaceIndex);
                        if (ret < 0) {
                            ALOGE("Error destroying sockets: %s", strerror(-ret));
                        }
                    } else {
                        ALOGE("Error opening NETLINK_SOCK_DIAG socket: %s", strerror(errno));
                    }
                }
            }
            // Note: if this interface was deleted, iface is "" and we don't notify.
            if (iface && iface[0] && address && flags && scope) {
                if (addrUpdated) {
                    notifyAddressUpdated(address, iface, std::stoi(flags), std::stoi(scope));
                } else {
                    notifyAddressRemoved(address, iface, std::stoi(flags), std::stoi(scope));
                }
            }
        } else if (action == NetlinkEvent::Action::kRdnss) {
            const char *lifetime = evt->findParam("LIFETIME");
            const char *servers = evt->findParam("SERVERS");
            if (lifetime && servers) {
                notifyInterfaceDnsServers(iface, strtol(lifetime, nullptr, 10),
                                          android::base::Split(servers, ","));
            }
        } else if (action == NetlinkEvent::Action::kRouteUpdated ||
                   action == NetlinkEvent::Action::kRouteRemoved) {
            const char *route = evt->findParam("ROUTE");
            const char *gateway = evt->findParam("GATEWAY");
            const char *iface = evt->findParam("INTERFACE");
            if (route && (gateway || iface)) {
                notifyRouteChange((action == NetlinkEvent::Action::kRouteUpdated) ? true : false,
                                  route, (gateway == nullptr) ? "" : gateway,
                                  (iface == nullptr) ? "" : iface);
            }
        }

    } else if (!strcmp(subsys, "qlog") || !strcmp(subsys, "xt_quota2")) {
        const char *alertName = evt->findParam("ALERT_NAME");
        const char *iface = evt->findParam("INTERFACE");
        if (alertName && iface) {
            notifyQuotaLimitReached(alertName, iface);
        }

    } else if (!strcmp(subsys, "strict")) {
        const char *uid = evt->findParam("UID");
        const char *hex = evt->findParam("HEX");
        if (uid && hex) {
            notifyStrictCleartext(strtol(uid, nullptr, 10), hex);
        }

    } else if (!strcmp(subsys, "xt_idletimer")) {
        const char *label = evt->findParam("INTERFACE");
        const char *state = evt->findParam("STATE");
        const char *timestamp = evt->findParam("TIME_NS");
        const char *uid = evt->findParam("UID");
        if (state) {
            bool isActive = !strcmp("active", state);
            int64_t processTimestamp = (timestamp == nullptr) ? 0 : strtoll(timestamp, nullptr, 10);
            int intLabel;
            // NMS only accepts interface class activity changes with integer labels, and only ever
            // creates idletimers with integer labels.
            if (android::base::ParseInt(label, &intLabel)) {
                const long reportedUid =
                        (uid != nullptr && isActive) ? strtol(uid, nullptr, 10) : -1;
                notifyInterfaceClassActivityChanged(intLabel, isActive, processTimestamp,
                                                    reportedUid);
            }
        }

#if !LOG_NDEBUG
    } else if (strcmp(subsys, "platform") && strcmp(subsys, "backlight")) {
        /* It is not a VSYNC or a backlight event */
        ALOGV("unexpected event from subsystem %s", subsys);
#endif
    }
}

void NetlinkHandler::notifyInterfaceAdded(const std::string& ifName) {
    LOG_EVENT_FUNC(BINDER_RETRY, onInterfaceAdded, ifName);
}

void NetlinkHandler::notifyInterfaceRemoved(const std::string& ifName) {
    LOG_EVENT_FUNC(BINDER_RETRY, onInterfaceRemoved, ifName);
}

void NetlinkHandler::notifyInterfaceChanged(const std::string& ifName, bool up) {
    LOG_EVENT_FUNC(BINDER_RETRY, onInterfaceChanged, ifName, up);
}

void NetlinkHandler::notifyInterfaceLinkChanged(const std::string& ifName, bool up) {
    LOG_EVENT_FUNC(BINDER_RETRY, onInterfaceLinkStateChanged, ifName, up);
}

void NetlinkHandler::notifyQuotaLimitReached(const std::string& labelName,
                                             const std::string& ifName) {
    LOG_EVENT_FUNC(BINDER_RETRY, onQuotaLimitReached, labelName, ifName);
}

void NetlinkHandler::notifyInterfaceClassActivityChanged(int label, bool isActive,
                                                         int64_t timestamp, int uid) {
    LOG_EVENT_FUNC(BINDER_RETRY, onInterfaceClassActivityChanged, isActive, label, timestamp, uid);
}

void NetlinkHandler::notifyAddressUpdated(const std::string& addr, const std::string& ifName,
                                          int flags, int scope) {
    LOG_EVENT_FUNC(BINDER_RETRY, onInterfaceAddressUpdated, addr, ifName, flags, scope);
}

void NetlinkHandler::notifyAddressRemoved(const std::string& addr, const std::string& ifName,
                                          int flags, int scope) {
    LOG_EVENT_FUNC(BINDER_RETRY, onInterfaceAddressRemoved, addr, ifName, flags, scope);
}

void NetlinkHandler::notifyInterfaceDnsServers(const std::string& ifName, int64_t lifetime,
                                               const std::vector<std::string>& servers) {
    LOG_EVENT_FUNC(BINDER_RETRY, onInterfaceDnsServerInfo, ifName, lifetime, servers);
}

void NetlinkHandler::notifyRouteChange(bool updated, const std::string& route,
                                       const std::string& gateway, const std::string& ifName) {
    LOG_EVENT_FUNC(BINDER_RETRY, onRouteChanged, updated, route, gateway, ifName);
}

void NetlinkHandler::notifyStrictCleartext(uid_t uid, const std::string& hex) {
    LOG_EVENT_FUNC(BINDER_RETRY, onStrictCleartextDetected, uid, hex);
}

}  // namespace net
}  // namespace android
