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);
583 dns_packet_truncate(p, saved_size);
588 int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) {
591 if (p->rindex + sz > p->size)
595 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->rindex;
604 void dns_packet_rewind(DnsPacket *p, size_t idx) {
606 assert(idx <= p->size);
607 assert(idx >= DNS_PACKET_HEADER_SIZE);
612 int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start) {
619 r = dns_packet_read(p, sz, &q, start);
627 int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) {
633 r = dns_packet_read(p, sizeof(uint8_t), &d, start);
637 *ret = ((uint8_t*) d)[0];
641 int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start) {
647 r = dns_packet_read(p, sizeof(uint16_t), &d, start);
651 *ret = (((uint16_t) ((uint8_t*) d)[0]) << 8) |
652 ((uint16_t) ((uint8_t*) d)[1]);
656 int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start) {
662 r = dns_packet_read(p, sizeof(uint32_t), &d, start);
666 *ret = (((uint32_t) ((uint8_t*) d)[0]) << 24) |
667 (((uint32_t) ((uint8_t*) d)[1]) << 16) |
668 (((uint32_t) ((uint8_t*) d)[2]) << 8) |
669 ((uint32_t) ((uint8_t*) d)[3]);
674 int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start) {
683 saved_rindex = p->rindex;
685 r = dns_packet_read_uint8(p, &c, NULL);
689 r = dns_packet_read(p, c, &d, NULL);
693 if (memchr(d, 0, c)) {
704 if (!utf8_is_valid(t)) {
713 *start = saved_rindex;
718 dns_packet_rewind(p, saved_rindex);
722 int dns_packet_read_name(DnsPacket *p, char **_ret, size_t *start) {
723 size_t saved_rindex, after_rindex = 0;
724 _cleanup_free_ char *ret = NULL;
725 size_t n = 0, allocated = 0;
732 saved_rindex = p->rindex;
737 r = dns_packet_read_uint8(p, &c, NULL);
745 _cleanup_free_ char *t = NULL;
749 r = dns_packet_read(p, c, (const void**) &label, NULL);
753 r = dns_label_escape(label, c, &t);
757 if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1)) {
767 memcpy(ret + n, t, c);
770 } else if ((c & 0xc0) == 0xc0) {
774 r = dns_packet_read_uint8(p, &d, NULL);
778 ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
779 if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= saved_rindex) {
784 if (after_rindex == 0)
785 after_rindex = p->rindex;
792 if (!GREEDY_REALLOC(ret, allocated, n + 1)) {
799 if (after_rindex != 0)
800 p->rindex= after_rindex;
806 *start = saved_rindex;
811 dns_packet_rewind(p, saved_rindex);
815 int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) {
816 _cleanup_free_ char *name = NULL;
817 uint16_t class, type;
825 saved_rindex = p->rindex;
827 r = dns_packet_read_name(p, &name, NULL);
831 r = dns_packet_read_uint16(p, &type, NULL);
835 r = dns_packet_read_uint16(p, &class, NULL);
839 key = dns_resource_key_new_consume(class, type, name);
849 *start = saved_rindex;
853 dns_packet_rewind(p, saved_rindex);
857 int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
858 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
859 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
860 size_t saved_rindex, offset;
868 saved_rindex = p->rindex;
870 r = dns_packet_read_key(p, &key, NULL);
874 if (key->class == DNS_CLASS_ANY ||
875 key->type == DNS_TYPE_ANY) {
880 rr = dns_resource_record_new(key);
886 r = dns_packet_read_uint32(p, &rr->ttl, NULL);
890 r = dns_packet_read_uint16(p, &rdlength, NULL);
894 if (p->rindex + rdlength > p->size) {
901 switch (rr->key->type) {
906 r = dns_packet_read_name(p, &rr->ptr.name, NULL);
910 r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL);
914 r = dns_packet_read_string(p, &rr->hinfo.os, NULL);
918 r = dns_packet_read_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
922 r = dns_packet_read_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
926 r = dns_packet_read_name(p, &rr->soa.mname, NULL);
930 r = dns_packet_read_name(p, &rr->soa.rname, NULL);
934 r = dns_packet_read_uint32(p, &rr->soa.serial, NULL);
938 r = dns_packet_read_uint32(p, &rr->soa.refresh, NULL);
942 r = dns_packet_read_uint32(p, &rr->soa.retry, NULL);
946 r = dns_packet_read_uint32(p, &rr->soa.expire, NULL);
950 r = dns_packet_read_uint32(p, &rr->soa.minimum, NULL);
959 r = dns_packet_read(p, rdlength, &d, NULL);
963 rr->generic.data = memdup(d, rdlength);
964 if (!rr->generic.data) {
969 rr->generic.size = rdlength;
974 if (p->rindex != offset + rdlength) {
983 *start = saved_rindex;
987 dns_packet_rewind(p, saved_rindex);
991 int dns_packet_extract(DnsPacket *p) {
992 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
993 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
998 saved_rindex = p->rindex;
999 dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
1001 n = DNS_PACKET_QDCOUNT(p);
1003 question = dns_question_new(n);
1009 for (i = 0; i < n; i++) {
1010 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
1012 r = dns_packet_read_key(p, &key, NULL);
1016 r = dns_question_add(question, key);
1022 n = DNS_PACKET_RRCOUNT(p);
1024 answer = dns_answer_new(n);
1030 for (i = 0; i < n; i++) {
1031 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
1033 r = dns_packet_read_rr(p, &rr, NULL);
1037 r = dns_answer_add(answer, rr);
1043 p->question = question;
1052 p->rindex = saved_rindex;
1056 static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
1057 [DNS_RCODE_SUCCESS] = "SUCCESS",
1058 [DNS_RCODE_FORMERR] = "FORMERR",
1059 [DNS_RCODE_SERVFAIL] = "SERVFAIL",
1060 [DNS_RCODE_NXDOMAIN] = "NXDOMAIN",
1061 [DNS_RCODE_NOTIMP] = "NOTIMP",
1062 [DNS_RCODE_REFUSED] = "REFUSED",
1063 [DNS_RCODE_YXDOMAIN] = "YXDOMAIN",
1064 [DNS_RCODE_YXRRSET] = "YRRSET",
1065 [DNS_RCODE_NXRRSET] = "NXRRSET",
1066 [DNS_RCODE_NOTAUTH] = "NOTAUTH",
1067 [DNS_RCODE_NOTZONE] = "NOTZONE",
1068 [DNS_RCODE_BADVERS] = "BADVERS",
1069 [DNS_RCODE_BADKEY] = "BADKEY",
1070 [DNS_RCODE_BADTIME] = "BADTIME",
1071 [DNS_RCODE_BADMODE] = "BADMODE",
1072 [DNS_RCODE_BADNAME] = "BADNAME",
1073 [DNS_RCODE_BADALG] = "BADALG",
1074 [DNS_RCODE_BADTRUNC] = "BADTRUNC",
1076 DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int);
1078 static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = {
1079 [DNS_PROTOCOL_DNS] = "dns",
1080 [DNS_PROTOCOL_MDNS] = "mdns",
1081 [DNS_PROTOCOL_LLMNR] = "llmnr",
1083 DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);