/*
 * Copyright (C) 2019 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 "resolv"

#include "ResolverController.h"

#include <set>
#include <string>
#include <vector>

#include <aidl/android/net/IDnsResolver.h>
#include <android-base/logging.h>
#include <android-base/strings.h>
#include <statslog_resolv.h>

#include "Dns64Configuration.h"
#include "DnsResolver.h"
#include "DnsTlsDispatcher.h"
#include "PrivateDnsConfiguration.h"
#include "ResolverEventReporter.h"
#include "ResolverStats.h"
#include "resolv_cache.h"
#include "stats.h"
#include "util.h"

using aidl::android::net::IDnsResolver;
using aidl::android::net::ResolverParamsParcel;
using aidl::android::net::resolv::aidl::IDnsResolverUnsolicitedEventListener;
using aidl::android::net::resolv::aidl::Nat64PrefixEventParcel;
using android::base::Join;
using android::net::ResolverStats;

namespace android {

using netdutils::DumpWriter;

namespace net {

namespace {

void sendNat64PrefixEvent(const Dns64Configuration::Nat64PrefixInfo& args) {
    LOG(DEBUG) << "Sending Nat64Prefix " << (args.added ? "added" : "removed") << " event on netId "
               << args.netId << " with prefix " << args.prefixString << "/"
               << (int)(args.prefixLength);
    // Send a nat64 prefix event to NetdEventListenerService.
    const auto& listeners = ResolverEventReporter::getInstance().getListeners();
    if (listeners.empty()) {
        LOG(ERROR) << __func__ << ": No available listener. Skipping NAT64 prefix event";
    }
    for (const auto& it : listeners) {
        it->onNat64PrefixEvent(args.netId, args.added, args.prefixString, args.prefixLength);
    }

    const auto& unsolEventListeners = ResolverEventReporter::getInstance().getUnsolEventListeners();
    const Nat64PrefixEventParcel nat64PrefixEvent = {
            .netId = static_cast<int32_t>(args.netId),
            .prefixOperation =
                    args.added ? IDnsResolverUnsolicitedEventListener::PREFIX_OPERATION_ADDED
                               : IDnsResolverUnsolicitedEventListener::PREFIX_OPERATION_REMOVED,
            .prefixAddress = args.prefixString,
            .prefixLength = args.prefixLength,
    };
    for (const auto& it : unsolEventListeners) {
        it->onNat64PrefixEvent(nat64PrefixEvent);
    }
}

int getDnsInfo(unsigned netId, std::vector<std::string>* servers, std::vector<std::string>* domains,
               res_params* params, std::vector<android::net::ResolverStats>* stats,
               std::vector<std::string>* interfaceNames, int* wait_for_pending_req_timeout_count) {
    static_assert(ResolverStats::STATS_SUCCESSES == IDnsResolver::RESOLVER_STATS_SUCCESSES &&
                          ResolverStats::STATS_ERRORS == IDnsResolver::RESOLVER_STATS_ERRORS &&
                          ResolverStats::STATS_TIMEOUTS == IDnsResolver::RESOLVER_STATS_TIMEOUTS &&
                          ResolverStats::STATS_INTERNAL_ERRORS ==
                                  IDnsResolver::RESOLVER_STATS_INTERNAL_ERRORS &&
                          ResolverStats::STATS_RTT_AVG == IDnsResolver::RESOLVER_STATS_RTT_AVG &&
                          ResolverStats::STATS_LAST_SAMPLE_TIME ==
                                  IDnsResolver::RESOLVER_STATS_LAST_SAMPLE_TIME &&
                          ResolverStats::STATS_USABLE == IDnsResolver::RESOLVER_STATS_USABLE &&
                          ResolverStats::STATS_COUNT == IDnsResolver::RESOLVER_STATS_COUNT,
                  "AIDL and ResolverStats.h out of sync");
    int nscount = -1;
    sockaddr_storage res_servers[MAXNS];
    int dcount = -1;
    char res_domains[MAXDNSRCH][MAXDNSRCHPATH];
    res_stats res_stats[MAXNS];
    servers->clear();
    domains->clear();
    interfaceNames->clear();
    *params = res_params{};
    stats->clear();
    int revision_id = android_net_res_stats_get_info_for_net(netId, &nscount, res_servers, &dcount,
                                                             res_domains, params, res_stats,
                                                             wait_for_pending_req_timeout_count);

    // If the netId is unknown (which can happen for valid net IDs for which no DNS servers have
    // yet been configured), there is no revision ID. In this case there is no data to return.
    if (revision_id < 0) {
        return 0;
    }

    // Verify that the returned data is valid.
    if (nscount < 0 || nscount > MAXNS || dcount < 0 || dcount > MAXDNSRCH) {
        LOG(ERROR) << __func__ << ": nscount = " << nscount << ", dcount = " << dcount;
        return -ENOTRECOVERABLE;
    }

    // Determine which servers are considered usable by the resolver.
    bool valid_servers[MAXNS];
    std::fill_n(valid_servers, MAXNS, false);
    android_net_res_stats_get_usable_servers(params, res_stats, nscount, valid_servers);

    // Convert the server sockaddr structures to std::string.
    stats->resize(nscount);
    for (int i = 0; i < nscount; ++i) {
        char hbuf[NI_MAXHOST];
        int rv =
                getnameinfo(reinterpret_cast<const sockaddr*>(&res_servers[i]),
                            sizeof(res_servers[i]), hbuf, sizeof(hbuf), nullptr, 0, NI_NUMERICHOST);
        std::string server_str;
        if (rv == 0) {
            server_str.assign(hbuf);
        } else {
            LOG(ERROR) << "getnameinfo() failed for server #" << i << ": " << gai_strerror(rv);
            server_str.assign("<invalid>");
        }
        servers->push_back(std::move(server_str));
        android::net::ResolverStats& cur_stats = (*stats)[i];
        android_net_res_stats_aggregate(&res_stats[i], &cur_stats.successes, &cur_stats.errors,
                                        &cur_stats.timeouts, &cur_stats.internal_errors,
                                        &cur_stats.rtt_avg, &cur_stats.last_sample_time);
        cur_stats.usable = valid_servers[i];
    }

    // Convert the stack-allocated search domain strings to std::string.
    for (int i = 0; i < dcount; ++i) {
        domains->push_back(res_domains[i]);
    }

    *interfaceNames = resolv_get_interface_names(netId);

    return 0;
}

}  // namespace

ResolverController::ResolverController()
    : mDns64Configuration(make_shared<Dns64Configuration>(
              gResNetdCallbacks.get_network_context,
              std::bind(sendNat64PrefixEvent, std::placeholders::_1))) {}

void ResolverController::destroyNetworkCache(unsigned netId) {
    LOG(VERBOSE) << __func__ << ": netId = " << netId;

    // Report NetworkDnsServerSupportReported metrics before the cleanup.
    auto& privateDnsConfiguration = PrivateDnsConfiguration::getInstance();
    NetworkDnsServerSupportReported event = privateDnsConfiguration.getStatusForMetrics(netId);
    const std::string str = event.servers().SerializeAsString();
    stats::BytesField bytesField{str.c_str(), str.size()};
    android::net::stats::stats_write(android::net::stats::NETWORK_DNS_SERVER_SUPPORT_REPORTED,
                                     event.network_type(), event.private_dns_modes(), bytesField);

    resolv_delete_cache_for_net(netId);
    mDns64Configuration->stopPrefixDiscovery(netId);
    privateDnsConfiguration.clear(netId);

    // Don't get this instance in PrivateDnsConfiguration. It's probe to deadlock.
    DnsTlsDispatcher::getInstance().forceCleanup(netId);
}

int ResolverController::createNetworkCache(unsigned netId) {
    LOG(VERBOSE) << __func__ << ": netId = " << netId;

    return resolv_create_cache_for_net(netId);
}

int ResolverController::flushNetworkCache(unsigned netId) {
    LOG(VERBOSE) << __func__ << ": netId = " << netId;
    return resolv_flush_cache_for_net(netId);
}

int ResolverController::setResolverConfiguration(const ResolverParamsParcel& resolverParams) {
    if (!has_named_cache(resolverParams.netId)) {
        return -ENOENT;
    }

    // Expect to get the mark with system permission.
    android_net_context netcontext;
    gResNetdCallbacks.get_network_context(resolverParams.netId, 0 /* uid */, &netcontext);

    // Allow at most MAXNS private DNS servers in a network to prevent too many broken servers.
    std::vector<std::string> tlsServers = resolverParams.tlsServers;
    if (tlsServers.size() > MAXNS) {
        tlsServers.resize(MAXNS);
    }

    // Use app_mark for DoT connection. Using dns_mark might result in reaching the DoT servers
    // through a different network. For example, on a VPN with no DNS servers (Do53), if the VPN
    // applies to UID 0, dns_mark is assigned for default network rathan the VPN. (note that it's
    // possible that a VPN doesn't have any DNS servers but DoT servers in DNS strict mode)
    auto& privateDnsConfiguration = PrivateDnsConfiguration::getInstance();
    int err = privateDnsConfiguration.set(
            resolverParams.netId, netcontext.app_mark, resolverParams.servers, tlsServers,
            resolverParams.tlsName, resolverParams.caCertificate, resolverParams.dohParams);

    if (err != 0) {
        return err;
    }

    if (is_mdns_supported_transport_types(resolverParams.transportTypes)) {
        if (err = resolv_stats_set_addrs(resolverParams.netId, PROTO_MDNS,
                                         {"ff02::fb", "224.0.0.251"}, 5353);
            err != 0) {
            return err;
        }
    }

    return resolv_set_nameservers(resolverParams);
}

int ResolverController::getResolverInfo(int32_t netId, std::vector<std::string>* servers,
                                        std::vector<std::string>* domains,
                                        std::vector<std::string>* tlsServers,
                                        std::vector<std::string>* interfaceNames,
                                        std::vector<int32_t>* params, std::vector<int32_t>* stats,
                                        int* wait_for_pending_req_timeout_count) {
    res_params res_params;
    std::vector<ResolverStats> res_stats;
    int ret = getDnsInfo(netId, servers, domains, &res_params, &res_stats, interfaceNames,
                         wait_for_pending_req_timeout_count);
    if (ret != 0) {
        return ret;
    }

    // Serialize the information for binder.
    ResolverStats::encodeAll(res_stats, stats);

    const auto privateDnsStatus = PrivateDnsConfiguration::getInstance().getStatus(netId);
    for (const auto& [server, _] : privateDnsStatus.dotServersMap) {
        tlsServers->push_back(server.toIpString());
    }

    params->resize(IDnsResolver::RESOLVER_PARAMS_COUNT);
    (*params)[IDnsResolver::RESOLVER_PARAMS_SAMPLE_VALIDITY] = res_params.sample_validity;
    (*params)[IDnsResolver::RESOLVER_PARAMS_SUCCESS_THRESHOLD] = res_params.success_threshold;
    (*params)[IDnsResolver::RESOLVER_PARAMS_MIN_SAMPLES] = res_params.min_samples;
    (*params)[IDnsResolver::RESOLVER_PARAMS_MAX_SAMPLES] = res_params.max_samples;
    (*params)[IDnsResolver::RESOLVER_PARAMS_BASE_TIMEOUT_MSEC] = res_params.base_timeout_msec;
    (*params)[IDnsResolver::RESOLVER_PARAMS_RETRY_COUNT] = res_params.retry_count;
    return 0;
}

void ResolverController::startPrefix64Discovery(int32_t netId) {
    mDns64Configuration->startPrefixDiscovery(netId);
}

void ResolverController::stopPrefix64Discovery(int32_t netId) {
    return mDns64Configuration->stopPrefixDiscovery(netId);
}

// TODO: use StatusOr<T> to wrap the result.
int ResolverController::getPrefix64(unsigned netId, netdutils::IPPrefix* prefix) {
    netdutils::IPPrefix p = mDns64Configuration->getPrefix64(netId);
    if (p.family() != AF_INET6 || p.length() == 0) {
        return -ENOENT;
    }
    *prefix = p;
    return 0;
}

int ResolverController::configureDnsForwarding(uint32_t ifindex, uint32_t netid, uint32_t uid) {
    return mDnsProxy->configureDnsForwarding(ifindex, netid, uid);
}

int ResolverController::stopDnsForwarding(uint32_t ifindex) {
    return mDnsProxy->stopDnsForwarding(ifindex);
}

void ResolverController::dump(DumpWriter& dw, unsigned netId) {
    // No lock needed since Bionic's resolver locks all accessed data structures internally.
    std::vector<std::string> servers;
    std::vector<std::string> domains;
    std::vector<std::string> interfaceNames;
    res_params params = {};
    std::vector<ResolverStats> stats;
    int wait_for_pending_req_timeout_count = 0;
    time_t now = time(nullptr);
    int rv = getDnsInfo(netId, &servers, &domains, &params, &stats, &interfaceNames,
                        &wait_for_pending_req_timeout_count);
    dw.incIndent();
    if (rv != 0) {
        dw.println("getDnsInfo() failed for netid %u", netId);
    } else {
        if (servers.empty()) {
            dw.println("No DNS servers defined");
        } else {
            dw.println("DnsEvent subsampling map: " +
                       Join(resolv_cache_dump_subsampling_map(netId, false), ' '));
            dw.println("DnsEvent subsampling map for MDNS: " +
                       Join(resolv_cache_dump_subsampling_map(netId, true), ' '));
            dw.println(
                    "DNS servers: # IP (total, successes, errors, timeouts, internal errors, "
                    "RTT avg, last sample)");
            dw.incIndent();
            for (size_t i = 0; i < servers.size(); ++i) {
                if (i < stats.size()) {
                    const ResolverStats& s = stats[i];
                    int total = s.successes + s.errors + s.timeouts + s.internal_errors;
                    if (total > 0) {
                        int time_delta = (s.last_sample_time > 0) ? now - s.last_sample_time : -1;
                        dw.println("%s (%d, %d, %d, %d, %d, %dms, %ds)%s", servers[i].c_str(),
                                   total, s.successes, s.errors, s.timeouts, s.internal_errors,
                                   s.rtt_avg, time_delta, s.usable ? "" : " BROKEN");
                    } else {
                        dw.println("%s <no data>", servers[i].c_str());
                    }
                } else {
                    dw.println("%s <no stats>", servers[i].c_str());
                }
            }
            dw.decIndent();
        }
        std::string ifacenames_str = Join(interfaceNames, ", ");
        dw.println("Interface names: [%s]", ifacenames_str.c_str());
        if (domains.empty()) {
            dw.println("No search domains defined");
        } else {
            std::string domains_str = Join(domains, ", ");
            dw.println("search domains: %s", domains_str.c_str());
        }
        if (params.sample_validity != 0) {
            dw.println(
                    "DNS parameters: sample validity = %us, success threshold = %u%%, "
                    "samples (min, max) = (%u, %u), base_timeout = %dmsec, retry count = "
                    "%dtimes",
                    params.sample_validity, params.success_threshold, params.min_samples,
                    params.max_samples, params.base_timeout_msec, params.retry_count);
        }

        mDns64Configuration->dump(dw, netId);
        const auto privateDnsStatus = PrivateDnsConfiguration::getInstance().getStatus(netId);
        dw.println("Private DNS mode: %s", getPrivateDnsModeString(privateDnsStatus.mode));
        if (privateDnsStatus.dotServersMap.size() == 0) {
            dw.println("No DoT servers configured");
        } else {
            dw.println("DoT configuration (%u entries)",
                       static_cast<uint32_t>(privateDnsStatus.dotServersMap.size()));
            dw.incIndent();
            for (const auto& [server, validation] : privateDnsStatus.dotServersMap) {
                dw.println("%s name{%s} status{%s}", server.toIpString().c_str(),
                           server.name.c_str(), validationStatusToString(validation));
            }
            dw.decIndent();
        }
        if (privateDnsStatus.dohServersMap.size() == 0) {
            dw.println("No DoH servers configured");
        } else {
            // TODO: print the hostname and URL as well.
            dw.println("DoH configuration (%u entries)",
                       static_cast<uint32_t>(privateDnsStatus.dohServersMap.size()));
            dw.incIndent();
            for (const auto& [server, info] : privateDnsStatus.dohServersMap) {
                dw.println("%s url{%s} status{%s}", server.toString().c_str(),
                           info.httpsTemplate.c_str(), validationStatusToString(info.status));
            }
            dw.decIndent();
        }
        dw.println("Concurrent DNS query timeout: %d", wait_for_pending_req_timeout_count);
        resolv_netconfig_dump(dw, netId);
    }
    dw.decIndent();
}

}  // namespace net
}  // namespace android
