-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+#include <stdio.h>
#include "alloc-util.h"
#include "dns-domain.h"
#include "resolved-dns-dnssec.h"
#include "string-util.h"
-DnsAnswer *dns_answer_new(unsigned n) {
+DnsAnswer *dns_answer_new(size_t n) {
DnsAnswer *a;
a = malloc0(offsetof(DnsAnswer, items) + sizeof(DnsAnswerItem) * n);
return a;
}
-DnsAnswer *dns_answer_ref(DnsAnswer *a) {
- if (!a)
- return NULL;
-
- assert(a->n_ref > 0);
- a->n_ref++;
- return a;
-}
-
static void dns_answer_flush(DnsAnswer *a) {
DnsResourceRecord *rr;
a->n_rrs = 0;
}
-DnsAnswer *dns_answer_unref(DnsAnswer *a) {
- if (!a)
- return NULL;
-
- assert(a->n_ref > 0);
-
- if (a->n_ref == 1) {
- dns_answer_flush(a);
- free(a);
- } else
- a->n_ref--;
+static DnsAnswer *dns_answer_free(DnsAnswer *a) {
+ assert(a);
- return NULL;
+ dns_answer_flush(a);
+ return mfree(a);
}
+DEFINE_TRIVIAL_REF_UNREF_FUNC(DnsAnswer, dns_answer, dns_answer_free);
+
static int dns_answer_add_raw(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) {
assert(rr);
}
int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) {
- unsigned i;
+ size_t i;
int r;
assert(rr);
if (a->items[i].ifindex != ifindex)
continue;
- r = dns_resource_record_equal(a->items[i].rr, rr);
+ r = dns_resource_key_equal(a->items[i].rr->key, rr->key);
if (r < 0)
return r;
- if (r > 0) {
- /* Don't mix contradicting TTLs (see below) */
- if ((rr->ttl == 0) != (a->items[i].rr->ttl == 0))
- return -EINVAL;
-
- /* Entry already exists, keep the entry with
- * the higher RR. */
- if (rr->ttl > a->items[i].rr->ttl) {
- dns_resource_record_ref(rr);
- dns_resource_record_unref(a->items[i].rr);
- a->items[i].rr = rr;
- }
+ if (r == 0)
+ continue;
- a->items[i].flags |= flags;
- return 0;
- }
+ /* There's already an RR of the same RRset in place! Let's see if the TTLs more or less
+ * match. We don't really care if they match precisely, but we do care whether one is 0 and
+ * the other is not. See RFC 2181, Section 5.2. */
+ if ((rr->ttl == 0) != (a->items[i].rr->ttl == 0))
+ return -EINVAL;
- r = dns_resource_key_equal(a->items[i].rr->key, rr->key);
+ r = dns_resource_record_payload_equal(a->items[i].rr, rr);
if (r < 0)
return r;
- if (r > 0) {
- /* There's already an RR of the same RRset in
- * place! Let's see if the TTLs more or less
- * match. We don't really care if they match
- * precisely, but we do care whether one is 0
- * and the other is not. See RFC 2181, Section
- * 5.2.*/
-
- if ((rr->ttl == 0) != (a->items[i].rr->ttl == 0))
- return -EINVAL;
+ if (r == 0)
+ continue;
+
+ /* Entry already exists, keep the entry with the higher RR. */
+ if (rr->ttl > a->items[i].rr->ttl) {
+ dns_resource_record_ref(rr);
+ dns_resource_record_unref(a->items[i].rr);
+ a->items[i].rr = rr;
}
+
+ a->items[i].flags |= flags;
+ return 0;
}
return dns_answer_add_raw(a, rr, ifindex, flags);
return dns_answer_add(*a, rr, ifindex, flags);
}
-int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl) {
+int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl, int ifindex) {
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *soa = NULL;
soa = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_SOA, name);
soa->soa.expire = 1;
soa->soa.minimum = ttl;
- return dns_answer_add(a, soa, 0, DNS_ANSWER_AUTHENTICATED);
+ return dns_answer_add(a, soa, ifindex, DNS_ANSWER_AUTHENTICATED);
}
int dns_answer_match_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *ret_flags) {
return found;
}
-int dns_answer_contains_rr(DnsAnswer *a, DnsResourceRecord *rr, DnsAnswerFlags *ret_flags) {
- DnsAnswerFlags flags = 0, i_flags;
- DnsResourceRecord *i;
- bool found = false;
- int r;
-
- assert(rr);
-
- DNS_ANSWER_FOREACH_FLAGS(i, i_flags, a) {
- r = dns_resource_record_equal(i, rr);
- if (r < 0)
- return r;
- if (r == 0)
- continue;
-
- if (!ret_flags)
- return 1;
-
- if (found)
- flags &= i_flags;
- else {
- flags = i_flags;
- found = true;
- }
- }
-
- if (ret_flags)
- *ret_flags = flags;
-
- return found;
-}
-
-int dns_answer_contains_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *ret_flags) {
- DnsAnswerFlags flags = 0, i_flags;
- DnsResourceRecord *i;
- bool found = false;
- int r;
-
- assert(key);
-
- DNS_ANSWER_FOREACH_FLAGS(i, i_flags, a) {
- r = dns_resource_key_equal(i->key, key);
- if (r < 0)
- return r;
- if (r == 0)
- continue;
-
- if (!ret_flags)
- return true;
-
- if (found)
- flags &= i_flags;
- else {
- flags = i_flags;
- found = true;
- }
- }
-
- if (ret_flags)
- *ret_flags = flags;
-
- return found;
-}
-
int dns_answer_contains_nsec_or_nsec3(DnsAnswer *a) {
DnsResourceRecord *i;
if (rr->key->type != DNS_TYPE_NSEC3)
continue;
- p = DNS_RESOURCE_KEY_NAME(rr->key);
+ p = dns_resource_key_name(rr->key);
r = dns_name_parent(&p);
if (r < 0)
return r;
if (r > 0) {
if (soa) {
- r = dns_name_endswith(DNS_RESOURCE_KEY_NAME(rr->key), DNS_RESOURCE_KEY_NAME(soa->key));
+ r = dns_name_endswith(dns_resource_key_name(rr->key), dns_resource_key_name(soa->key));
if (r < 0)
return r;
if (r > 0)
if (r < 0)
return r;
- *ret = k;
- k = NULL;
+ *ret = TAKE_PTR(k);
return 0;
}
int dns_answer_remove_by_key(DnsAnswer **a, const DnsResourceKey *key) {
bool found = false, other = false;
DnsResourceRecord *rr;
- unsigned i;
+ size_t i;
int r;
assert(a);
}
dns_answer_unref(*a);
- *a = copy;
- copy = NULL;
+ *a = TAKE_PTR(copy);
return 1;
}
dns_resource_record_unref((*a)->items[i].rr);
memmove((*a)->items + i, (*a)->items + i + 1, sizeof(DnsAnswerItem) * ((*a)->n_rrs - i - 1));
- (*a)->n_rrs --;
+ (*a)->n_rrs--;
continue;
} else
int dns_answer_remove_by_rr(DnsAnswer **a, DnsResourceRecord *rm) {
bool found = false, other = false;
DnsResourceRecord *rr;
- unsigned i;
+ size_t i;
int r;
assert(a);
}
dns_answer_unref(*a);
- *a = copy;
- copy = NULL;
+ *a = TAKE_PTR(copy);
return 1;
}
dns_resource_record_unref((*a)->items[i].rr);
memmove((*a)->items + i, (*a)->items + i + 1, sizeof(DnsAnswerItem) * ((*a)->n_rrs - i - 1));
- (*a)->n_rrs --;
+ (*a)->n_rrs--;
continue;
} else
void dns_answer_order_by_scope(DnsAnswer *a, bool prefer_link_local) {
DnsAnswerItem *items;
- unsigned i, start, end;
+ size_t i, start, end;
if (!a)
return;
if (a->items[i].rr->key->class == DNS_CLASS_IN &&
((a->items[i].rr->key->type == DNS_TYPE_A && in_addr_is_link_local(AF_INET, (union in_addr_union*) &a->items[i].rr->a.in_addr) != prefer_link_local) ||
(a->items[i].rr->key->type == DNS_TYPE_AAAA && in_addr_is_link_local(AF_INET6, (union in_addr_union*) &a->items[i].rr->aaaa.in6_addr) != prefer_link_local)))
- /* Order address records that are are not preferred to the end of the array */
+ /* Order address records that are not preferred to the end of the array */
items[end--] = a->items[i];
else
/* Order all other records to the beginning of the array */
memcpy(a->items, items, sizeof(DnsAnswerItem) * a->n_rrs);
}
-int dns_answer_reserve(DnsAnswer **a, unsigned n_free) {
+int dns_answer_reserve(DnsAnswer **a, size_t n_free) {
DnsAnswer *n;
assert(a);
return 0;
if (*a) {
- unsigned ns;
+ size_t ns;
if ((*a)->n_ref > 1)
return -EBUSY;
return 0;
}
-int dns_answer_reserve_or_clone(DnsAnswer **a, unsigned n_free) {
+int dns_answer_reserve_or_clone(DnsAnswer **a, size_t n_free) {
_cleanup_(dns_answer_unrefp) DnsAnswer *n = NULL;
int r;
assert(a);
/* Tries to extend the DnsAnswer object. And if that's not
- * possibly, since we are not the sole owner, then allocate a
+ * possible, since we are not the sole owner, then allocate a
* new, appropriately sized one. Either way, after this call
* the object will only have a single reference, and has room
* for at least the specified number of RRs. */
return r;
dns_answer_unref(*a);
- *a = n;
- n = NULL;
+ *a = TAKE_PTR(n);
return 0;
}
}
}
-bool dns_answer_has_dname_for_cname(DnsAnswer *a, DnsResourceRecord *cname) {
+int dns_answer_has_dname_for_cname(DnsAnswer *a, DnsResourceRecord *cname) {
DnsResourceRecord *rr;
int r;
if (rr->key->class != cname->key->class)
continue;
- r = dns_name_change_suffix(cname->cname.name, rr->dname.name, DNS_RESOURCE_KEY_NAME(rr->key), &n);
+ r = dns_name_change_suffix(cname->cname.name, rr->dname.name, dns_resource_key_name(rr->key), &n);
if (r < 0)
return r;
if (r == 0)
continue;
- r = dns_name_equal(n, DNS_RESOURCE_KEY_NAME(cname->key));
+ r = dns_name_equal(n, dns_resource_key_name(cname->key));
if (r < 0)
return r;
if (r > 0)
return 1;
-
}
return 0;