/* SPDX-License-Identifier: LGPL-2.1+ */

#include "alloc-util.h"
#include "dns-domain.h"
#include "list.h"
#include "resolved-dns-packet.h"
#include "resolved-dns-zone.h"
#include "resolved-dnssd.h"
#include "string-util.h"

/* Never allow more than 1K entries */
#define ZONE_MAX 1024

void dns_zone_item_probe_stop(DnsZoneItem *i) {
        DnsTransaction *t;
        assert(i);

        if (!i->probe_transaction)
                return;

        t = TAKE_PTR(i->probe_transaction);

        set_remove(t->notify_zone_items, i);
        set_remove(t->notify_zone_items_done, i);
        dns_transaction_gc(t);
}

static void dns_zone_item_free(DnsZoneItem *i) {
        if (!i)
                return;

        dns_zone_item_probe_stop(i);
        dns_resource_record_unref(i->rr);

        free(i);
}

DEFINE_TRIVIAL_CLEANUP_FUNC(DnsZoneItem*, dns_zone_item_free);

static void dns_zone_item_remove_and_free(DnsZone *z, DnsZoneItem *i) {
        DnsZoneItem *first;

        assert(z);

        if (!i)
                return;

        first = hashmap_get(z->by_key, i->rr->key);
        LIST_REMOVE(by_key, first, i);
        if (first)
                assert_se(hashmap_replace(z->by_key, first->rr->key, first) >= 0);
        else
                hashmap_remove(z->by_key, i->rr->key);

        first = hashmap_get(z->by_name, dns_resource_key_name(i->rr->key));
        LIST_REMOVE(by_name, first, i);
        if (first)
                assert_se(hashmap_replace(z->by_name, dns_resource_key_name(first->rr->key), first) >= 0);
        else
                hashmap_remove(z->by_name, dns_resource_key_name(i->rr->key));

        dns_zone_item_free(i);
}

void dns_zone_flush(DnsZone *z) {
        DnsZoneItem *i;

        assert(z);

        while ((i = hashmap_first(z->by_key)))
                dns_zone_item_remove_and_free(z, i);

        assert(hashmap_size(z->by_key) == 0);
        assert(hashmap_size(z->by_name) == 0);

        z->by_key = hashmap_free(z->by_key);
        z->by_name = hashmap_free(z->by_name);
}

DnsZoneItem* dns_zone_get(DnsZone *z, DnsResourceRecord *rr) {
        DnsZoneItem *i;

        assert(z);
        assert(rr);

        LIST_FOREACH(by_key, i, hashmap_get(z->by_key, rr->key))
                if (dns_resource_record_equal(i->rr, rr) > 0)
                        return i;

        return NULL;
}

void dns_zone_remove_rr(DnsZone *z, DnsResourceRecord *rr) {
        DnsZoneItem *i;

        assert(z);
        assert(rr);

        i = dns_zone_get(z, rr);
        if (i)
                dns_zone_item_remove_and_free(z, i);
}

int dns_zone_remove_rrs_by_key(DnsZone *z, DnsResourceKey *key) {
        _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
        DnsResourceRecord *rr;
        bool tentative;
        int r;

        r = dns_zone_lookup(z, key, 0, &answer, &soa, &tentative);
        if (r < 0)
                return r;

        DNS_ANSWER_FOREACH(rr, answer)
                dns_zone_remove_rr(z, rr);

        return 0;
}

static int dns_zone_init(DnsZone *z) {
        int r;

        assert(z);

        r = hashmap_ensure_allocated(&z->by_key, &dns_resource_key_hash_ops);
        if (r < 0)
                return r;

        r = hashmap_ensure_allocated(&z->by_name, &dns_name_hash_ops);
        if (r < 0)
                return r;

        return 0;
}

static int dns_zone_link_item(DnsZone *z, DnsZoneItem *i) {
        DnsZoneItem *first;
        int r;

        first = hashmap_get(z->by_key, i->rr->key);
        if (first) {
                LIST_PREPEND(by_key, first, i);
                assert_se(hashmap_replace(z->by_key, first->rr->key, first) >= 0);
        } else {
                r = hashmap_put(z->by_key, i->rr->key, i);
                if (r < 0)
                        return r;
        }

        first = hashmap_get(z->by_name, dns_resource_key_name(i->rr->key));
        if (first) {
                LIST_PREPEND(by_name, first, i);
                assert_se(hashmap_replace(z->by_name, dns_resource_key_name(first->rr->key), first) >= 0);
        } else {
                r = hashmap_put(z->by_name, dns_resource_key_name(i->rr->key), i);
                if (r < 0)
                        return r;
        }

        return 0;
}

static int dns_zone_item_probe_start(DnsZoneItem *i)  {
        DnsTransaction *t;
        int r;

        assert(i);

        if (i->probe_transaction)
                return 0;

        t = dns_scope_find_transaction(i->scope, &DNS_RESOURCE_KEY_CONST(i->rr->key->class, DNS_TYPE_ANY, dns_resource_key_name(i->rr->key)), false);
        if (!t) {
                _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;

                key = dns_resource_key_new(i->rr->key->class, DNS_TYPE_ANY, dns_resource_key_name(i->rr->key));
                if (!key)
                        return -ENOMEM;

                r = dns_transaction_new(&t, i->scope, key);
                if (r < 0)
                        return r;
        }

        r = set_ensure_allocated(&t->notify_zone_items, NULL);
        if (r < 0)
                goto gc;

        r = set_ensure_allocated(&t->notify_zone_items_done, NULL);
        if (r < 0)
                goto gc;

        r = set_put(t->notify_zone_items, i);
        if (r < 0)
                goto gc;

        i->probe_transaction = t;
        t->probing = true;

        if (t->state == DNS_TRANSACTION_NULL) {

                i->block_ready++;
                r = dns_transaction_go(t);
                i->block_ready--;

                if (r < 0) {
                        dns_zone_item_probe_stop(i);
                        return r;
                }
        }

        dns_zone_item_notify(i);
        return 0;

gc:
        dns_transaction_gc(t);
        return r;
}

int dns_zone_put(DnsZone *z, DnsScope *s, DnsResourceRecord *rr, bool probe) {
        _cleanup_(dns_zone_item_freep) DnsZoneItem *i = NULL;
        DnsZoneItem *existing;
        int r;

        assert(z);
        assert(s);
        assert(rr);

        if (dns_class_is_pseudo(rr->key->class))
                return -EINVAL;
        if (dns_type_is_pseudo(rr->key->type))
                return -EINVAL;

        existing = dns_zone_get(z, rr);
        if (existing)
                return 0;

        r = dns_zone_init(z);
        if (r < 0)
                return r;

        i = new0(DnsZoneItem, 1);
        if (!i)
                return -ENOMEM;

        i->scope = s;
        i->rr = dns_resource_record_ref(rr);
        i->probing_enabled = probe;

        r = dns_zone_link_item(z, i);
        if (r < 0)
                return r;

        if (probe) {
                DnsZoneItem *first, *j;
                bool established = false;

                /* Check if there's already an RR with the same name
                 * established. If so, it has been probed already, and
                 * we don't ned to probe again. */

                LIST_FIND_HEAD(by_name, i, first);
                LIST_FOREACH(by_name, j, first) {
                        if (i == j)
                                continue;

                        if (j->state == DNS_ZONE_ITEM_ESTABLISHED)
                                established = true;
                }

                if (established)
                        i->state = DNS_ZONE_ITEM_ESTABLISHED;
                else {
                        i->state = DNS_ZONE_ITEM_PROBING;

                        r = dns_zone_item_probe_start(i);
                        if (r < 0) {
                                dns_zone_item_remove_and_free(z, i);
                                i = NULL;
                                return r;
                        }
                }
        } else
                i->state = DNS_ZONE_ITEM_ESTABLISHED;

        i = NULL;
        return 0;
}

static int dns_zone_add_authenticated_answer(DnsAnswer *a, DnsZoneItem *i, int ifindex) {
        DnsAnswerFlags flags;

        /* From RFC 6762, Section 10.2
         * "They (the rules about when to set the cache-flush bit) apply to
         * startup announcements as described in Section 8.3, "Announcing",
         * and to responses generated as a result of receiving query messages."
         * So, set the cache-flush bit for mDNS answers except for DNS-SD
         * service enumeration PTRs described in RFC 6763, Section 4.1. */
        if (i->scope->protocol == DNS_PROTOCOL_MDNS &&
            !dns_resource_key_is_dnssd_ptr(i->rr->key))
                flags = DNS_ANSWER_AUTHENTICATED|DNS_ANSWER_CACHE_FLUSH;
        else
                flags = DNS_ANSWER_AUTHENTICATED;

        return dns_answer_add(a, i->rr, ifindex, flags);
}

int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, int ifindex, DnsAnswer **ret_answer, DnsAnswer **ret_soa, bool *ret_tentative) {
        _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
        unsigned n_answer = 0;
        DnsZoneItem *j, *first;
        bool tentative = true, need_soa = false;
        int r;

        /* Note that we don't actually need the ifindex for anything. However when it is passed we'll initialize the
         * ifindex field in the answer with it */

        assert(z);
        assert(key);
        assert(ret_answer);

        /* First iteration, count what we have */

        if (key->type == DNS_TYPE_ANY || key->class == DNS_CLASS_ANY) {
                bool found = false, added = false;
                int k;

                /* If this is a generic match, then we have to
                 * go through the list by the name and look
                 * for everything manually */

                first = hashmap_get(z->by_name, dns_resource_key_name(key));
                LIST_FOREACH(by_name, j, first) {
                        if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
                                continue;

                        found = true;

                        k = dns_resource_key_match_rr(key, j->rr, NULL);
                        if (k < 0)
                                return k;
                        if (k > 0) {
                                n_answer++;
                                added = true;
                        }

                }

                if (found && !added)
                        need_soa = true;

        } else {
                bool found = false;

                /* If this is a specific match, then look for
                 * the right key immediately */

                first = hashmap_get(z->by_key, key);
                LIST_FOREACH(by_key, j, first) {
                        if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
                                continue;

                        found = true;
                        n_answer++;
                }

                if (!found) {
                        first = hashmap_get(z->by_name, dns_resource_key_name(key));
                        LIST_FOREACH(by_name, j, first) {
                                if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
                                        continue;

                                need_soa = true;
                                break;
                        }
                }
        }

        if (n_answer <= 0 && !need_soa)
                goto return_empty;

        if (n_answer > 0) {
                answer = dns_answer_new(n_answer);
                if (!answer)
                        return -ENOMEM;
        }

        if (need_soa) {
                soa = dns_answer_new(1);
                if (!soa)
                        return -ENOMEM;
        }

        /* Second iteration, actually add the RRs to the answers */
        if (key->type == DNS_TYPE_ANY || key->class == DNS_CLASS_ANY) {
                bool found = false, added = false;
                int k;

                first = hashmap_get(z->by_name, dns_resource_key_name(key));
                LIST_FOREACH(by_name, j, first) {
                        if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
                                continue;

                        found = true;

                        if (j->state != DNS_ZONE_ITEM_PROBING)
                                tentative = false;

                        k = dns_resource_key_match_rr(key, j->rr, NULL);
                        if (k < 0)
                                return k;
                        if (k > 0) {
                                r = dns_zone_add_authenticated_answer(answer, j, ifindex);
                                if (r < 0)
                                        return r;

                                added = true;
                        }
                }

                if (found && !added) {
                        r = dns_answer_add_soa(soa, dns_resource_key_name(key), LLMNR_DEFAULT_TTL, ifindex);
                        if (r < 0)
                                return r;
                }
        } else {
                bool found = false;

                first = hashmap_get(z->by_key, key);
                LIST_FOREACH(by_key, j, first) {
                        if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
                                continue;

                        found = true;

                        if (j->state != DNS_ZONE_ITEM_PROBING)
                                tentative = false;

                        r = dns_zone_add_authenticated_answer(answer, j, ifindex);
                        if (r < 0)
                                return r;
                }

                if (!found) {
                        bool add_soa = false;

                        first = hashmap_get(z->by_name, dns_resource_key_name(key));
                        LIST_FOREACH(by_name, j, first) {
                                if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
                                        continue;

                                if (j->state != DNS_ZONE_ITEM_PROBING)
                                        tentative = false;

                                add_soa = true;
                        }

                        if (add_soa) {
                                r = dns_answer_add_soa(soa, dns_resource_key_name(key), LLMNR_DEFAULT_TTL, ifindex);
                                if (r < 0)
                                        return r;
                        }
                }
        }

        /* If the caller sets ret_tentative to NULL, then use this as
         * indication to not return tentative entries */

        if (!ret_tentative && tentative)
                goto return_empty;

        *ret_answer = TAKE_PTR(answer);

        if (ret_soa)
                *ret_soa = TAKE_PTR(soa);

        if (ret_tentative)
                *ret_tentative = tentative;

        return 1;

return_empty:
        *ret_answer = NULL;

        if (ret_soa)
                *ret_soa = NULL;

        if (ret_tentative)
                *ret_tentative = false;

        return 0;
}

void dns_zone_item_conflict(DnsZoneItem *i) {
        assert(i);

        if (!IN_SET(i->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_VERIFYING, DNS_ZONE_ITEM_ESTABLISHED))
                return;

        log_info("Detected conflict on %s", strna(dns_resource_record_to_string(i->rr)));

        dns_zone_item_probe_stop(i);

        /* Withdraw the conflict item */
        i->state = DNS_ZONE_ITEM_WITHDRAWN;

        dnssd_signal_conflict(i->scope->manager, dns_resource_key_name(i->rr->key));

        /* Maybe change the hostname */
        if (manager_is_own_hostname(i->scope->manager, dns_resource_key_name(i->rr->key)) > 0)
                manager_next_hostname(i->scope->manager);
}

void dns_zone_item_notify(DnsZoneItem *i) {
        assert(i);
        assert(i->probe_transaction);

        if (i->block_ready > 0)
                return;

        if (IN_SET(i->probe_transaction->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_VALIDATING))
                return;

        if (i->probe_transaction->state == DNS_TRANSACTION_SUCCESS) {
                bool we_lost = false;

                /* The probe got a successful reply. If we so far
                 * weren't established we just give up.
                 *
                 * In LLMNR case if we already
                 * were established, and the peer has the
                 * lexicographically larger IP address we continue
                 * and defend it. */

                if (!IN_SET(i->state, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING)) {
                        log_debug("Got a successful probe for not yet established RR, we lost.");
                        we_lost = true;
                } else if (i->probe_transaction->scope->protocol == DNS_PROTOCOL_LLMNR) {
                        assert(i->probe_transaction->received);
                        we_lost = memcmp(&i->probe_transaction->received->sender, &i->probe_transaction->received->destination, FAMILY_ADDRESS_SIZE(i->probe_transaction->received->family)) < 0;
                        if (we_lost)
                                log_debug("Got a successful probe reply for an established RR, and we have a lexicographically larger IP address and thus lost.");
                }

                if (we_lost) {
                        dns_zone_item_conflict(i);
                        return;
                }

                log_debug("Got a successful probe reply, but peer has lexicographically lower IP address and thus lost.");
        }

        log_debug("Record %s successfully probed.", strna(dns_resource_record_to_string(i->rr)));

        dns_zone_item_probe_stop(i);
        i->state = DNS_ZONE_ITEM_ESTABLISHED;
}

static int dns_zone_item_verify(DnsZoneItem *i) {
        int r;

        assert(i);

        if (i->state != DNS_ZONE_ITEM_ESTABLISHED)
                return 0;

        log_debug("Verifying RR %s", strna(dns_resource_record_to_string(i->rr)));

        i->state = DNS_ZONE_ITEM_VERIFYING;
        r = dns_zone_item_probe_start(i);
        if (r < 0) {
                log_error_errno(r, "Failed to start probing for verifying RR: %m");
                i->state = DNS_ZONE_ITEM_ESTABLISHED;
                return r;
        }

        return 0;
}

int dns_zone_check_conflicts(DnsZone *zone, DnsResourceRecord *rr) {
        DnsZoneItem *i, *first;
        int c = 0;

        assert(zone);
        assert(rr);

        /* This checks whether a response RR we received from somebody
         * else is one that we actually thought was uniquely ours. If
         * so, we'll verify our RRs. */

        /* No conflict if we don't have the name at all. */
        first = hashmap_get(zone->by_name, dns_resource_key_name(rr->key));
        if (!first)
                return 0;

        /* No conflict if we have the exact same RR */
        if (dns_zone_get(zone, rr))
                return 0;

        /* No conflict if it is DNS-SD RR used for service enumeration. */
        if (dns_resource_key_is_dnssd_ptr(rr->key))
                return 0;

        /* OK, somebody else has RRs for the same name. Yuck! Let's
         * start probing again */

        LIST_FOREACH(by_name, i, first) {
                if (dns_resource_record_equal(i->rr, rr))
                        continue;

                dns_zone_item_verify(i);
                c++;
        }

        return c;
}

int dns_zone_verify_conflicts(DnsZone *zone, DnsResourceKey *key) {
        DnsZoneItem *i, *first;
        int c = 0;

        assert(zone);

        /* Somebody else notified us about a possible conflict. Let's
         * verify if that's true. */

        first = hashmap_get(zone->by_name, dns_resource_key_name(key));
        if (!first)
                return 0;

        LIST_FOREACH(by_name, i, first) {
                dns_zone_item_verify(i);
                c++;
        }

        return c;
}

void dns_zone_verify_all(DnsZone *zone) {
        DnsZoneItem *i;
        Iterator iterator;

        assert(zone);

        HASHMAP_FOREACH(i, zone->by_key, iterator) {
                DnsZoneItem *j;

                LIST_FOREACH(by_key, j, i)
                        dns_zone_item_verify(j);
        }
}

void dns_zone_dump(DnsZone *zone, FILE *f) {
        Iterator iterator;
        DnsZoneItem *i;

        if (!zone)
                return;

        if (!f)
                f = stdout;

        HASHMAP_FOREACH(i, zone->by_key, iterator) {
                DnsZoneItem *j;

                LIST_FOREACH(by_key, j, i) {
                        const char *t;

                        t = dns_resource_record_to_string(j->rr);
                        if (!t) {
                                log_oom();
                                continue;
                        }

                        fputc('\t', f);
                        fputs(t, f);
                        fputc('\n', f);
                }
        }
}

bool dns_zone_is_empty(DnsZone *zone) {
        if (!zone)
                return true;

        return hashmap_isempty(zone->by_key);
}

bool dns_zone_contains_name(DnsZone *z, const char *name) {
        DnsZoneItem *i, *first;

        first = hashmap_get(z->by_name, name);
        if (!first)
                return false;

        LIST_FOREACH(by_name, i, first) {
                if (!IN_SET(i->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
                        continue;

                return true;
        }

        return false;
}
