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);
552 r = dns_packet_append_uint16(p, rr->mx.priority, NULL);
556 r = dns_packet_append_name(p, rr->mx.exchange, NULL);
564 r = dns_packet_append_blob(p, rr->generic.data, rr->generic.size, NULL);
570 /* Let's calculate the actual data size and update the field */
571 rdlength = p->size - rdlength_offset - sizeof(uint16_t);
572 if (rdlength > 0xFFFF) {
578 p->size = rdlength_offset;
579 r = dns_packet_append_uint16(p, rdlength, NULL);
590 dns_packet_truncate(p, saved_size);
595 int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) {
598 if (p->rindex + sz > p->size)
602 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->rindex;
611 void dns_packet_rewind(DnsPacket *p, size_t idx) {
613 assert(idx <= p->size);
614 assert(idx >= DNS_PACKET_HEADER_SIZE);
619 int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start) {
626 r = dns_packet_read(p, sz, &q, start);
634 int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) {
640 r = dns_packet_read(p, sizeof(uint8_t), &d, start);
644 *ret = ((uint8_t*) d)[0];
648 int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start) {
654 r = dns_packet_read(p, sizeof(uint16_t), &d, start);
658 *ret = (((uint16_t) ((uint8_t*) d)[0]) << 8) |
659 ((uint16_t) ((uint8_t*) d)[1]);
663 int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start) {
669 r = dns_packet_read(p, sizeof(uint32_t), &d, start);
673 *ret = (((uint32_t) ((uint8_t*) d)[0]) << 24) |
674 (((uint32_t) ((uint8_t*) d)[1]) << 16) |
675 (((uint32_t) ((uint8_t*) d)[2]) << 8) |
676 ((uint32_t) ((uint8_t*) d)[3]);
681 int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start) {
690 saved_rindex = p->rindex;
692 r = dns_packet_read_uint8(p, &c, NULL);
696 r = dns_packet_read(p, c, &d, NULL);
700 if (memchr(d, 0, c)) {
711 if (!utf8_is_valid(t)) {
720 *start = saved_rindex;
725 dns_packet_rewind(p, saved_rindex);
729 int dns_packet_read_name(DnsPacket *p, char **_ret, size_t *start) {
730 size_t saved_rindex, after_rindex = 0;
731 _cleanup_free_ char *ret = NULL;
732 size_t n = 0, allocated = 0;
739 saved_rindex = p->rindex;
744 r = dns_packet_read_uint8(p, &c, NULL);
752 _cleanup_free_ char *t = NULL;
756 r = dns_packet_read(p, c, (const void**) &label, NULL);
760 r = dns_label_escape(label, c, &t);
764 if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1)) {
774 memcpy(ret + n, t, c);
777 } else if ((c & 0xc0) == 0xc0) {
781 r = dns_packet_read_uint8(p, &d, NULL);
785 ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
786 if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= saved_rindex) {
791 if (after_rindex == 0)
792 after_rindex = p->rindex;
799 if (!GREEDY_REALLOC(ret, allocated, n + 1)) {
806 if (after_rindex != 0)
807 p->rindex= after_rindex;
813 *start = saved_rindex;
818 dns_packet_rewind(p, saved_rindex);
822 int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) {
823 _cleanup_free_ char *name = NULL;
824 uint16_t class, type;
832 saved_rindex = p->rindex;
834 r = dns_packet_read_name(p, &name, NULL);
838 r = dns_packet_read_uint16(p, &type, NULL);
842 r = dns_packet_read_uint16(p, &class, NULL);
846 key = dns_resource_key_new_consume(class, type, name);
856 *start = saved_rindex;
860 dns_packet_rewind(p, saved_rindex);
864 int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
865 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
866 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
867 size_t saved_rindex, offset;
875 saved_rindex = p->rindex;
877 r = dns_packet_read_key(p, &key, NULL);
881 if (key->class == DNS_CLASS_ANY ||
882 key->type == DNS_TYPE_ANY) {
887 rr = dns_resource_record_new(key);
893 r = dns_packet_read_uint32(p, &rr->ttl, NULL);
897 r = dns_packet_read_uint16(p, &rdlength, NULL);
901 if (p->rindex + rdlength > p->size) {
908 switch (rr->key->type) {
913 r = dns_packet_read_name(p, &rr->ptr.name, NULL);
917 r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL);
921 r = dns_packet_read_string(p, &rr->hinfo.os, NULL);
925 r = dns_packet_read_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
929 r = dns_packet_read_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
933 r = dns_packet_read_name(p, &rr->soa.mname, NULL);
937 r = dns_packet_read_name(p, &rr->soa.rname, NULL);
941 r = dns_packet_read_uint32(p, &rr->soa.serial, NULL);
945 r = dns_packet_read_uint32(p, &rr->soa.refresh, NULL);
949 r = dns_packet_read_uint32(p, &rr->soa.retry, NULL);
953 r = dns_packet_read_uint32(p, &rr->soa.expire, NULL);
957 r = dns_packet_read_uint32(p, &rr->soa.minimum, NULL);
961 r = dns_packet_read_uint16(p, &rr->mx.priority, NULL);
965 r = dns_packet_read_name(p, &rr->mx.exchange, NULL);
973 r = dns_packet_read(p, rdlength, &d, NULL);
977 rr->generic.data = memdup(d, rdlength);
978 if (!rr->generic.data) {
983 rr->generic.size = rdlength;
988 if (p->rindex != offset + rdlength) {
997 *start = saved_rindex;
1001 dns_packet_rewind(p, saved_rindex);
1005 int dns_packet_extract(DnsPacket *p) {
1006 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
1007 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
1008 size_t saved_rindex;
1012 saved_rindex = p->rindex;
1013 dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
1015 n = DNS_PACKET_QDCOUNT(p);
1017 question = dns_question_new(n);
1023 for (i = 0; i < n; i++) {
1024 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
1026 r = dns_packet_read_key(p, &key, NULL);
1030 r = dns_question_add(question, key);
1036 n = DNS_PACKET_RRCOUNT(p);
1038 answer = dns_answer_new(n);
1044 for (i = 0; i < n; i++) {
1045 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
1047 r = dns_packet_read_rr(p, &rr, NULL);
1051 r = dns_answer_add(answer, rr);
1057 p->question = question;
1066 p->rindex = saved_rindex;
1070 static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
1071 [DNS_RCODE_SUCCESS] = "SUCCESS",
1072 [DNS_RCODE_FORMERR] = "FORMERR",
1073 [DNS_RCODE_SERVFAIL] = "SERVFAIL",
1074 [DNS_RCODE_NXDOMAIN] = "NXDOMAIN",
1075 [DNS_RCODE_NOTIMP] = "NOTIMP",
1076 [DNS_RCODE_REFUSED] = "REFUSED",
1077 [DNS_RCODE_YXDOMAIN] = "YXDOMAIN",
1078 [DNS_RCODE_YXRRSET] = "YRRSET",
1079 [DNS_RCODE_NXRRSET] = "NXRRSET",
1080 [DNS_RCODE_NOTAUTH] = "NOTAUTH",
1081 [DNS_RCODE_NOTZONE] = "NOTZONE",
1082 [DNS_RCODE_BADVERS] = "BADVERS",
1083 [DNS_RCODE_BADKEY] = "BADKEY",
1084 [DNS_RCODE_BADTIME] = "BADTIME",
1085 [DNS_RCODE_BADMODE] = "BADMODE",
1086 [DNS_RCODE_BADNAME] = "BADNAME",
1087 [DNS_RCODE_BADALG] = "BADALG",
1088 [DNS_RCODE_BADTRUNC] = "BADTRUNC",
1090 DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int);
1092 static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = {
1093 [DNS_PROTOCOL_DNS] = "dns",
1094 [DNS_PROTOCOL_MDNS] = "mdns",
1095 [DNS_PROTOCOL_LLMNR] = "llmnr",
1097 DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);