1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
4 typedef struct DnsAnswer DnsAnswer
;
5 typedef struct DnsAnswerItem DnsAnswerItem
;
8 #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 */
26 DNS_ANSWER_MASK_SECTIONS
= DNS_ANSWER_SECTION_ANSWER
|
27 DNS_ANSWER_SECTION_AUTHORITY
|
28 DNS_ANSWER_SECTION_ADDITIONAL
,
31 struct DnsAnswerItem
{
32 DnsResourceRecord
*rr
;
33 DnsResourceRecord
*rrsig
; /* Optionally, also store RRSIG RR that successfully validates this item */
40 Set
*set_items
; /* Used by dns_answer_add() for optimization. */
41 size_t n_rrs
, n_allocated
;
42 DnsAnswerItem items
[0];
45 DnsAnswer
*dns_answer_new(size_t n
);
46 DnsAnswer
*dns_answer_ref(DnsAnswer
*a
);
47 DnsAnswer
*dns_answer_unref(DnsAnswer
*a
);
49 int dns_answer_add(DnsAnswer
*a
, DnsResourceRecord
*rr
, int ifindex
, DnsAnswerFlags flags
, DnsResourceRecord
*rrsig
);
50 int dns_answer_add_extend(DnsAnswer
**a
, DnsResourceRecord
*rr
, int ifindex
, DnsAnswerFlags flags
, DnsResourceRecord
*rrsig
);
51 int dns_answer_add_soa(DnsAnswer
*a
, const char *name
, uint32_t ttl
, int ifindex
);
53 int dns_answer_match_key(DnsAnswer
*a
, const DnsResourceKey
*key
, DnsAnswerFlags
*combined_flags
);
54 int dns_answer_contains_nsec_or_nsec3(DnsAnswer
*a
);
55 int dns_answer_contains_zone_nsec3(DnsAnswer
*answer
, const char *zone
);
56 int dns_answer_contains(DnsAnswer
*answer
, DnsResourceRecord
*rr
);
58 int dns_answer_find_soa(DnsAnswer
*a
, const DnsResourceKey
*key
, DnsResourceRecord
**ret
, DnsAnswerFlags
*ret_flags
);
59 int dns_answer_find_cname_or_dname(DnsAnswer
*a
, const DnsResourceKey
*key
, DnsResourceRecord
**ret
, DnsAnswerFlags
*ret_flags
);
61 int dns_answer_merge(DnsAnswer
*a
, DnsAnswer
*b
, DnsAnswer
**ret
);
62 int dns_answer_extend(DnsAnswer
**a
, DnsAnswer
*b
);
64 void dns_answer_order_by_scope(DnsAnswer
*a
, bool prefer_link_local
);
66 int dns_answer_reserve(DnsAnswer
**a
, size_t n_free
);
67 int dns_answer_reserve_or_clone(DnsAnswer
**a
, size_t n_free
);
69 int dns_answer_remove_by_key(DnsAnswer
**a
, const DnsResourceKey
*key
);
70 int dns_answer_remove_by_rr(DnsAnswer
**a
, DnsResourceRecord
*rr
);
71 int dns_answer_remove_by_answer_keys(DnsAnswer
**a
, DnsAnswer
*b
);
73 int dns_answer_copy_by_key(DnsAnswer
**a
, DnsAnswer
*source
, const DnsResourceKey
*key
, DnsAnswerFlags or_flags
, DnsResourceRecord
*rrsig
);
74 int dns_answer_move_by_key(DnsAnswer
**to
, DnsAnswer
**from
, const DnsResourceKey
*key
, DnsAnswerFlags or_flags
, DnsResourceRecord
*rrsig
);
76 int dns_answer_has_dname_for_cname(DnsAnswer
*a
, DnsResourceRecord
*cname
);
78 static inline size_t dns_answer_size(DnsAnswer
*a
) {
79 return a
? a
->n_rrs
: 0;
82 static inline bool dns_answer_isempty(DnsAnswer
*a
) {
83 return dns_answer_size(a
) <= 0;
86 void dns_answer_dump(DnsAnswer
*answer
, FILE *f
);
88 void dns_answer_randomize(DnsAnswer
*a
);
90 uint32_t dns_answer_min_ttl(DnsAnswer
*a
);
92 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsAnswer
*, dns_answer_unref
);
94 #define _DNS_ANSWER_FOREACH(q, kk, a) \
95 for (size_t UNIQ_T(i, q) = ({ \
96 (kk) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].rr : NULL; \
99 (a) && (UNIQ_T(i, q) < (a)->n_rrs); \
100 UNIQ_T(i, q)++, (kk) = (UNIQ_T(i, q) < (a)->n_rrs ? (a)->items[UNIQ_T(i, q)].rr : NULL))
102 #define DNS_ANSWER_FOREACH(kk, a) _DNS_ANSWER_FOREACH(UNIQ, kk, a)
104 #define _DNS_ANSWER_FOREACH_IFINDEX(q, kk, ifi, a) \
105 for (size_t UNIQ_T(i, q) = ({ \
106 (kk) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].rr : NULL; \
107 (ifi) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].ifindex : 0; \
110 (a) && (UNIQ_T(i, q) < (a)->n_rrs); \
112 (kk) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].rr : NULL), \
113 (ifi) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].ifindex : 0))
115 #define DNS_ANSWER_FOREACH_IFINDEX(kk, ifindex, a) _DNS_ANSWER_FOREACH_IFINDEX(UNIQ, kk, ifindex, a)
117 #define _DNS_ANSWER_FOREACH_FLAGS(q, kk, fl, a) \
118 for (size_t UNIQ_T(i, q) = ({ \
119 (kk) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].rr : NULL; \
120 (fl) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].flags : 0; \
123 (a) && (UNIQ_T(i, q) < (a)->n_rrs); \
125 (kk) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].rr : NULL), \
126 (fl) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].flags : 0))
128 #define DNS_ANSWER_FOREACH_FLAGS(kk, flags, a) _DNS_ANSWER_FOREACH_FLAGS(UNIQ, kk, flags, a)
130 #define _DNS_ANSWER_FOREACH_ITEM(q, item, a) \
131 for (size_t UNIQ_T(i, q) = ({ \
132 (item) = dns_answer_isempty(a) ? NULL : (a)->items; \
135 UNIQ_T(i, q) < dns_answer_size(a); \
137 (item) = ((UNIQ_T(i, q) < dns_answer_size(a)) ? (a)->items + UNIQ_T(i, q) : NULL))
139 #define DNS_ANSWER_FOREACH_ITEM(item, a) _DNS_ANSWER_FOREACH_ITEM(UNIQ, item, a)