1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2014 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
25 #include "unaligned.h"
26 #include "dns-domain.h"
27 #include "resolved-dns-packet.h"
29 int dns_packet_new(DnsPacket
**ret
, DnsProtocol protocol
, size_t mtu
) {
35 if (mtu
<= UDP_PACKET_HEADER_SIZE
)
36 a
= DNS_PACKET_SIZE_START
;
38 a
= mtu
- UDP_PACKET_HEADER_SIZE
;
40 if (a
< DNS_PACKET_HEADER_SIZE
)
41 a
= DNS_PACKET_HEADER_SIZE
;
43 /* round up to next page size */
44 a
= PAGE_ALIGN(ALIGN(sizeof(DnsPacket
)) + a
) - ALIGN(sizeof(DnsPacket
));
46 /* make sure we never allocate more than useful */
47 if (a
> DNS_PACKET_SIZE_MAX
)
48 a
= DNS_PACKET_SIZE_MAX
;
50 p
= malloc0(ALIGN(sizeof(DnsPacket
)) + a
);
54 p
->size
= p
->rindex
= DNS_PACKET_HEADER_SIZE
;
56 p
->protocol
= protocol
;
64 int dns_packet_new_query(DnsPacket
**ret
, DnsProtocol protocol
, size_t mtu
) {
71 r
= dns_packet_new(&p
, protocol
, mtu
);
75 h
= DNS_PACKET_HEADER(p
);
77 if (protocol
== DNS_PROTOCOL_LLMNR
)
78 h
->flags
= htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
88 h
->flags
= htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
92 1 /* rd (ask for recursion) */,
102 DnsPacket
*dns_packet_ref(DnsPacket
*p
) {
107 assert(p
->n_ref
> 0);
112 static void dns_packet_free(DnsPacket
*p
) {
117 dns_question_unref(p
->question
);
118 dns_answer_unref(p
->answer
);
120 while ((s
= hashmap_steal_first_key(p
->names
)))
122 hashmap_free(p
->names
);
128 DnsPacket
*dns_packet_unref(DnsPacket
*p
) {
132 assert(p
->n_ref
> 0);
142 int dns_packet_validate(DnsPacket
*p
) {
145 if (p
->size
< DNS_PACKET_HEADER_SIZE
)
148 if (p
->size
> DNS_PACKET_SIZE_MAX
)
154 int dns_packet_validate_reply(DnsPacket
*p
) {
159 r
= dns_packet_validate(p
);
163 if (DNS_PACKET_QR(p
) != 1)
166 if (DNS_PACKET_OPCODE(p
) != 0)
169 switch (p
->protocol
) {
170 case DNS_PROTOCOL_LLMNR
:
171 /* RFC 4795, Section 2.1.1. says to discard all replies with QDCOUNT != 1 */
172 if (DNS_PACKET_QDCOUNT(p
) != 1)
184 int dns_packet_validate_query(DnsPacket
*p
) {
189 r
= dns_packet_validate(p
);
193 if (DNS_PACKET_QR(p
) != 0)
196 if (DNS_PACKET_OPCODE(p
) != 0)
199 if (DNS_PACKET_TC(p
))
202 switch (p
->protocol
) {
203 case DNS_PROTOCOL_LLMNR
:
204 /* RFC 4795, Section 2.1.1. says to discard all queries with QDCOUNT != 1 */
205 if (DNS_PACKET_QDCOUNT(p
) != 1)
208 /* RFC 4795, Section 2.1.1. says to discard all queries with ANCOUNT != 0 */
209 if (DNS_PACKET_ANCOUNT(p
) > 0)
212 /* RFC 4795, Section 2.1.1. says to discard all queries with NSCOUNT != 0 */
213 if (DNS_PACKET_NSCOUNT(p
) > 0)
225 static int dns_packet_extend(DnsPacket
*p
, size_t add
, void **ret
, size_t *start
) {
228 if (p
->size
+ add
> p
->allocated
) {
231 a
= PAGE_ALIGN((p
->size
+ add
) * 2);
232 if (a
> DNS_PACKET_SIZE_MAX
)
233 a
= DNS_PACKET_SIZE_MAX
;
235 if (p
->size
+ add
> a
)
241 d
= realloc(p
->_data
, a
);
247 p
->_data
= malloc(a
);
251 memcpy(p
->_data
, (uint8_t*) p
+ ALIGN(sizeof(DnsPacket
)), p
->size
);
252 memzero((uint8_t*) p
->_data
+ p
->size
, a
- p
->size
);
262 *ret
= (uint8_t*) DNS_PACKET_DATA(p
) + p
->size
;
268 static void dns_packet_truncate(DnsPacket
*p
, size_t sz
) {
278 HASHMAP_FOREACH_KEY(s
, n
, p
->names
, i
) {
280 if (PTR_TO_SIZE(n
) < sz
)
283 hashmap_remove(p
->names
, s
);
290 int dns_packet_append_blob(DnsPacket
*p
, const void *d
, size_t l
, size_t *start
) {
296 r
= dns_packet_extend(p
, l
, &q
, start
);
304 int dns_packet_append_uint8(DnsPacket
*p
, uint8_t v
, size_t *start
) {
310 r
= dns_packet_extend(p
, sizeof(uint8_t), &d
, start
);
314 ((uint8_t*) d
)[0] = v
;
319 int dns_packet_append_uint16(DnsPacket
*p
, uint16_t v
, size_t *start
) {
325 r
= dns_packet_extend(p
, sizeof(uint16_t), &d
, start
);
329 unaligned_write_be16(d
, v
);
334 int dns_packet_append_uint32(DnsPacket
*p
, uint32_t v
, size_t *start
) {
340 r
= dns_packet_extend(p
, sizeof(uint32_t), &d
, start
);
344 unaligned_write_be32(d
, v
);
349 int dns_packet_append_string(DnsPacket
*p
, const char *s
, size_t *start
) {
361 r
= dns_packet_extend(p
, 1 + l
, &d
, start
);
365 ((uint8_t*) d
)[0] = (uint8_t) l
;
366 memcpy(((uint8_t*) d
) + 1, s
, l
);
371 int dns_packet_append_label(DnsPacket
*p
, const char *d
, size_t l
, size_t *start
) {
378 if (l
> DNS_LABEL_MAX
)
381 r
= dns_packet_extend(p
, 1 + l
, &w
, start
);
385 ((uint8_t*) w
)[0] = (uint8_t) l
;
386 memcpy(((uint8_t*) w
) + 1, d
, l
);
391 int dns_packet_append_name(DnsPacket
*p
, const char *name
,
392 bool allow_compression
, size_t *start
) {
399 saved_size
= p
->size
;
402 _cleanup_free_
char *s
= NULL
;
403 char label
[DNS_LABEL_MAX
];
407 if (allow_compression
)
408 n
= PTR_TO_SIZE(hashmap_get(p
->names
, name
));
413 r
= dns_packet_append_uint16(p
, 0xC000 | n
, NULL
);
427 r
= dns_label_unescape(&name
, label
, sizeof(label
));
431 if (p
->protocol
== DNS_PROTOCOL_DNS
)
432 k
= dns_label_apply_idna(label
, r
, label
, sizeof(label
));
434 k
= dns_label_undo_idna(label
, r
, label
, sizeof(label
));
442 r
= dns_packet_append_label(p
, label
, r
, &n
);
446 if (allow_compression
) {
447 r
= hashmap_ensure_allocated(&p
->names
, &dns_name_hash_ops
);
451 r
= hashmap_put(p
->names
, s
, SIZE_TO_PTR(n
));
459 r
= dns_packet_append_uint8(p
, 0, NULL
);
470 dns_packet_truncate(p
, saved_size
);
474 int dns_packet_append_key(DnsPacket
*p
, const DnsResourceKey
*k
, size_t *start
) {
481 saved_size
= p
->size
;
483 r
= dns_packet_append_name(p
, DNS_RESOURCE_KEY_NAME(k
), true, NULL
);
487 r
= dns_packet_append_uint16(p
, k
->type
, NULL
);
491 r
= dns_packet_append_uint16(p
, k
->class, NULL
);
501 dns_packet_truncate(p
, saved_size
);
505 int dns_packet_append_rr(DnsPacket
*p
, const DnsResourceRecord
*rr
, size_t *start
) {
506 size_t saved_size
, rdlength_offset
, end
, rdlength
;
512 saved_size
= p
->size
;
514 r
= dns_packet_append_key(p
, rr
->key
, NULL
);
518 r
= dns_packet_append_uint32(p
, rr
->ttl
, NULL
);
522 /* Initially we write 0 here */
523 r
= dns_packet_append_uint16(p
, 0, &rdlength_offset
);
527 switch (rr
->unparseable
? _DNS_TYPE_INVALID
: rr
->key
->type
) {
530 r
= dns_packet_append_uint16(p
, rr
->srv
.priority
, NULL
);
534 r
= dns_packet_append_uint16(p
, rr
->srv
.weight
, NULL
);
538 r
= dns_packet_append_uint16(p
, rr
->srv
.port
, NULL
);
542 r
= dns_packet_append_name(p
, rr
->srv
.name
, true, NULL
);
549 r
= dns_packet_append_name(p
, rr
->ptr
.name
, true, NULL
);
553 r
= dns_packet_append_string(p
, rr
->hinfo
.cpu
, NULL
);
557 r
= dns_packet_append_string(p
, rr
->hinfo
.os
, NULL
);
560 case DNS_TYPE_SPF
: /* exactly the same as TXT */
564 if (strv_isempty(rr
->txt
.strings
)) {
565 /* RFC 6763, section 6.1 suggests to generate
566 * single empty string for an empty array. */
568 r
= dns_packet_append_string(p
, "", NULL
);
572 STRV_FOREACH(s
, rr
->txt
.strings
) {
573 r
= dns_packet_append_string(p
, *s
, NULL
);
584 r
= dns_packet_append_blob(p
, &rr
->a
.in_addr
, sizeof(struct in_addr
), NULL
);
588 r
= dns_packet_append_blob(p
, &rr
->aaaa
.in6_addr
, sizeof(struct in6_addr
), NULL
);
592 r
= dns_packet_append_name(p
, rr
->soa
.mname
, true, NULL
);
596 r
= dns_packet_append_name(p
, rr
->soa
.rname
, true, NULL
);
600 r
= dns_packet_append_uint32(p
, rr
->soa
.serial
, NULL
);
604 r
= dns_packet_append_uint32(p
, rr
->soa
.refresh
, NULL
);
608 r
= dns_packet_append_uint32(p
, rr
->soa
.retry
, NULL
);
612 r
= dns_packet_append_uint32(p
, rr
->soa
.expire
, NULL
);
616 r
= dns_packet_append_uint32(p
, rr
->soa
.minimum
, NULL
);
620 r
= dns_packet_append_uint16(p
, rr
->mx
.priority
, NULL
);
624 r
= dns_packet_append_name(p
, rr
->mx
.exchange
, true, NULL
);
628 r
= dns_packet_append_uint8(p
, rr
->loc
.version
, NULL
);
632 r
= dns_packet_append_uint8(p
, rr
->loc
.size
, NULL
);
636 r
= dns_packet_append_uint8(p
, rr
->loc
.horiz_pre
, NULL
);
640 r
= dns_packet_append_uint8(p
, rr
->loc
.vert_pre
, NULL
);
644 r
= dns_packet_append_uint32(p
, rr
->loc
.latitude
, NULL
);
648 r
= dns_packet_append_uint32(p
, rr
->loc
.longitude
, NULL
);
652 r
= dns_packet_append_uint32(p
, rr
->loc
.altitude
, NULL
);
656 r
= dns_packet_append_uint8(p
, rr
->sshfp
.algorithm
, NULL
);
660 r
= dns_packet_append_uint8(p
, rr
->sshfp
.fptype
, NULL
);
664 r
= dns_packet_append_blob(p
, rr
->sshfp
.key
, rr
->sshfp
.key_size
, NULL
);
667 case DNS_TYPE_DNSKEY
:
668 r
= dns_packet_append_uint16(p
, dnskey_to_flags(rr
), NULL
);
672 r
= dns_packet_append_uint8(p
, 3u, NULL
);
676 r
= dns_packet_append_uint8(p
, rr
->dnskey
.algorithm
, NULL
);
680 r
= dns_packet_append_blob(p
, rr
->dnskey
.key
, rr
->dnskey
.key_size
, NULL
);
684 r
= dns_packet_append_uint16(p
, rr
->rrsig
.type_covered
, NULL
);
688 r
= dns_packet_append_uint8(p
, rr
->rrsig
.algorithm
, NULL
);
692 r
= dns_packet_append_uint8(p
, rr
->rrsig
.labels
, NULL
);
696 r
= dns_packet_append_uint32(p
, rr
->rrsig
.original_ttl
, NULL
);
700 r
= dns_packet_append_uint32(p
, rr
->rrsig
.expiration
, NULL
);
704 r
= dns_packet_append_uint32(p
, rr
->rrsig
.inception
, NULL
);
708 r
= dns_packet_append_uint16(p
, rr
->rrsig
.key_tag
, NULL
);
712 r
= dns_packet_append_name(p
, rr
->rrsig
.signer
, false, NULL
);
716 r
= dns_packet_append_blob(p
, rr
->rrsig
.signature
, rr
->rrsig
.signature_size
, NULL
);
719 case _DNS_TYPE_INVALID
: /* unparseable */
722 r
= dns_packet_append_blob(p
, rr
->generic
.data
, rr
->generic
.size
, NULL
);
728 /* Let's calculate the actual data size and update the field */
729 rdlength
= p
->size
- rdlength_offset
- sizeof(uint16_t);
730 if (rdlength
> 0xFFFF) {
736 p
->size
= rdlength_offset
;
737 r
= dns_packet_append_uint16(p
, rdlength
, NULL
);
748 dns_packet_truncate(p
, saved_size
);
753 int dns_packet_read(DnsPacket
*p
, size_t sz
, const void **ret
, size_t *start
) {
756 if (p
->rindex
+ sz
> p
->size
)
760 *ret
= (uint8_t*) DNS_PACKET_DATA(p
) + p
->rindex
;
769 void dns_packet_rewind(DnsPacket
*p
, size_t idx
) {
771 assert(idx
<= p
->size
);
772 assert(idx
>= DNS_PACKET_HEADER_SIZE
);
777 int dns_packet_read_blob(DnsPacket
*p
, void *d
, size_t sz
, size_t *start
) {
784 r
= dns_packet_read(p
, sz
, &q
, start
);
792 int dns_packet_read_uint8(DnsPacket
*p
, uint8_t *ret
, size_t *start
) {
798 r
= dns_packet_read(p
, sizeof(uint8_t), &d
, start
);
802 *ret
= ((uint8_t*) d
)[0];
806 int dns_packet_read_uint16(DnsPacket
*p
, uint16_t *ret
, size_t *start
) {
812 r
= dns_packet_read(p
, sizeof(uint16_t), &d
, start
);
816 *ret
= unaligned_read_be16(d
);
821 int dns_packet_read_uint32(DnsPacket
*p
, uint32_t *ret
, size_t *start
) {
827 r
= dns_packet_read(p
, sizeof(uint32_t), &d
, start
);
831 *ret
= unaligned_read_be32(d
);
836 int dns_packet_read_string(DnsPacket
*p
, char **ret
, size_t *start
) {
845 saved_rindex
= p
->rindex
;
847 r
= dns_packet_read_uint8(p
, &c
, NULL
);
851 r
= dns_packet_read(p
, c
, &d
, NULL
);
855 if (memchr(d
, 0, c
)) {
866 if (!utf8_is_valid(t
)) {
875 *start
= saved_rindex
;
880 dns_packet_rewind(p
, saved_rindex
);
884 int dns_packet_read_name(DnsPacket
*p
, char **_ret
,
885 bool allow_compression
, size_t *start
) {
886 size_t saved_rindex
, after_rindex
= 0, jump_barrier
;
887 _cleanup_free_
char *ret
= NULL
;
888 size_t n
= 0, allocated
= 0;
895 saved_rindex
= p
->rindex
;
896 jump_barrier
= p
->rindex
;
901 r
= dns_packet_read_uint8(p
, &c
, NULL
);
909 _cleanup_free_
char *t
= NULL
;
913 r
= dns_packet_read(p
, c
, (const void**) &label
, NULL
);
917 r
= dns_label_escape(label
, c
, &t
);
921 if (!GREEDY_REALLOC(ret
, allocated
, n
+ !first
+ strlen(t
) + 1)) {
931 memcpy(ret
+ n
, t
, r
);
934 } else if (allow_compression
&& (c
& 0xc0) == 0xc0) {
938 r
= dns_packet_read_uint8(p
, &d
, NULL
);
942 ptr
= (uint16_t) (c
& ~0xc0) << 8 | (uint16_t) d
;
943 if (ptr
< DNS_PACKET_HEADER_SIZE
|| ptr
>= jump_barrier
) {
948 if (after_rindex
== 0)
949 after_rindex
= p
->rindex
;
951 /* Jumps are limited to a "prior occurrence" (RFC-1035 4.1.4) */
960 if (!GREEDY_REALLOC(ret
, allocated
, n
+ 1)) {
967 if (after_rindex
!= 0)
968 p
->rindex
= after_rindex
;
974 *start
= saved_rindex
;
979 dns_packet_rewind(p
, saved_rindex
);
983 int dns_packet_read_key(DnsPacket
*p
, DnsResourceKey
**ret
, size_t *start
) {
984 _cleanup_free_
char *name
= NULL
;
985 uint16_t class, type
;
993 saved_rindex
= p
->rindex
;
995 r
= dns_packet_read_name(p
, &name
, true, NULL
);
999 r
= dns_packet_read_uint16(p
, &type
, NULL
);
1003 r
= dns_packet_read_uint16(p
, &class, NULL
);
1007 key
= dns_resource_key_new_consume(class, type
, name
);
1017 *start
= saved_rindex
;
1021 dns_packet_rewind(p
, saved_rindex
);
1025 static int dns_packet_read_public_key(DnsPacket
*p
, size_t length
,
1026 void **dp
, size_t *lengthp
,
1032 r
= dns_packet_read(p
, length
, &d
, NULL
);
1036 d2
= memdup(d
, length
);
1045 static bool loc_size_ok(uint8_t size
) {
1046 uint8_t m
= size
>> 4, e
= size
& 0xF;
1048 return m
<= 9 && e
<= 9 && (m
> 0 || e
== 0);
1051 static int dnskey_parse_flags(DnsResourceRecord
*rr
, uint16_t flags
) {
1054 if (flags
& ~(DNSKEY_FLAG_SEP
| DNSKEY_FLAG_ZONE_KEY
))
1057 rr
->dnskey
.zone_key_flag
= flags
& DNSKEY_FLAG_ZONE_KEY
;
1058 rr
->dnskey
.sep_flag
= flags
& DNSKEY_FLAG_SEP
;
1062 int dns_packet_read_rr(DnsPacket
*p
, DnsResourceRecord
**ret
, size_t *start
) {
1063 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*rr
= NULL
;
1064 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
1065 size_t saved_rindex
, offset
;
1073 saved_rindex
= p
->rindex
;
1075 r
= dns_packet_read_key(p
, &key
, NULL
);
1079 if (key
->class == DNS_CLASS_ANY
||
1080 key
->type
== DNS_TYPE_ANY
) {
1085 rr
= dns_resource_record_new(key
);
1091 r
= dns_packet_read_uint32(p
, &rr
->ttl
, NULL
);
1095 r
= dns_packet_read_uint16(p
, &rdlength
, NULL
);
1099 if (p
->rindex
+ rdlength
> p
->size
) {
1106 switch (rr
->key
->type
) {
1109 r
= dns_packet_read_uint16(p
, &rr
->srv
.priority
, NULL
);
1112 r
= dns_packet_read_uint16(p
, &rr
->srv
.weight
, NULL
);
1115 r
= dns_packet_read_uint16(p
, &rr
->srv
.port
, NULL
);
1118 r
= dns_packet_read_name(p
, &rr
->srv
.name
, true, NULL
);
1123 case DNS_TYPE_CNAME
:
1124 case DNS_TYPE_DNAME
:
1125 r
= dns_packet_read_name(p
, &rr
->ptr
.name
, true, NULL
);
1128 case DNS_TYPE_HINFO
:
1129 r
= dns_packet_read_string(p
, &rr
->hinfo
.cpu
, NULL
);
1133 r
= dns_packet_read_string(p
, &rr
->hinfo
.os
, NULL
);
1136 case DNS_TYPE_SPF
: /* exactly the same as TXT */
1138 if (rdlength
<= 0) {
1139 /* RFC 6763, section 6.1 suggests to treat
1140 * empty TXT RRs as equivalent to a TXT record
1141 * with a single empty string. */
1143 r
= strv_extend(&rr
->txt
.strings
, "");
1147 while (p
->rindex
< offset
+ rdlength
) {
1150 r
= dns_packet_read_string(p
, &s
, NULL
);
1154 r
= strv_consume(&rr
->txt
.strings
, s
);
1164 r
= dns_packet_read_blob(p
, &rr
->a
.in_addr
, sizeof(struct in_addr
), NULL
);
1168 r
= dns_packet_read_blob(p
, &rr
->aaaa
.in6_addr
, sizeof(struct in6_addr
), NULL
);
1172 r
= dns_packet_read_name(p
, &rr
->soa
.mname
, true, NULL
);
1176 r
= dns_packet_read_name(p
, &rr
->soa
.rname
, true, NULL
);
1180 r
= dns_packet_read_uint32(p
, &rr
->soa
.serial
, NULL
);
1184 r
= dns_packet_read_uint32(p
, &rr
->soa
.refresh
, NULL
);
1188 r
= dns_packet_read_uint32(p
, &rr
->soa
.retry
, NULL
);
1192 r
= dns_packet_read_uint32(p
, &rr
->soa
.expire
, NULL
);
1196 r
= dns_packet_read_uint32(p
, &rr
->soa
.minimum
, NULL
);
1200 r
= dns_packet_read_uint16(p
, &rr
->mx
.priority
, NULL
);
1204 r
= dns_packet_read_name(p
, &rr
->mx
.exchange
, true, NULL
);
1207 case DNS_TYPE_LOC
: {
1211 r
= dns_packet_read_uint8(p
, &t
, &pos
);
1216 rr
->loc
.version
= t
;
1218 r
= dns_packet_read_uint8(p
, &rr
->loc
.size
, NULL
);
1222 if (!loc_size_ok(rr
->loc
.size
)) {
1227 r
= dns_packet_read_uint8(p
, &rr
->loc
.horiz_pre
, NULL
);
1231 if (!loc_size_ok(rr
->loc
.horiz_pre
)) {
1236 r
= dns_packet_read_uint8(p
, &rr
->loc
.vert_pre
, NULL
);
1240 if (!loc_size_ok(rr
->loc
.vert_pre
)) {
1245 r
= dns_packet_read_uint32(p
, &rr
->loc
.latitude
, NULL
);
1249 r
= dns_packet_read_uint32(p
, &rr
->loc
.longitude
, NULL
);
1253 r
= dns_packet_read_uint32(p
, &rr
->loc
.altitude
, NULL
);
1259 dns_packet_rewind(p
, pos
);
1260 rr
->unparseable
= true;
1265 case DNS_TYPE_SSHFP
:
1266 r
= dns_packet_read_uint8(p
, &rr
->sshfp
.algorithm
, NULL
);
1270 r
= dns_packet_read_uint8(p
, &rr
->sshfp
.fptype
, NULL
);
1274 r
= dns_packet_read_public_key(p
, rdlength
- 2,
1275 &rr
->sshfp
.key
, &rr
->sshfp
.key_size
,
1279 case DNS_TYPE_DNSKEY
: {
1283 r
= dns_packet_read_uint16(p
, &flags
, NULL
);
1287 r
= dnskey_parse_flags(rr
, flags
);
1291 r
= dns_packet_read_uint8(p
, &proto
, NULL
);
1295 /* protocol is required to be always 3 */
1301 r
= dns_packet_read_uint8(p
, &rr
->dnskey
.algorithm
, NULL
);
1305 r
= dns_packet_read_public_key(p
, rdlength
- 4,
1306 &rr
->dnskey
.key
, &rr
->dnskey
.key_size
,
1311 case DNS_TYPE_RRSIG
:
1312 r
= dns_packet_read_uint16(p
, &rr
->rrsig
.type_covered
, NULL
);
1316 r
= dns_packet_read_uint8(p
, &rr
->rrsig
.algorithm
, NULL
);
1320 r
= dns_packet_read_uint8(p
, &rr
->rrsig
.labels
, NULL
);
1324 r
= dns_packet_read_uint32(p
, &rr
->rrsig
.original_ttl
, NULL
);
1328 r
= dns_packet_read_uint32(p
, &rr
->rrsig
.expiration
, NULL
);
1332 r
= dns_packet_read_uint32(p
, &rr
->rrsig
.inception
, NULL
);
1336 r
= dns_packet_read_uint16(p
, &rr
->rrsig
.key_tag
, NULL
);
1340 r
= dns_packet_read_name(p
, &rr
->rrsig
.signer
, false, NULL
);
1344 r
= dns_packet_read_public_key(p
, offset
+ rdlength
- p
->rindex
,
1345 &rr
->rrsig
.signature
, &rr
->rrsig
.signature_size
,
1351 r
= dns_packet_read(p
, rdlength
, &d
, NULL
);
1355 rr
->generic
.data
= memdup(d
, rdlength
);
1356 if (!rr
->generic
.data
) {
1361 rr
->generic
.size
= rdlength
;
1366 if (p
->rindex
!= offset
+ rdlength
) {
1375 *start
= saved_rindex
;
1379 dns_packet_rewind(p
, saved_rindex
);
1383 int dns_packet_extract(DnsPacket
*p
) {
1384 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
1385 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
1386 size_t saved_rindex
;
1393 saved_rindex
= p
->rindex
;
1394 dns_packet_rewind(p
, DNS_PACKET_HEADER_SIZE
);
1396 n
= DNS_PACKET_QDCOUNT(p
);
1398 question
= dns_question_new(n
);
1404 for (i
= 0; i
< n
; i
++) {
1405 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
1407 r
= dns_packet_read_key(p
, &key
, NULL
);
1411 r
= dns_question_add(question
, key
);
1417 n
= DNS_PACKET_RRCOUNT(p
);
1419 answer
= dns_answer_new(n
);
1425 for (i
= 0; i
< n
; i
++) {
1426 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*rr
= NULL
;
1428 r
= dns_packet_read_rr(p
, &rr
, NULL
);
1432 r
= dns_answer_add(answer
, rr
);
1438 p
->question
= question
;
1444 p
->extracted
= true;
1449 p
->rindex
= saved_rindex
;
1453 static const char* const dns_rcode_table
[_DNS_RCODE_MAX_DEFINED
] = {
1454 [DNS_RCODE_SUCCESS
] = "SUCCESS",
1455 [DNS_RCODE_FORMERR
] = "FORMERR",
1456 [DNS_RCODE_SERVFAIL
] = "SERVFAIL",
1457 [DNS_RCODE_NXDOMAIN
] = "NXDOMAIN",
1458 [DNS_RCODE_NOTIMP
] = "NOTIMP",
1459 [DNS_RCODE_REFUSED
] = "REFUSED",
1460 [DNS_RCODE_YXDOMAIN
] = "YXDOMAIN",
1461 [DNS_RCODE_YXRRSET
] = "YRRSET",
1462 [DNS_RCODE_NXRRSET
] = "NXRRSET",
1463 [DNS_RCODE_NOTAUTH
] = "NOTAUTH",
1464 [DNS_RCODE_NOTZONE
] = "NOTZONE",
1465 [DNS_RCODE_BADVERS
] = "BADVERS",
1466 [DNS_RCODE_BADKEY
] = "BADKEY",
1467 [DNS_RCODE_BADTIME
] = "BADTIME",
1468 [DNS_RCODE_BADMODE
] = "BADMODE",
1469 [DNS_RCODE_BADNAME
] = "BADNAME",
1470 [DNS_RCODE_BADALG
] = "BADALG",
1471 [DNS_RCODE_BADTRUNC
] = "BADTRUNC",
1473 DEFINE_STRING_TABLE_LOOKUP(dns_rcode
, int);
1475 static const char* const dns_protocol_table
[_DNS_PROTOCOL_MAX
] = {
1476 [DNS_PROTOCOL_DNS
] = "dns",
1477 [DNS_PROTOCOL_MDNS
] = "mdns",
1478 [DNS_PROTOCOL_LLMNR
] = "llmnr",
1480 DEFINE_STRING_TABLE_LOOKUP(dns_protocol
, DnsProtocol
);
1482 static const char* const dnssec_algorithm_table
[_DNSSEC_ALGORITHM_MAX_DEFINED
] = {
1483 [DNSSEC_ALGORITHM_RSAMD5
] = "RSAMD5",
1484 [DNSSEC_ALGORITHM_DH
] = "DH",
1485 [DNSSEC_ALGORITHM_DSA
] = "DSA",
1486 [DNSSEC_ALGORITHM_ECC
] = "ECC",
1487 [DNSSEC_ALGORITHM_RSASHA1
] = "RSASHA1",
1488 [DNSSEC_ALGORITHM_INDIRECT
] = "INDIRECT",
1489 [DNSSEC_ALGORITHM_PRIVATEDNS
] = "PRIVATEDNS",
1490 [DNSSEC_ALGORITHM_PRIVATEOID
] = "PRIVATEOID",
1492 DEFINE_STRING_TABLE_LOOKUP(dnssec_algorithm
, int);