/* SPDX-License-Identifier: LGPL-2.1-or-later */

#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 "resolved-manager.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 DnsZoneItem* dns_zone_item_free(DnsZoneItem *i) {
        if (!i)
                return NULL;

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

        return mfree(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);

        if (!rr)
                return;

        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)  {
        _cleanup_(dns_transaction_gcp) DnsTransaction *t = NULL;
        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)),
                        SD_RESOLVED_NO_CACHE|SD_RESOLVED_NO_ZONE);
        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, NULL, SD_RESOLVED_NO_CACHE|SD_RESOLVED_NO_ZONE);
                if (r < 0)
                        return r;
        }

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

        r = set_ensure_put(&t->notify_zone_items, NULL, i);
        if (r < 0)
                return r;

        t->probing = true;
        i->probe_transaction = TAKE_PTR(t);

        if (i->probe_transaction->state == DNS_TRANSACTION_NULL) {
                i->block_ready++;
                r = dns_transaction_go(i->probe_transaction);
                i->block_ready--;

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

        dns_zone_item_notify(i);
        return 0;
}

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 = new(DnsZoneItem, 1);
        if (!i)
                return -ENOMEM;

        *i = (DnsZoneItem) {
                .scope = s,
                .rr = dns_resource_record_ref(rr),
                .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 need 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, NULL);
}

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;

        (void) 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;

        assert(zone);

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

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

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

        if (!zone)
                return;

        if (!f)
                f = stdout;

        HASHMAP_FOREACH(i, zone->by_key) {
                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;
}
