/*
 * 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 "ResolverController"

#include "ResolverController.h"

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

#include <netdb.h>

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

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

using aidl::android::net::ResolverParamsParcel;

namespace android {

using netdutils::DumpWriter;

namespace net {

namespace {

std::string addrToString(const sockaddr_storage* addr) {
    char out[INET6_ADDRSTRLEN] = {0};
    getnameinfo((const sockaddr*)addr, sizeof(sockaddr_storage), out, INET6_ADDRSTRLEN, nullptr, 0,
                NI_NUMERICHOST);
    return std::string(out);
}

const char* getPrivateDnsModeString(PrivateDnsMode mode) {
    switch (mode) {
        case PrivateDnsMode::OFF:
            return "OFF";
        case PrivateDnsMode::OPPORTUNISTIC:
            return "OPPORTUNISTIC";
        case PrivateDnsMode::STRICT:
            return "STRICT";
    }
}

constexpr const char* validationStatusToString(Validation value) {
    switch (value) {
        case Validation::in_process:
            return "in_process";
        case Validation::success:
            return "success";
        case Validation::fail:
            return "fail";
        case Validation::unknown_server:
            return "unknown_server";
        case Validation::unknown_netid:
            return "unknown_netid";
        default:
            return "unknown_status";
    }
}

void sendNat64PrefixEvent(const Dns64Configuration::Nat64PrefixInfo& args) {
    const auto& listeners = ResolverEventReporter::getInstance().getListeners();
    if (listeners.size() == 0) {
        LOG(ERROR) << __func__ << ": No available listener. dropping NAT64 prefix event";
        return;
    }
    for (const auto& it : listeners) {
        it->onNat64PrefixEvent(args.netId, args.added, args.prefixString, args.prefixLength);
    }
}

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<int32_t>* wait_for_pending_req_timeout_count) {
    using aidl::android::net::IDnsResolver;
    using android::net::ResolverStats;
    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();
    *params = res_params{};
    stats->clear();
    int res_wait_for_pending_req_timeout_count;
    int revision_id = android_net_res_stats_get_info_for_net(
            netId, &nscount, res_servers, &dcount, res_domains, params, res_stats,
            &res_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 sane.
    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]);
    }

    (*wait_for_pending_req_timeout_count)[0] = res_wait_for_pending_req_timeout_count;
    return 0;
}

}  // namespace

ResolverController::ResolverController()
    : mDns64Configuration(
              [](uint32_t netId, uint32_t uid, android_net_context* netcontext) {
                  gResNetdCallbacks.get_network_context(netId, uid, netcontext);
              },
              std::bind(sendNat64PrefixEvent, std::placeholders::_1)) {}

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

    resolv_delete_cache_for_net(netId);
    mDns64Configuration.stopPrefixDiscovery(netId);
    gPrivateDnsConfiguration.clear(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) {
    using aidl::android::net::IDnsResolver;

    // 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)
    const int err =
            gPrivateDnsConfiguration.set(resolverParams.netId, netcontext.app_mark, tlsServers,
                                         resolverParams.tlsName, resolverParams.caCertificate);

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

    res_params res_params = {};
    res_params.sample_validity = resolverParams.sampleValiditySeconds;
    res_params.success_threshold = resolverParams.successThreshold;
    res_params.min_samples = resolverParams.minSamples;
    res_params.max_samples = resolverParams.maxSamples;
    res_params.base_timeout_msec = resolverParams.baseTimeoutMsec;
    res_params.retry_count = resolverParams.retryCount;

    return resolv_set_nameservers(resolverParams.netId, resolverParams.servers,
                                  resolverParams.domains, res_params,
                                  resolverParams.resolverOptions, resolverParams.transportTypes);
}

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

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

    const auto privateDnsStatus = gPrivateDnsConfiguration.getStatus(netId);
    for (const auto& pair : privateDnsStatus.serversMap) {
        tlsServers->push_back(addrToString(&pair.first.ss));
    }

    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) {
        LOG(INFO) << "No valid NAT64 prefix (" << netId << ", " << p.toString().c_str() << ")";

        return -ENOENT;
    }
    *prefix = p;
    return 0;
}

void ResolverController::dump(DumpWriter& dw, unsigned netId) {
    // No lock needed since Bionic's resolver locks all accessed data structures internally.
    using android::net::ResolverStats;
    std::vector<std::string> servers;
    std::vector<std::string> domains;
    res_params params = {};
    std::vector<ResolverStats> stats;
    std::vector<int32_t> wait_for_pending_req_timeout_count(1, 0);
    time_t now = time(nullptr);
    int rv = getDnsInfo(netId, &servers, &domains, &params, &stats,
                        &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: " +
                       android::base::Join(resolv_cache_dump_subsampling_map(netId), ' '));
            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();
        }
        if (domains.empty()) {
            dw.println("No search domains defined");
        } else {
            std::string domains_str = android::base::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 = gPrivateDnsConfiguration.getStatus(netId);
        dw.println("Private DNS mode: %s", getPrivateDnsModeString(privateDnsStatus.mode));
        if (privateDnsStatus.serversMap.size() == 0) {
            dw.println("No Private DNS servers configured");
        } else {
            dw.println("Private DNS configuration (%u entries)",
                       static_cast<uint32_t>(privateDnsStatus.serversMap.size()));
            dw.incIndent();
            for (const auto& pair : privateDnsStatus.serversMap) {
                dw.println("%s name{%s} status{%s}", addrToString(&pair.first.ss).c_str(),
                           pair.first.name.c_str(), validationStatusToString(pair.second));
            }
            dw.decIndent();
        }
        dw.println("Concurrent DNS query timeout: %d", wait_for_pending_req_timeout_count[0]);
        resolv_netconfig_dump(dw, netId);
    }
    dw.decIndent();
}

}  // namespace net
}  // namespace android
