1 /* SPDX-License-Identifier: LGPL-2.1+ */
4 #include <netinet/ip.h>
5 #include <netinet/udp.h>
8 #include "in-addr-util.h"
10 #include "sparse-endian.h"
12 typedef struct DnsPacketHeader DnsPacketHeader
;
13 typedef struct DnsPacket DnsPacket
;
15 #include "resolved-def.h"
16 #include "resolved-dns-answer.h"
17 #include "resolved-dns-question.h"
18 #include "resolved-dns-rr.h"
20 typedef enum DnsProtocol
{
25 _DNS_PROTOCOL_INVALID
= -1
28 struct DnsPacketHeader
{
37 #define DNS_PACKET_HEADER_SIZE sizeof(DnsPacketHeader)
38 #define UDP_PACKET_HEADER_SIZE (sizeof(struct iphdr) + sizeof(struct udphdr))
40 /* The various DNS protocols deviate in how large a packet can grow,
41 * but the TCP transport has a 16bit size field, hence that appears to
42 * be the absolute maximum. */
43 #define DNS_PACKET_SIZE_MAX 0xFFFFu
45 /* The default size to use for allocation when we don't know how large
46 * the packet will turn out to be. */
47 #define DNS_PACKET_SIZE_START 512u
49 /* RFC 1035 say 512 is the maximum, for classic unicast DNS */
50 #define DNS_PACKET_UNICAST_SIZE_MAX 512u
52 /* With EDNS0 we can use larger packets, default to 4096, which is what is commonly used */
53 #define DNS_PACKET_UNICAST_SIZE_LARGE_MAX 4096u
58 size_t size
, allocated
, rindex
, max_size
;
59 void *_data
; /* don't access directly, use DNS_PACKET_DATA()! */
60 Hashmap
*names
; /* For name compression */
61 size_t opt_start
, opt_size
;
64 DnsQuestion
*question
;
66 DnsResourceRecord
*opt
;
68 /* Packet reception metadata */
71 union in_addr_union sender
, destination
;
72 uint16_t sender_port
, destination_port
;
75 /* For support of truncated packets */
80 bool refuse_compression
:1;
81 bool canonical_form
:1;
84 static inline uint8_t* DNS_PACKET_DATA(DnsPacket
*p
) {
91 return ((uint8_t*) p
) + ALIGN(sizeof(DnsPacket
));
94 #define DNS_PACKET_HEADER(p) ((DnsPacketHeader*) DNS_PACKET_DATA(p))
95 #define DNS_PACKET_ID(p) DNS_PACKET_HEADER(p)->id
96 #define DNS_PACKET_QR(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 15) & 1)
97 #define DNS_PACKET_OPCODE(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 11) & 15)
98 #define DNS_PACKET_AA(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 10) & 1)
99 #define DNS_PACKET_TC(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 9) & 1)
100 #define DNS_PACKET_RD(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 8) & 1)
101 #define DNS_PACKET_RA(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 7) & 1)
102 #define DNS_PACKET_AD(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 5) & 1)
103 #define DNS_PACKET_CD(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 4) & 1)
105 #define DNS_PACKET_FLAG_TC (UINT16_C(1) << 9)
107 static inline uint16_t DNS_PACKET_RCODE(DnsPacket
*p
) {
111 rcode
= (uint16_t) (p
->opt
->ttl
>> 24);
115 return rcode
| (be16toh(DNS_PACKET_HEADER(p
)->flags
) & 0xF);
118 static inline uint16_t DNS_PACKET_PAYLOAD_SIZE_MAX(DnsPacket
*p
) {
120 /* Returns the advertised maximum size for replies, or the DNS default if there's nothing defined. */
122 if (p
->ipproto
== IPPROTO_TCP
) /* we ignore EDNS(0) size data on TCP, like everybody else */
123 return DNS_PACKET_SIZE_MAX
;
126 return MAX(DNS_PACKET_UNICAST_SIZE_MAX
, p
->opt
->key
->class);
128 return DNS_PACKET_UNICAST_SIZE_MAX
;
131 static inline bool DNS_PACKET_DO(DnsPacket
*p
) {
135 return !!(p
->opt
->ttl
& (1U << 15));
138 static inline bool DNS_PACKET_VERSION_SUPPORTED(DnsPacket
*p
) {
139 /* Returns true if this packet is in a version we support. Which means either non-EDNS or EDNS(0), but not EDNS
140 * of any newer versions */
145 return DNS_RESOURCE_RECORD_OPT_VERSION_SUPPORTED(p
->opt
);
148 /* LLMNR defines some bits differently */
149 #define DNS_PACKET_LLMNR_C(p) DNS_PACKET_AA(p)
150 #define DNS_PACKET_LLMNR_T(p) DNS_PACKET_RD(p)
152 #define DNS_PACKET_QDCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->qdcount)
153 #define DNS_PACKET_ANCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->ancount)
154 #define DNS_PACKET_NSCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->nscount)
155 #define DNS_PACKET_ARCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->arcount)
157 #define DNS_PACKET_MAKE_FLAGS(qr, opcode, aa, tc, rd, ra, ad, cd, rcode) \
158 (((uint16_t) !!(qr) << 15) | \
159 ((uint16_t) ((opcode) & 15) << 11) | \
160 ((uint16_t) !!(aa) << 10) | /* on LLMNR: c */ \
161 ((uint16_t) !!(tc) << 9) | \
162 ((uint16_t) !!(rd) << 8) | /* on LLMNR: t */ \
163 ((uint16_t) !!(ra) << 7) | \
164 ((uint16_t) !!(ad) << 5) | \
165 ((uint16_t) !!(cd) << 4) | \
166 ((uint16_t) ((rcode) & 15)))
168 static inline unsigned DNS_PACKET_RRCOUNT(DnsPacket
*p
) {
170 (unsigned) DNS_PACKET_ANCOUNT(p
) +
171 (unsigned) DNS_PACKET_NSCOUNT(p
) +
172 (unsigned) DNS_PACKET_ARCOUNT(p
);
175 int dns_packet_new(DnsPacket
**p
, DnsProtocol protocol
, size_t min_alloc_dsize
, size_t max_size
);
176 int dns_packet_new_query(DnsPacket
**p
, DnsProtocol protocol
, size_t min_alloc_dsize
, bool dnssec_checking_disabled
);
178 void dns_packet_set_flags(DnsPacket
*p
, bool dnssec_checking_disabled
, bool truncated
);
180 DnsPacket
*dns_packet_ref(DnsPacket
*p
);
181 DnsPacket
*dns_packet_unref(DnsPacket
*p
);
183 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsPacket
*, dns_packet_unref
);
185 int dns_packet_validate(DnsPacket
*p
);
186 int dns_packet_validate_reply(DnsPacket
*p
);
187 int dns_packet_validate_query(DnsPacket
*p
);
189 int dns_packet_is_reply_for(DnsPacket
*p
, const DnsResourceKey
*key
);
191 int dns_packet_append_blob(DnsPacket
*p
, const void *d
, size_t sz
, size_t *start
);
192 int dns_packet_append_uint8(DnsPacket
*p
, uint8_t v
, size_t *start
);
193 int dns_packet_append_uint16(DnsPacket
*p
, uint16_t v
, size_t *start
);
194 int dns_packet_append_uint32(DnsPacket
*p
, uint32_t v
, size_t *start
);
195 int dns_packet_append_string(DnsPacket
*p
, const char *s
, size_t *start
);
196 int dns_packet_append_raw_string(DnsPacket
*p
, const void *s
, size_t size
, size_t *start
);
197 int dns_packet_append_label(DnsPacket
*p
, const char *s
, size_t l
, bool canonical_candidate
, size_t *start
);
198 int dns_packet_append_name(DnsPacket
*p
, const char *name
, bool allow_compression
, bool canonical_candidate
, size_t *start
);
199 int dns_packet_append_key(DnsPacket
*p
, const DnsResourceKey
*key
, const DnsAnswerFlags flags
, size_t *start
);
200 int dns_packet_append_rr(DnsPacket
*p
, const DnsResourceRecord
*rr
, const DnsAnswerFlags flags
, size_t *start
, size_t *rdata_start
);
201 int dns_packet_append_opt(DnsPacket
*p
, uint16_t max_udp_size
, bool edns0_do
, int rcode
, size_t *start
);
202 int dns_packet_append_question(DnsPacket
*p
, DnsQuestion
*q
);
203 int dns_packet_append_answer(DnsPacket
*p
, DnsAnswer
*a
);
205 void dns_packet_truncate(DnsPacket
*p
, size_t sz
);
206 int dns_packet_truncate_opt(DnsPacket
*p
);
208 int dns_packet_read(DnsPacket
*p
, size_t sz
, const void **ret
, size_t *start
);
209 int dns_packet_read_blob(DnsPacket
*p
, void *d
, size_t sz
, size_t *start
);
210 int dns_packet_read_uint8(DnsPacket
*p
, uint8_t *ret
, size_t *start
);
211 int dns_packet_read_uint16(DnsPacket
*p
, uint16_t *ret
, size_t *start
);
212 int dns_packet_read_uint32(DnsPacket
*p
, uint32_t *ret
, size_t *start
);
213 int dns_packet_read_string(DnsPacket
*p
, char **ret
, size_t *start
);
214 int dns_packet_read_raw_string(DnsPacket
*p
, const void **ret
, size_t *size
, size_t *start
);
215 int dns_packet_read_name(DnsPacket
*p
, char **ret
, bool allow_compression
, size_t *start
);
216 int dns_packet_read_key(DnsPacket
*p
, DnsResourceKey
**ret
, bool *ret_cache_flush
, size_t *start
);
217 int dns_packet_read_rr(DnsPacket
*p
, DnsResourceRecord
**ret
, bool *ret_cache_flush
, size_t *start
);
219 void dns_packet_rewind(DnsPacket
*p
, size_t idx
);
221 int dns_packet_skip_question(DnsPacket
*p
);
222 int dns_packet_extract(DnsPacket
*p
);
224 static inline bool DNS_PACKET_SHALL_CACHE(DnsPacket
*p
) {
225 /* Never cache data originating from localhost, under the
226 * assumption, that it's coming from a locally DNS forwarder
227 * or server, that is caching on its own. */
229 return in_addr_is_localhost(p
->family
, &p
->sender
) == 0;
232 /* https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6 */
234 DNS_RCODE_SUCCESS
= 0,
235 DNS_RCODE_FORMERR
= 1,
236 DNS_RCODE_SERVFAIL
= 2,
237 DNS_RCODE_NXDOMAIN
= 3,
238 DNS_RCODE_NOTIMP
= 4,
239 DNS_RCODE_REFUSED
= 5,
240 DNS_RCODE_YXDOMAIN
= 6,
241 DNS_RCODE_YXRRSET
= 7,
242 DNS_RCODE_NXRRSET
= 8,
243 DNS_RCODE_NOTAUTH
= 9,
244 DNS_RCODE_NOTZONE
= 10,
245 DNS_RCODE_BADVERS
= 16,
246 DNS_RCODE_BADSIG
= 16, /* duplicate value! */
247 DNS_RCODE_BADKEY
= 17,
248 DNS_RCODE_BADTIME
= 18,
249 DNS_RCODE_BADMODE
= 19,
250 DNS_RCODE_BADNAME
= 20,
251 DNS_RCODE_BADALG
= 21,
252 DNS_RCODE_BADTRUNC
= 22,
253 DNS_RCODE_BADCOOKIE
= 23,
254 _DNS_RCODE_MAX_DEFINED
,
255 _DNS_RCODE_MAX
= 4095 /* 4 bit rcode in the header plus 8 bit rcode in OPT, makes 12 bit */
258 const char* dns_rcode_to_string(int i
) _const_
;
259 int dns_rcode_from_string(const char *s
) _pure_
;
261 const char* dns_protocol_to_string(DnsProtocol p
) _const_
;
262 DnsProtocol
dns_protocol_from_string(const char *s
) _pure_
;
264 #define LLMNR_MULTICAST_IPV4_ADDRESS ((struct in_addr) { .s_addr = htobe32(224U << 24 | 252U) })
265 #define LLMNR_MULTICAST_IPV6_ADDRESS ((struct in6_addr) { .s6_addr = { 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03 } })
267 #define MDNS_MULTICAST_IPV4_ADDRESS ((struct in_addr) { .s_addr = htobe32(224U << 24 | 251U) })
268 #define MDNS_MULTICAST_IPV6_ADDRESS ((struct in6_addr) { .s6_addr = { 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb } })
270 extern const struct hash_ops dns_packet_hash_ops
;
272 static inline uint64_t SD_RESOLVED_FLAGS_MAKE(DnsProtocol protocol
, int family
, bool authenticated
) {
275 /* Converts a protocol + family into a flags field as used in queries and responses */
277 f
= authenticated
? SD_RESOLVED_AUTHENTICATED
: 0;
280 case DNS_PROTOCOL_DNS
:
281 return f
|SD_RESOLVED_DNS
;
283 case DNS_PROTOCOL_LLMNR
:
284 return f
|(family
== AF_INET6
? SD_RESOLVED_LLMNR_IPV6
: SD_RESOLVED_LLMNR_IPV4
);
286 case DNS_PROTOCOL_MDNS
:
287 return f
|(family
== AF_INET6
? SD_RESOLVED_MDNS_IPV6
: SD_RESOLVED_MDNS_IPV4
);
294 static inline size_t dns_packet_size_max(DnsPacket
*p
) {
297 /* Why not insist on a fully initialized max_size during DnsPacket construction? Well, this way it's easy to
298 * allocate a transient, throw-away DnsPacket on the stack by simple zero initialization, without having to
299 * deal with explicit field initialization. */
301 return p
->max_size
!= 0 ? p
->max_size
: DNS_PACKET_SIZE_MAX
;