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/>.
24 #include "resolved-dns-domain.h"
25 #include "resolved-dns-packet.h"
27 int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
34 a = DNS_PACKET_SIZE_START;
38 if (a < DNS_PACKET_HEADER_SIZE)
39 a = DNS_PACKET_HEADER_SIZE;
41 /* round up to next page size */
42 a = PAGE_ALIGN(ALIGN(sizeof(DnsPacket)) + a) - ALIGN(sizeof(DnsPacket));
44 /* make sure we never allocate more than useful */
45 if (a > DNS_PACKET_SIZE_MAX)
46 a = DNS_PACKET_SIZE_MAX;
48 p = malloc0(ALIGN(sizeof(DnsPacket)) + a);
52 p->size = p->rindex = DNS_PACKET_HEADER_SIZE;
54 p->protocol = protocol;
62 int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
69 r = dns_packet_new(&p, protocol, mtu);
73 h = DNS_PACKET_HEADER(p);
75 if (protocol == DNS_PROTOCOL_LLMNR)
76 h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
86 h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
90 1 /* rd (ask for recursion) */,
100 DnsPacket *dns_packet_ref(DnsPacket *p) {
105 assert(p->n_ref > 0);
110 static void dns_packet_free(DnsPacket *p) {
115 dns_question_unref(p->question);
116 dns_answer_unref(p->answer);
118 while ((s = hashmap_steal_first_key(p->names)))
120 hashmap_free(p->names);
126 DnsPacket *dns_packet_unref(DnsPacket *p) {
130 assert(p->n_ref > 0);
140 int dns_packet_validate(DnsPacket *p) {
143 if (p->size < DNS_PACKET_HEADER_SIZE)
146 if (p->size > DNS_PACKET_SIZE_MAX)
152 int dns_packet_validate_reply(DnsPacket *p) {
157 r = dns_packet_validate(p);
161 if (DNS_PACKET_QR(p) != 1)
164 if (DNS_PACKET_OPCODE(p) != 0)
167 /* RFC 4795, Section 2.1.1. says to discard all replies with QDCOUNT != 1 */
168 if (p->protocol == DNS_PROTOCOL_LLMNR &&
169 DNS_PACKET_QDCOUNT(p) != 1)
175 int dns_packet_validate_query(DnsPacket *p) {
180 r = dns_packet_validate(p);
184 if (DNS_PACKET_QR(p) != 0)
187 if (DNS_PACKET_OPCODE(p) != 0)
190 if (DNS_PACKET_TC(p))
193 /* RFC 4795, Section 2.1.1. says to discard all queries with QDCOUNT != 1 */
194 if (p->protocol == DNS_PROTOCOL_LLMNR &&
195 DNS_PACKET_QDCOUNT(p) != 1)
198 /* RFC 4795, Section 2.1.1. says to discard all queries with ANCOUNT != 0 */
199 if (DNS_PACKET_ANCOUNT(p) > 0)
202 /* RFC 4795, Section 2.1.1. says to discard all queries with NSCOUNT != 0 */
203 if (DNS_PACKET_NSCOUNT(p) > 0)
209 static int dns_packet_extend(DnsPacket *p, size_t add, void **ret, size_t *start) {
212 if (p->size + add > p->allocated) {
215 a = PAGE_ALIGN((p->size + add) * 2);
216 if (a > DNS_PACKET_SIZE_MAX)
217 a = DNS_PACKET_SIZE_MAX;
219 if (p->size + add > a)
225 d = realloc(p->_data, a);
231 p->_data = malloc(a);
235 memcpy(p->_data, (uint8_t*) p + ALIGN(sizeof(DnsPacket)), p->size);
236 memzero((uint8_t*) p->_data + p->size, a - p->size);
246 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->size;
252 static void dns_packet_truncate(DnsPacket *p, size_t sz) {
262 HASHMAP_FOREACH_KEY(s, n, p->names, i) {
264 if (PTR_TO_SIZE(n) < sz)
267 hashmap_remove(p->names, s);
274 int dns_packet_append_blob(DnsPacket *p, const void *d, size_t l, size_t *start) {
280 r = dns_packet_extend(p, l, &q, start);
288 int dns_packet_append_uint8(DnsPacket *p, uint8_t v, size_t *start) {
294 r = dns_packet_extend(p, sizeof(uint8_t), &d, start);
298 ((uint8_t*) d)[0] = v;
303 int dns_packet_append_uint16(DnsPacket *p, uint16_t v, size_t *start) {
309 r = dns_packet_extend(p, sizeof(uint16_t), &d, start);
313 ((uint8_t*) d)[0] = (uint8_t) (v >> 8);
314 ((uint8_t*) d)[1] = (uint8_t) v;
319 int dns_packet_append_uint32(DnsPacket *p, uint32_t v, size_t *start) {
325 r = dns_packet_extend(p, sizeof(uint32_t), &d, start);
329 ((uint8_t*) d)[0] = (uint8_t) (v >> 24);
330 ((uint8_t*) d)[1] = (uint8_t) (v >> 16);
331 ((uint8_t*) d)[2] = (uint8_t) (v >> 8);
332 ((uint8_t*) d)[3] = (uint8_t) v;
337 int dns_packet_append_string(DnsPacket *p, const char *s, size_t *start) {
349 r = dns_packet_extend(p, 1 + l, &d, start);
353 ((uint8_t*) d)[0] = (uint8_t) l;
354 memcpy(((uint8_t*) d) + 1, s, l);
359 int dns_packet_append_label(DnsPacket *p, const char *d, size_t l, size_t *start) {
366 if (l > DNS_LABEL_MAX)
369 r = dns_packet_extend(p, 1 + l, &w, start);
373 ((uint8_t*) w)[0] = (uint8_t) l;
374 memcpy(((uint8_t*) w) + 1, d, l);
379 int dns_packet_append_name(DnsPacket *p, const char *name, size_t *start) {
386 saved_size = p->size;
389 _cleanup_free_ char *s = NULL;
390 char label[DNS_LABEL_MAX];
393 n = PTR_TO_SIZE(hashmap_get(p->names, name));
398 r = dns_packet_append_uint16(p, 0xC000 | n, NULL);
412 r = dns_label_unescape(&name, label, sizeof(label));
416 r = dns_packet_append_label(p, label, r, &n);
420 r = hashmap_ensure_allocated(&p->names, dns_name_hash_func, dns_name_compare_func);
424 r = hashmap_put(p->names, s, SIZE_TO_PTR(n));
431 r = dns_packet_append_uint8(p, 0, NULL);
442 dns_packet_truncate(p, saved_size);
446 int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *k, size_t *start) {
453 saved_size = p->size;
455 r = dns_packet_append_name(p, DNS_RESOURCE_KEY_NAME(k), NULL);
459 r = dns_packet_append_uint16(p, k->type, NULL);
463 r = dns_packet_append_uint16(p, k->class, NULL);
473 dns_packet_truncate(p, saved_size);
477 int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start) {
478 size_t saved_size, rdlength_offset, end, rdlength;
484 saved_size = p->size;
486 r = dns_packet_append_key(p, rr->key, NULL);
490 r = dns_packet_append_uint32(p, rr->ttl, NULL);
494 /* Initially we write 0 here */
495 r = dns_packet_append_uint16(p, 0, &rdlength_offset);
499 switch (rr->key->type) {
504 r = dns_packet_append_name(p, rr->ptr.name, NULL);
508 r = dns_packet_append_string(p, rr->hinfo.cpu, NULL);
512 r = dns_packet_append_string(p, rr->hinfo.os, NULL);
516 r = dns_packet_append_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
520 r = dns_packet_append_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
524 r = dns_packet_append_name(p, rr->soa.mname, NULL);
528 r = dns_packet_append_name(p, rr->soa.rname, NULL);
532 r = dns_packet_append_uint32(p, rr->soa.serial, NULL);
536 r = dns_packet_append_uint32(p, rr->soa.refresh, NULL);
540 r = dns_packet_append_uint32(p, rr->soa.retry, NULL);
544 r = dns_packet_append_uint32(p, rr->soa.expire, NULL);
548 r = dns_packet_append_uint32(p, rr->soa.minimum, NULL);
557 r = dns_packet_append_blob(p, rr->generic.data, rr->generic.size, NULL);
563 /* Let's calculate the actual data size and update the field */
564 rdlength = p->size - rdlength_offset - sizeof(uint16_t);
565 if (rdlength > 0xFFFF) {
571 p->size = rdlength_offset;
572 r = dns_packet_append_uint16(p, rdlength, NULL);
580 dns_packet_truncate(p, saved_size);
585 int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) {
588 if (p->rindex + sz > p->size)
592 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->rindex;
601 void dns_packet_rewind(DnsPacket *p, size_t idx) {
603 assert(idx <= p->size);
604 assert(idx >= DNS_PACKET_HEADER_SIZE);
609 int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start) {
616 r = dns_packet_read(p, sz, &q, start);
624 int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) {
630 r = dns_packet_read(p, sizeof(uint8_t), &d, start);
634 *ret = ((uint8_t*) d)[0];
638 int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start) {
644 r = dns_packet_read(p, sizeof(uint16_t), &d, start);
648 *ret = (((uint16_t) ((uint8_t*) d)[0]) << 8) |
649 ((uint16_t) ((uint8_t*) d)[1]);
653 int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start) {
659 r = dns_packet_read(p, sizeof(uint32_t), &d, start);
663 *ret = (((uint32_t) ((uint8_t*) d)[0]) << 24) |
664 (((uint32_t) ((uint8_t*) d)[1]) << 16) |
665 (((uint32_t) ((uint8_t*) d)[2]) << 8) |
666 ((uint32_t) ((uint8_t*) d)[3]);
671 int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start) {
680 saved_rindex = p->rindex;
682 r = dns_packet_read_uint8(p, &c, NULL);
686 r = dns_packet_read(p, c, &d, NULL);
690 if (memchr(d, 0, c)) {
701 if (!utf8_is_valid(t)) {
710 *start = saved_rindex;
715 dns_packet_rewind(p, saved_rindex);
719 int dns_packet_read_name(DnsPacket *p, char **_ret, size_t *start) {
720 size_t saved_rindex, after_rindex = 0;
721 _cleanup_free_ char *ret = NULL;
722 size_t n = 0, allocated = 0;
729 saved_rindex = p->rindex;
734 r = dns_packet_read_uint8(p, &c, NULL);
742 _cleanup_free_ char *t = NULL;
746 r = dns_packet_read(p, c, (const void**) &label, NULL);
750 r = dns_label_escape(label, c, &t);
754 if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1)) {
764 memcpy(ret + n, t, c);
767 } else if ((c & 0xc0) == 0xc0) {
771 r = dns_packet_read_uint8(p, &d, NULL);
775 ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
776 if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= saved_rindex) {
781 if (after_rindex == 0)
782 after_rindex = p->rindex;
789 if (!GREEDY_REALLOC(ret, allocated, n + 1)) {
796 if (after_rindex != 0)
797 p->rindex= after_rindex;
803 *start = saved_rindex;
808 dns_packet_rewind(p, saved_rindex);
812 int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) {
813 _cleanup_free_ char *name = NULL;
814 uint16_t class, type;
822 saved_rindex = p->rindex;
824 r = dns_packet_read_name(p, &name, NULL);
828 r = dns_packet_read_uint16(p, &type, NULL);
832 r = dns_packet_read_uint16(p, &class, NULL);
836 key = dns_resource_key_new_consume(class, type, name);
846 *start = saved_rindex;
850 dns_packet_rewind(p, saved_rindex);
854 int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
855 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
856 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
857 size_t saved_rindex, offset;
865 saved_rindex = p->rindex;
867 r = dns_packet_read_key(p, &key, NULL);
871 if (key->class == DNS_CLASS_ANY ||
872 key->type == DNS_TYPE_ANY) {
877 rr = dns_resource_record_new(key);
883 r = dns_packet_read_uint32(p, &rr->ttl, NULL);
887 r = dns_packet_read_uint16(p, &rdlength, NULL);
891 if (p->rindex + rdlength > p->size) {
898 switch (rr->key->type) {
903 r = dns_packet_read_name(p, &rr->ptr.name, NULL);
907 r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL);
911 r = dns_packet_read_string(p, &rr->hinfo.os, NULL);
915 r = dns_packet_read_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
919 r = dns_packet_read_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
923 r = dns_packet_read_name(p, &rr->soa.mname, NULL);
927 r = dns_packet_read_name(p, &rr->soa.rname, NULL);
931 r = dns_packet_read_uint32(p, &rr->soa.serial, NULL);
935 r = dns_packet_read_uint32(p, &rr->soa.refresh, NULL);
939 r = dns_packet_read_uint32(p, &rr->soa.retry, NULL);
943 r = dns_packet_read_uint32(p, &rr->soa.expire, NULL);
947 r = dns_packet_read_uint32(p, &rr->soa.minimum, NULL);
956 r = dns_packet_read(p, rdlength, &d, NULL);
960 rr->generic.data = memdup(d, rdlength);
961 if (!rr->generic.data) {
966 rr->generic.size = rdlength;
971 if (p->rindex != offset + rdlength) {
980 *start = saved_rindex;
984 dns_packet_rewind(p, saved_rindex);
988 int dns_packet_extract(DnsPacket *p) {
989 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
990 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
995 saved_rindex = p->rindex;
996 dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
998 n = DNS_PACKET_QDCOUNT(p);
1000 question = dns_question_new(n);
1006 for (i = 0; i < n; i++) {
1007 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
1009 r = dns_packet_read_key(p, &key, NULL);
1013 r = dns_question_add(question, key);
1019 n = DNS_PACKET_RRCOUNT(p);
1021 answer = dns_answer_new(n);
1027 for (i = 0; i < n; i++) {
1028 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
1030 r = dns_packet_read_rr(p, &rr, NULL);
1034 r = dns_answer_add(answer, rr);
1040 p->question = question;
1049 p->rindex = saved_rindex;
1053 static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
1054 [DNS_RCODE_SUCCESS] = "SUCCESS",
1055 [DNS_RCODE_FORMERR] = "FORMERR",
1056 [DNS_RCODE_SERVFAIL] = "SERVFAIL",
1057 [DNS_RCODE_NXDOMAIN] = "NXDOMAIN",
1058 [DNS_RCODE_NOTIMP] = "NOTIMP",
1059 [DNS_RCODE_REFUSED] = "REFUSED",
1060 [DNS_RCODE_YXDOMAIN] = "YXDOMAIN",
1061 [DNS_RCODE_YXRRSET] = "YRRSET",
1062 [DNS_RCODE_NXRRSET] = "NXRRSET",
1063 [DNS_RCODE_NOTAUTH] = "NOTAUTH",
1064 [DNS_RCODE_NOTZONE] = "NOTZONE",
1065 [DNS_RCODE_BADVERS] = "BADVERS",
1066 [DNS_RCODE_BADKEY] = "BADKEY",
1067 [DNS_RCODE_BADTIME] = "BADTIME",
1068 [DNS_RCODE_BADMODE] = "BADMODE",
1069 [DNS_RCODE_BADNAME] = "BADNAME",
1070 [DNS_RCODE_BADALG] = "BADALG",
1071 [DNS_RCODE_BADTRUNC] = "BADTRUNC",
1073 DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int);
1075 static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = {
1076 [DNS_PROTOCOL_DNS] = "dns",
1077 [DNS_PROTOCOL_MDNS] = "mdns",
1078 [DNS_PROTOCOL_LLMNR] = "llmnr",
1080 DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);