1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
4 typedef struct DnsAnswer DnsAnswer
;
5 typedef struct DnsAnswerItem DnsAnswerItem
;
8 #include "ordered-set.h"
9 #include "resolved-dns-rr.h"
11 /* A simple array of resource records. We keep track of the originating ifindex for each RR where that makes
12 * sense, so that we can qualify A and AAAA RRs referring to a local link with the right ifindex.
14 * Note that we usually encode the empty DnsAnswer object as a simple NULL. */
16 typedef enum DnsAnswerFlags
{
17 DNS_ANSWER_AUTHENTICATED
= 1 << 0, /* Item has been authenticated */
18 DNS_ANSWER_CACHEABLE
= 1 << 1, /* Item is subject to caching */
19 DNS_ANSWER_SHARED_OWNER
= 1 << 2, /* For mDNS: RRset may be owner by multiple peers */
20 DNS_ANSWER_CACHE_FLUSH
= 1 << 3, /* For mDNS: sets cache-flush bit in the rrclass of response records */
21 DNS_ANSWER_GOODBYE
= 1 << 4, /* For mDNS: item is subject to disappear */
22 DNS_ANSWER_SECTION_ANSWER
= 1 << 5, /* When parsing: RR originates from answer section */
23 DNS_ANSWER_SECTION_AUTHORITY
= 1 << 6, /* When parsing: RR originates from authority section */
24 DNS_ANSWER_SECTION_ADDITIONAL
= 1 << 7, /* When parsing: RR originates from additional section */
25 DNS_ANSWER_REFUSE_TTL_NO_MATCH
= 1 << 8, /* For mDNS; refuse to merge a zero TTL RR with a nonzero TTL RR */
27 DNS_ANSWER_MASK_SECTIONS
= DNS_ANSWER_SECTION_ANSWER
|
28 DNS_ANSWER_SECTION_AUTHORITY
|
29 DNS_ANSWER_SECTION_ADDITIONAL
,
32 struct DnsAnswerItem
{
34 DnsResourceRecord
*rr
;
35 DnsResourceRecord
*rrsig
; /* Optionally, also store RRSIG RR that successfully validates this item */
45 DnsAnswer
*dns_answer_new(size_t n
);
46 DnsAnswer
*dns_answer_ref(DnsAnswer
*a
);
47 DnsAnswer
*dns_answer_unref(DnsAnswer
*a
);
49 #define DNS_ANSWER_REPLACE(a, b) \
51 typeof(a)* _a = &(a); \
53 dns_answer_unref(*_a); \
57 int dns_answer_add(DnsAnswer
*a
, DnsResourceRecord
*rr
, int ifindex
, DnsAnswerFlags flags
, DnsResourceRecord
*rrsig
);
58 int dns_answer_add_extend(DnsAnswer
**a
, DnsResourceRecord
*rr
, int ifindex
, DnsAnswerFlags flags
, DnsResourceRecord
*rrsig
);
59 int dns_answer_add_soa(DnsAnswer
*a
, const char *name
, uint32_t ttl
, int ifindex
);
61 int dns_answer_match_key(DnsAnswer
*a
, const DnsResourceKey
*key
, DnsAnswerFlags
*ret_flags
);
62 bool dns_answer_contains_nsec_or_nsec3(DnsAnswer
*a
);
63 int dns_answer_contains_zone_nsec3(DnsAnswer
*answer
, const char *zone
);
64 bool dns_answer_contains(DnsAnswer
*answer
, DnsResourceRecord
*rr
);
66 int dns_answer_find_soa(DnsAnswer
*a
, const DnsResourceKey
*key
, DnsResourceRecord
**ret
, DnsAnswerFlags
*ret_flags
);
67 int dns_answer_find_cname_or_dname(DnsAnswer
*a
, const DnsResourceKey
*key
, DnsResourceRecord
**ret
, DnsAnswerFlags
*ret_flags
);
69 int dns_answer_merge(DnsAnswer
*a
, DnsAnswer
*b
, DnsAnswer
**ret
);
70 int dns_answer_extend(DnsAnswer
**a
, DnsAnswer
*b
);
72 void dns_answer_order_by_scope(DnsAnswer
*a
, bool prefer_link_local
);
74 int dns_answer_reserve(DnsAnswer
**a
, size_t n_free
);
75 int dns_answer_reserve_or_clone(DnsAnswer
**a
, size_t n_free
);
77 int dns_answer_remove_by_key(DnsAnswer
**a
, const DnsResourceKey
*key
);
78 int dns_answer_remove_by_rr(DnsAnswer
**a
, DnsResourceRecord
*rr
);
79 int dns_answer_remove_by_answer_keys(DnsAnswer
**a
, DnsAnswer
*b
);
81 int dns_answer_copy_by_key(DnsAnswer
**a
, DnsAnswer
*source
, const DnsResourceKey
*key
, DnsAnswerFlags or_flags
, DnsResourceRecord
*rrsig
);
82 int dns_answer_move_by_key(DnsAnswer
**to
, DnsAnswer
**from
, const DnsResourceKey
*key
, DnsAnswerFlags or_flags
, DnsResourceRecord
*rrsig
);
84 int dns_answer_has_dname_for_cname(DnsAnswer
*a
, DnsResourceRecord
*cname
);
86 static inline size_t dns_answer_size(DnsAnswer
*a
) {
87 return a
? ordered_set_size(a
->items
) : 0;
90 static inline bool dns_answer_isempty(DnsAnswer
*a
) {
91 return dns_answer_size(a
) <= 0;
94 void dns_answer_dump(DnsAnswer
*answer
, FILE *f
);
96 void dns_answer_randomize(DnsAnswer
*a
);
98 uint32_t dns_answer_min_ttl(DnsAnswer
*a
);
100 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsAnswer
*, dns_answer_unref
);
102 typedef struct DnsAnswerIterator
{
108 #define _DNS_ANSWER_FOREACH(kk, a, i) \
109 for (DnsAnswerIterator i = { .iterator = ITERATOR_FIRST, .answer = (a) }; \
111 ordered_set_iterate(i.answer->items, &i.iterator, (void**) &(i.item)) && \
112 (kk = i.item->rr, true); )
114 #define DNS_ANSWER_FOREACH(rr, a) _DNS_ANSWER_FOREACH(rr, a, UNIQ_T(i, UNIQ))
116 #define _DNS_ANSWER_FOREACH_IFINDEX(kk, ifi, a, i) \
117 for (DnsAnswerIterator i = { .iterator = ITERATOR_FIRST, .answer = (a) }; \
119 ordered_set_iterate(i.answer->items, &i.iterator, (void**) &(i.item)) && \
120 (kk = i.item->rr, ifi = i.item->ifindex, true); )
122 #define DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, a) _DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, a, UNIQ_T(i, UNIQ))
124 #define _DNS_ANSWER_FOREACH_FLAGS(kk, fl, a, i) \
125 for (DnsAnswerIterator i = { .iterator = ITERATOR_FIRST, .answer = (a) }; \
127 ordered_set_iterate(i.answer->items, &i.iterator, (void**) &(i.item)) && \
128 (kk = i.item->rr, fl = i.item->flags, true); )
130 #define DNS_ANSWER_FOREACH_FLAGS(rr, flags, a) _DNS_ANSWER_FOREACH_FLAGS(rr, flags, a, UNIQ_T(i, UNIQ))
132 #define _DNS_ANSWER_FOREACH_ITEM(it, a, i) \
133 for (DnsAnswerIterator i = { .iterator = ITERATOR_FIRST, .answer = (a) }; \
135 ordered_set_iterate(i.answer->items, &i.iterator, (void**) &(i.item)) && \
136 (it = i.item, true); )
138 #define DNS_ANSWER_FOREACH_ITEM(item, a) _DNS_ANSWER_FOREACH_ITEM(item, a, UNIQ_T(i, UNIQ))