1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
4 #include "ordered-set.h"
5 #include "resolved-forward.h"
7 /* A simple array of resource records. We keep track of the originating ifindex for each RR where that makes
8 * sense, so that we can qualify A and AAAA RRs referring to a local link with the right ifindex.
10 * Note that we usually encode the empty DnsAnswer object as a simple NULL. */
12 typedef enum DnsAnswerFlags
{
13 DNS_ANSWER_AUTHENTICATED
= 1 << 0, /* Item has been authenticated */
14 DNS_ANSWER_CACHEABLE
= 1 << 1, /* Item is subject to caching */
15 DNS_ANSWER_SHARED_OWNER
= 1 << 2, /* For mDNS: RRset may be owner by multiple peers */
16 DNS_ANSWER_CACHE_FLUSH
= 1 << 3, /* For mDNS: sets cache-flush bit in the rrclass of response records */
17 DNS_ANSWER_GOODBYE
= 1 << 4, /* For mDNS: item is subject to disappear */
18 DNS_ANSWER_SECTION_ANSWER
= 1 << 5, /* When parsing: RR originates from answer section */
19 DNS_ANSWER_SECTION_AUTHORITY
= 1 << 6, /* When parsing: RR originates from authority section */
20 DNS_ANSWER_SECTION_ADDITIONAL
= 1 << 7, /* When parsing: RR originates from additional section */
21 DNS_ANSWER_REFUSE_TTL_NO_MATCH
= 1 << 8, /* For mDNS; refuse to merge a zero TTL RR with a nonzero TTL RR */
23 DNS_ANSWER_MASK_SECTIONS
= DNS_ANSWER_SECTION_ANSWER
|
24 DNS_ANSWER_SECTION_AUTHORITY
|
25 DNS_ANSWER_SECTION_ADDITIONAL
,
28 typedef struct DnsAnswerItem
{
30 DnsResourceRecord
*rr
;
31 DnsResourceRecord
*rrsig
; /* Optionally, also store RRSIG RR that successfully validates this item */
36 typedef struct DnsAnswer
{
41 DnsAnswer
*dns_answer_new(size_t n
);
42 DnsAnswer
*dns_answer_ref(DnsAnswer
*a
);
43 DnsAnswer
*dns_answer_unref(DnsAnswer
*a
);
45 #define DNS_ANSWER_REPLACE(a, b) \
47 typeof(a)* _a = &(a); \
49 dns_answer_unref(*_a); \
53 int dns_answer_add(DnsAnswer
*a
, DnsResourceRecord
*rr
, int ifindex
, DnsAnswerFlags flags
, DnsResourceRecord
*rrsig
);
54 int dns_answer_add_extend(DnsAnswer
**a
, DnsResourceRecord
*rr
, int ifindex
, DnsAnswerFlags flags
, DnsResourceRecord
*rrsig
);
55 int dns_answer_add_soa(DnsAnswer
*a
, const char *name
, uint32_t ttl
, int ifindex
);
57 int dns_answer_match_key(DnsAnswer
*a
, const DnsResourceKey
*key
, DnsAnswerFlags
*ret_flags
);
58 bool dns_answer_contains_nsec_or_nsec3(DnsAnswer
*a
);
59 int dns_answer_contains_zone_nsec3(DnsAnswer
*answer
, const char *zone
);
60 bool dns_answer_contains(DnsAnswer
*answer
, DnsResourceRecord
*rr
);
62 int dns_answer_find_soa(DnsAnswer
*a
, const DnsResourceKey
*key
, DnsResourceRecord
**ret
, DnsAnswerFlags
*ret_flags
);
63 int dns_answer_find_cname_or_dname(DnsAnswer
*a
, const DnsResourceKey
*key
, DnsResourceRecord
**ret
, DnsAnswerFlags
*ret_flags
);
65 int dns_answer_merge(DnsAnswer
*a
, DnsAnswer
*b
, DnsAnswer
**ret
);
66 int dns_answer_extend(DnsAnswer
**a
, DnsAnswer
*b
);
68 void dns_answer_order_by_scope(DnsAnswer
*a
, bool prefer_link_local
);
70 int dns_answer_reserve(DnsAnswer
**a
, size_t n_free
);
71 int dns_answer_reserve_or_clone(DnsAnswer
**a
, size_t n_free
);
73 int dns_answer_remove_by_key(DnsAnswer
**a
, const DnsResourceKey
*key
);
74 int dns_answer_remove_by_rr(DnsAnswer
**a
, DnsResourceRecord
*rr
);
75 int dns_answer_remove_by_answer_keys(DnsAnswer
**a
, DnsAnswer
*b
);
77 int dns_answer_copy_by_key(DnsAnswer
**a
, DnsAnswer
*source
, const DnsResourceKey
*key
, DnsAnswerFlags or_flags
, DnsResourceRecord
*rrsig
);
78 int dns_answer_move_by_key(DnsAnswer
**to
, DnsAnswer
**from
, const DnsResourceKey
*key
, DnsAnswerFlags or_flags
, DnsResourceRecord
*rrsig
);
80 int dns_answer_has_dname_for_cname(DnsAnswer
*a
, DnsResourceRecord
*cname
);
82 static inline size_t dns_answer_size(DnsAnswer
*a
) {
83 return a
? ordered_set_size(a
->items
) : 0;
86 static inline bool dns_answer_isempty(DnsAnswer
*a
) {
87 return dns_answer_size(a
) <= 0;
90 void dns_answer_dump(DnsAnswer
*answer
, FILE *f
);
92 void dns_answer_randomize(DnsAnswer
*a
);
94 uint32_t dns_answer_min_ttl(DnsAnswer
*a
);
96 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsAnswer
*, dns_answer_unref
);
98 typedef struct DnsAnswerIterator
{
104 #define _DNS_ANSWER_FOREACH(kk, a, i) \
105 for (DnsAnswerIterator i = { .iterator = ITERATOR_FIRST, .answer = (a) }; \
107 ordered_set_iterate(i.answer->items, &i.iterator, (void**) &(i.item)) && \
108 (kk = i.item->rr, true); )
110 #define DNS_ANSWER_FOREACH(rr, a) _DNS_ANSWER_FOREACH(rr, a, UNIQ_T(i, UNIQ))
112 #define _DNS_ANSWER_FOREACH_IFINDEX(kk, ifi, a, i) \
113 for (DnsAnswerIterator i = { .iterator = ITERATOR_FIRST, .answer = (a) }; \
115 ordered_set_iterate(i.answer->items, &i.iterator, (void**) &(i.item)) && \
116 (kk = i.item->rr, ifi = i.item->ifindex, true); )
118 #define DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, a) _DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, a, UNIQ_T(i, UNIQ))
120 #define _DNS_ANSWER_FOREACH_FLAGS(kk, fl, a, i) \
121 for (DnsAnswerIterator i = { .iterator = ITERATOR_FIRST, .answer = (a) }; \
123 ordered_set_iterate(i.answer->items, &i.iterator, (void**) &(i.item)) && \
124 (kk = i.item->rr, fl = i.item->flags, true); )
126 #define DNS_ANSWER_FOREACH_FLAGS(rr, flags, a) _DNS_ANSWER_FOREACH_FLAGS(rr, flags, a, UNIQ_T(i, UNIQ))
128 #define _DNS_ANSWER_FOREACH_ITEM(it, a, i) \
129 for (DnsAnswerIterator i = { .iterator = ITERATOR_FIRST, .answer = (a) }; \
131 ordered_set_iterate(i.answer->items, &i.iterator, (void**) &(i.item)) && \
132 (it = i.item, true); )
134 #define DNS_ANSWER_FOREACH_ITEM(item, a) _DNS_ANSWER_FOREACH_ITEM(item, a, UNIQ_T(i, UNIQ))