resolved-dns-answer.c revision 1849cb7cb723e8ea7c13b967d056c1d3a36d9042
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering/***
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering This file is part of systemd.
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering Copyright 2014 Lennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering systemd is free software; you can redistribute it and/or modify it
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering under the terms of the GNU Lesser General Public License as published by
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering (at your option) any later version.
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering systemd is distributed in the hope that it will be useful, but
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering Lesser General Public License for more details.
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering You should have received a copy of the GNU Lesser General Public License
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering***/
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "alloc-util.h"
4ad7f2761da661853dcc29d542efb4727abb1101Nick Owens#include "dns-domain.h"
0f7091e624fdba6c0bf281f2a9a23cd3e9ca93fbLennart Poettering#include "resolved-dns-answer.h"
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "resolved-dns-dnssec.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "string-util.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart PoetteringDnsAnswer *dns_answer_new(unsigned n) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering DnsAnswer *a;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering a = malloc0(offsetof(DnsAnswer, items) + sizeof(DnsAnswerItem) * n);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (!a)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return NULL;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering a->n_ref = 1;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering a->n_allocated = n;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return a;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering}
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart PoetteringDnsAnswer *dns_answer_ref(DnsAnswer *a) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (!a)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return NULL;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering assert(a->n_ref > 0);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering a->n_ref++;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return a;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering}
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringstatic void dns_answer_flush(DnsAnswer *a) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering DnsResourceRecord *rr;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (!a)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering DNS_ANSWER_FOREACH(rr, a)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering dns_resource_record_unref(rr);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering a->n_rrs = 0;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering}
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart PoetteringDnsAnswer *dns_answer_unref(DnsAnswer *a) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (!a)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return NULL;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering assert(a->n_ref > 0);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (a->n_ref == 1) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering dns_answer_flush(a);
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering free(a);
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering } else
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering a->n_ref--;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return NULL;
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering}
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poetteringstatic int dns_answer_add_raw(DnsAnswer *a, DnsResourceRecord *rr, int ifindex) {
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering assert(rr);
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering if (!a)
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering return -ENOSPC;
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering if (a->n_rrs >= a->n_allocated)
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering return -ENOSPC;
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering a->items[a->n_rrs].rr = dns_resource_record_ref(rr);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering a->items[a->n_rrs].ifindex = ifindex;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering a->n_rrs++;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return 1;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering}
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
801ad6a6a9cd8fbd58b9f9c27f20dbb3c87d47ddLennart Poetteringstatic int dns_answer_add_raw_all(DnsAnswer *a, DnsAnswer *source) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering DnsResourceRecord *rr;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering int ifindex, r;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, source) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = dns_answer_add_raw(a, rr, ifindex);
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering if (r < 0)
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering return r;
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering }
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
801ad6a6a9cd8fbd58b9f9c27f20dbb3c87d47ddLennart Poettering return 0;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering}
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringint dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering unsigned i;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering int r;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering assert(rr);
801ad6a6a9cd8fbd58b9f9c27f20dbb3c87d47ddLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (!a)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return -ENOSPC;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (a->n_ref > 1)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return -EBUSY;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering for (i = 0; i < a->n_rrs; i++) {
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering if (a->items[i].ifindex != ifindex)
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering continue;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
5d27351f8546530cf779847b0b04b0172c09f9d0Tom Gundersen r = dns_resource_record_equal(a->items[i].rr, rr);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (r < 0)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return r;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (r > 0) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering /* Entry already exists, keep the entry with
34b9656f0b2890743eee6a746ef08d817abfd5e9Lennart Poettering * the higher RR, or the one with TTL 0 */
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (rr->ttl == 0 || (rr->ttl > a->items[i].rr->ttl && a->items[i].rr->ttl != 0)) {
703e4f5e39c019da8c002ba10bd450ce378c0e91Lennart Poettering dns_resource_record_ref(rr);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering dns_resource_record_unref(a->items[i].rr);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering a->items[i].rr = rr;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering }
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering return 0;
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering }
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering }
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return dns_answer_add_raw(a, rr, ifindex);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering}
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringstatic int dns_answer_add_all(DnsAnswer *a, DnsAnswer *b) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering DnsResourceRecord *rr;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering int ifindex, r;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, b) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = dns_answer_add(a, rr, ifindex);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (r < 0)
0f7091e624fdba6c0bf281f2a9a23cd3e9ca93fbLennart Poettering return r;
34b9656f0b2890743eee6a746ef08d817abfd5e9Lennart Poettering }
34b9656f0b2890743eee6a746ef08d817abfd5e9Lennart Poettering
0f7091e624fdba6c0bf281f2a9a23cd3e9ca93fbLennart Poettering return 0;
0f7091e624fdba6c0bf281f2a9a23cd3e9ca93fbLennart Poettering}
0f7091e624fdba6c0bf281f2a9a23cd3e9ca93fbLennart Poettering
0f7091e624fdba6c0bf281f2a9a23cd3e9ca93fbLennart Poetteringint dns_answer_add_extend(DnsAnswer **a, DnsResourceRecord *rr, int ifindex) {
0f7091e624fdba6c0bf281f2a9a23cd3e9ca93fbLennart Poettering int r;
0f7091e624fdba6c0bf281f2a9a23cd3e9ca93fbLennart Poettering
0f7091e624fdba6c0bf281f2a9a23cd3e9ca93fbLennart Poettering assert(a);
0f7091e624fdba6c0bf281f2a9a23cd3e9ca93fbLennart Poettering assert(rr);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = dns_answer_reserve_or_clone(a, 1);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (r < 0)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return r;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
6a21960c0be378799db51a2735ff68474e5e21f8Lennart Poettering return dns_answer_add(*a, rr, ifindex);
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering}
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poetteringint dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl) {
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *soa = NULL;
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering soa = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_SOA, name);
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering if (!soa)
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering return -ENOMEM;
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering soa->ttl = ttl;
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering soa->soa.mname = strdup(name);
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering if (!soa->soa.mname)
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering return -ENOMEM;
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering soa->soa.rname = strappend("root.", name);
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering if (!soa->soa.rname)
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering return -ENOMEM;
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering soa->soa.serial = 1;
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering soa->soa.refresh = 1;
b6800689e03456efd0430d171ebf962f64b94eb0Lennart Poettering soa->soa.retry = 1;
b6800689e03456efd0430d171ebf962f64b94eb0Lennart Poettering soa->soa.expire = 1;
b6800689e03456efd0430d171ebf962f64b94eb0Lennart Poettering soa->soa.minimum = ttl;
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering return dns_answer_add(a, soa, 0);
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering}
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poetteringint dns_answer_match_key(DnsAnswer *a, const DnsResourceKey *key) {
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering DnsResourceRecord *i;
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering int r;
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering assert(key);
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering if (!a)
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering return 0;
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering DNS_ANSWER_FOREACH(i, a) {
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering r = dns_resource_key_match_rr(key, i, NULL);
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering if (r < 0)
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering return r;
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering if (r > 0)
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering return 1;
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering }
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering return 0;
36d9205d669bcdcb04fa730d1f3549a9fc9a9001Tom Gundersen}
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poetteringint dns_answer_contains_rr(DnsAnswer *a, DnsResourceRecord *rr) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering DnsResourceRecord *i;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering int r;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
36d9205d669bcdcb04fa730d1f3549a9fc9a9001Tom Gundersen assert(rr);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering DNS_ANSWER_FOREACH(i, a) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = dns_resource_record_equal(i, rr);
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering if (r < 0)
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering return r;
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering if (r > 0)
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering return 1;
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering }
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering return 0;
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering}
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poetteringint dns_answer_find_soa(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret) {
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering DnsResourceRecord *rr;
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering int r;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering assert(key);
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering /* For a SOA record we can never find a matching SOA record */
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering if (key->type == DNS_TYPE_SOA)
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering return 0;
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering DNS_ANSWER_FOREACH(rr, a) {
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering r = dns_resource_key_match_soa(key, rr->key);
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering if (r < 0)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return r;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (r > 0) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (ret)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering *ret = rr;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return 1;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering }
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering }
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return 0;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering}
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poetteringint dns_answer_find_cname_or_dname(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering DnsResourceRecord *rr;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering int r;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering assert(key);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering /* For a {C,D}NAME record we can never find a matching {C,D}NAME record */
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (key->type == DNS_TYPE_CNAME || key->type == DNS_TYPE_DNAME)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return 0;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering DNS_ANSWER_FOREACH(rr, a) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = dns_resource_key_match_cname_or_dname(key, rr->key, NULL);
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering if (r < 0)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return r;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (r > 0) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (ret)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering *ret = rr;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return 1;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering }
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering }
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return 0;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering}
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringint dns_answer_merge(DnsAnswer *a, DnsAnswer *b, DnsAnswer **ret) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering _cleanup_(dns_answer_unrefp) DnsAnswer *k = NULL;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering int r;
703e4f5e39c019da8c002ba10bd450ce378c0e91Lennart Poettering
703e4f5e39c019da8c002ba10bd450ce378c0e91Lennart Poettering assert(ret);
703e4f5e39c019da8c002ba10bd450ce378c0e91Lennart Poettering
703e4f5e39c019da8c002ba10bd450ce378c0e91Lennart Poettering if (dns_answer_size(a) <= 0) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering *ret = dns_answer_ref(b);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return 0;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering }
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (dns_answer_size(b) <= 0) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering *ret = dns_answer_ref(a);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return 0;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering }
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering k = dns_answer_new(a->n_rrs + b->n_rrs);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (!k)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return -ENOMEM;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering r = dns_answer_add_raw_all(k, a);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (r < 0)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return r;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering r = dns_answer_add_all(k, b);
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering if (r < 0)
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering return r;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering *ret = k;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering k = NULL;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering return 0;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering}
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poetteringint dns_answer_extend(DnsAnswer **a, DnsAnswer *b) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering DnsAnswer *merged;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering int r;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering assert(a);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering r = dns_answer_merge(*a, b, &merged);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (r < 0)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return r;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering dns_answer_unref(*a);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering *a = merged;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return 0;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering}
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poetteringint dns_answer_remove_by_key(DnsAnswer **a, const DnsResourceKey *key) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering bool found = false, other = false;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering DnsResourceRecord *rr;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering unsigned i;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering int r;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering assert(a);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering assert(key);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering /* Remove all entries matching the specified key from *a */
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering DNS_ANSWER_FOREACH(rr, *a) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering r = dns_resource_key_equal(rr->key, key);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (r < 0)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return r;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (r > 0)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering found = true;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering else
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering other = true;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (found && other)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering break;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering }
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (!found)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return 0;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (!other) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering *a = dns_answer_unref(*a); /* Return NULL for the empty answer */
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return 1;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering }
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if ((*a)->n_ref > 1) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering _cleanup_(dns_answer_unrefp) DnsAnswer *copy = NULL;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering int ifindex;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering copy = dns_answer_new((*a)->n_rrs);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (!copy)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return -ENOMEM;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, *a) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering r = dns_resource_key_equal(rr->key, key);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (r < 0)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return r;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (r > 0)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering continue;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering r = dns_answer_add_raw(copy, rr, ifindex);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (r < 0)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return r;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering }
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering dns_answer_unref(*a);
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering *a = copy;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering copy = NULL;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering return 1;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering }
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering /* Only a single reference, edit in-place */
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering i = 0;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering for (;;) {
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering if (i >= (*a)->n_rrs)
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering break;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering r = dns_resource_key_equal((*a)->items[i].rr->key, key);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (r < 0)
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering return r;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering if (r > 0) {
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering /* Kill this entry */
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering dns_resource_record_unref((*a)->items[i].rr);
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering memmove((*a)->items + i, (*a)->items + i + 1, sizeof(DnsAnswerItem) * ((*a)->n_rrs - i - 1));
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering (*a)->n_rrs --;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering continue;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering } else
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering /* Keep this entry */
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering i++;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering }
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering return 1;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering}
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poetteringint dns_answer_copy_by_key(DnsAnswer **a, DnsAnswer *source, const DnsResourceKey *key) {
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering DnsResourceRecord *rr_source;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering int ifindex_source, r;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering assert(a);
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering assert(key);
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering /* Copy all RRs matching the specified key from source into *a */
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering DNS_ANSWER_FOREACH_IFINDEX(rr_source, ifindex_source, source) {
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering r = dns_resource_key_equal(rr_source->key, key);
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering if (r < 0)
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering return r;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering if (r == 0)
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering continue;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering /* Make space for at least one entry */
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering r = dns_answer_reserve_or_clone(a, 1);
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering if (r < 0)
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering return r;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering r = dns_answer_add(*a, rr_source, ifindex_source);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (r < 0)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return r;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering }
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return 0;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering}
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poetteringvoid dns_answer_order_by_scope(DnsAnswer *a, bool prefer_link_local) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering DnsAnswerItem *items;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering unsigned i, start, end;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (!a)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (a->n_rrs <= 1)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering start = 0;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering end = a->n_rrs-1;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering /* RFC 4795, Section 2.6 suggests we should order entries
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering * depending on whether the sender is a link-local address. */
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering items = newa(DnsAnswerItem, a->n_rrs);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering for (i = 0; i < a->n_rrs; i++) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (a->items[i].rr->key->class == DNS_CLASS_IN &&
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering ((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 */
items[end--] = a->items[i];
else
/* Order all other records to the beginning of the array */
items[start++] = a->items[i];
}
assert(start == end+1);
memcpy(a->items, items, sizeof(DnsAnswerItem) * a->n_rrs);
}
int dns_answer_reserve(DnsAnswer **a, unsigned n_free) {
DnsAnswer *n;
assert(a);
if (n_free <= 0)
return 0;
if (*a) {
unsigned ns;
if ((*a)->n_ref > 1)
return -EBUSY;
ns = (*a)->n_rrs + n_free;
if ((*a)->n_allocated >= ns)
return 0;
/* Allocate more than we need */
ns *= 2;
n = realloc(*a, offsetof(DnsAnswer, items) + sizeof(DnsAnswerItem) * ns);
if (!n)
return -ENOMEM;
n->n_allocated = ns;
} else {
n = dns_answer_new(n_free);
if (!n)
return -ENOMEM;
}
*a = n;
return 0;
}
int dns_answer_reserve_or_clone(DnsAnswer **a, unsigned 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
* 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. */
r = dns_answer_reserve(a, n_free);
if (r != -EBUSY)
return r;
assert(*a);
n = dns_answer_new(((*a)->n_rrs + n_free) * 2);
if (!n)
return -ENOMEM;
r = dns_answer_add_raw_all(n, *a);
if (r < 0)
return r;
dns_answer_unref(*a);
*a = n;
n = NULL;
return 0;
}