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_DNS)
76 h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0, 0, 0, 0, 1, 0, 0, 0, 0)); /* ask for recursion */
78 h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0, 0, 0, 0, 0, 0, 0, 0, 0));
84 DnsPacket *dns_packet_ref(DnsPacket *p) {
94 static void dns_packet_free(DnsPacket *p) {
99 dns_question_unref(p->question);
100 dns_answer_unref(p->answer);
102 while ((s = hashmap_steal_first_key(p->names)))
104 hashmap_free(p->names);
110 DnsPacket *dns_packet_unref(DnsPacket *p) {
114 assert(p->n_ref > 0);
124 int dns_packet_validate(DnsPacket *p) {
127 if (p->size < DNS_PACKET_HEADER_SIZE)
130 if (p->size > DNS_PACKET_SIZE_MAX)
136 int dns_packet_validate_reply(DnsPacket *p) {
141 r = dns_packet_validate(p);
145 if (DNS_PACKET_QR(p) != 1)
148 if (DNS_PACKET_OPCODE(p) != 0)
154 int dns_packet_validate_query(DnsPacket *p) {
159 r = dns_packet_validate(p);
163 if (DNS_PACKET_QR(p) != 0)
166 if (DNS_PACKET_OPCODE(p) != 0)
169 if (DNS_PACKET_TC(p))
172 if (p->protocol == DNS_PROTOCOL_LLMNR &&
173 DNS_PACKET_QDCOUNT(p) != 1)
176 if (DNS_PACKET_ANCOUNT(p) > 0)
179 if (DNS_PACKET_NSCOUNT(p) > 0)
185 static int dns_packet_extend(DnsPacket *p, size_t add, void **ret, size_t *start) {
188 if (p->size + add > p->allocated) {
191 a = PAGE_ALIGN((p->size + add) * 2);
192 if (a > DNS_PACKET_SIZE_MAX)
193 a = DNS_PACKET_SIZE_MAX;
195 if (p->size + add > a)
201 d = realloc(p->_data, a);
207 p->_data = malloc(a);
211 memcpy(p->_data, (uint8_t*) p + ALIGN(sizeof(DnsPacket)), p->size);
212 memzero((uint8_t*) p->_data + p->size, a - p->size);
222 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->size;
228 static void dns_packet_truncate(DnsPacket *p, size_t sz) {
238 HASHMAP_FOREACH_KEY(s, n, p->names, i) {
240 if (PTR_TO_SIZE(n) < sz)
243 hashmap_remove(p->names, s);
250 int dns_packet_append_blob(DnsPacket *p, const void *d, size_t l, size_t *start) {
256 r = dns_packet_extend(p, l, &q, start);
264 int dns_packet_append_uint8(DnsPacket *p, uint8_t v, size_t *start) {
270 r = dns_packet_extend(p, sizeof(uint8_t), &d, start);
274 ((uint8_t*) d)[0] = v;
279 int dns_packet_append_uint16(DnsPacket *p, uint16_t v, size_t *start) {
285 r = dns_packet_extend(p, sizeof(uint16_t), &d, start);
289 ((uint8_t*) d)[0] = (uint8_t) (v >> 8);
290 ((uint8_t*) d)[1] = (uint8_t) v;
295 int dns_packet_append_uint32(DnsPacket *p, uint32_t v, size_t *start) {
301 r = dns_packet_extend(p, sizeof(uint32_t), &d, start);
305 ((uint8_t*) d)[0] = (uint8_t) (v >> 24);
306 ((uint8_t*) d)[1] = (uint8_t) (v >> 16);
307 ((uint8_t*) d)[2] = (uint8_t) (v >> 8);
308 ((uint8_t*) d)[3] = (uint8_t) v;
313 int dns_packet_append_string(DnsPacket *p, const char *s, size_t *start) {
325 r = dns_packet_extend(p, 1 + l, &d, start);
329 ((uint8_t*) d)[0] = (uint8_t) l;
330 memcpy(((uint8_t*) d) + 1, s, l);
335 int dns_packet_append_label(DnsPacket *p, const char *d, size_t l, size_t *start) {
342 if (l > DNS_LABEL_MAX)
345 r = dns_packet_extend(p, 1 + l, &w, start);
349 ((uint8_t*) w)[0] = (uint8_t) l;
350 memcpy(((uint8_t*) w) + 1, d, l);
355 int dns_packet_append_name(DnsPacket *p, const char *name, size_t *start) {
362 saved_size = p->size;
365 _cleanup_free_ char *s = NULL;
366 char label[DNS_LABEL_MAX];
369 n = PTR_TO_SIZE(hashmap_get(p->names, name));
374 r = dns_packet_append_uint16(p, 0xC000 | n, NULL);
388 r = dns_label_unescape(&name, label, sizeof(label));
392 r = dns_packet_append_label(p, label, r, &n);
396 r = hashmap_ensure_allocated(&p->names, dns_name_hash_func, dns_name_compare_func);
400 r = hashmap_put(p->names, s, SIZE_TO_PTR(n));
407 r = dns_packet_append_uint8(p, 0, NULL);
418 dns_packet_truncate(p, saved_size);
422 int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *k, size_t *start) {
429 saved_size = p->size;
431 r = dns_packet_append_name(p, DNS_RESOURCE_KEY_NAME(k), NULL);
435 r = dns_packet_append_uint16(p, k->type, NULL);
439 r = dns_packet_append_uint16(p, k->class, NULL);
449 dns_packet_truncate(p, saved_size);
453 int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start) {
454 size_t saved_size, rdlength_offset, end, rdlength;
460 saved_size = p->size;
462 r = dns_packet_append_key(p, rr->key, NULL);
466 r = dns_packet_append_uint32(p, rr->ttl, NULL);
470 /* Initially we write 0 here */
471 r = dns_packet_append_uint16(p, 0, &rdlength_offset);
475 switch (rr->key->type) {
480 r = dns_packet_append_name(p, rr->ptr.name, NULL);
484 r = dns_packet_append_string(p, rr->hinfo.cpu, NULL);
488 r = dns_packet_append_string(p, rr->hinfo.os, NULL);
492 r = dns_packet_append_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
496 r = dns_packet_append_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
500 r = dns_packet_append_name(p, rr->soa.mname, NULL);
504 r = dns_packet_append_name(p, rr->soa.rname, NULL);
508 r = dns_packet_append_uint32(p, rr->soa.serial, NULL);
512 r = dns_packet_append_uint32(p, rr->soa.refresh, NULL);
516 r = dns_packet_append_uint32(p, rr->soa.retry, NULL);
520 r = dns_packet_append_uint32(p, rr->soa.expire, NULL);
524 r = dns_packet_append_uint32(p, rr->soa.minimum, NULL);
533 r = dns_packet_append_blob(p, rr->generic.data, rr->generic.size, NULL);
539 /* Let's calculate the actual data size and update the field */
540 rdlength = p->size - rdlength_offset - sizeof(uint16_t);
541 if (rdlength > 0xFFFF) {
547 p->size = rdlength_offset;
548 r = dns_packet_append_uint16(p, rdlength, NULL);
556 dns_packet_truncate(p, saved_size);
561 int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) {
564 if (p->rindex + sz > p->size)
568 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->rindex;
577 void dns_packet_rewind(DnsPacket *p, size_t idx) {
579 assert(idx <= p->size);
580 assert(idx >= DNS_PACKET_HEADER_SIZE);
585 int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start) {
592 r = dns_packet_read(p, sz, &q, start);
600 int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) {
606 r = dns_packet_read(p, sizeof(uint8_t), &d, start);
610 *ret = ((uint8_t*) d)[0];
614 int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start) {
620 r = dns_packet_read(p, sizeof(uint16_t), &d, start);
624 *ret = (((uint16_t) ((uint8_t*) d)[0]) << 8) |
625 ((uint16_t) ((uint8_t*) d)[1]);
629 int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start) {
635 r = dns_packet_read(p, sizeof(uint32_t), &d, start);
639 *ret = (((uint32_t) ((uint8_t*) d)[0]) << 24) |
640 (((uint32_t) ((uint8_t*) d)[1]) << 16) |
641 (((uint32_t) ((uint8_t*) d)[2]) << 8) |
642 ((uint32_t) ((uint8_t*) d)[3]);
647 int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start) {
656 saved_rindex = p->rindex;
658 r = dns_packet_read_uint8(p, &c, NULL);
662 r = dns_packet_read(p, c, &d, NULL);
666 if (memchr(d, 0, c)) {
677 if (!utf8_is_valid(t)) {
686 *start = saved_rindex;
691 dns_packet_rewind(p, saved_rindex);
695 int dns_packet_read_name(DnsPacket *p, char **_ret, size_t *start) {
696 size_t saved_rindex, after_rindex = 0;
697 _cleanup_free_ char *ret = NULL;
698 size_t n = 0, allocated = 0;
705 saved_rindex = p->rindex;
710 r = dns_packet_read_uint8(p, &c, NULL);
718 _cleanup_free_ char *t = NULL;
722 r = dns_packet_read(p, c, (const void**) &label, NULL);
726 r = dns_label_escape(label, c, &t);
730 if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1)) {
740 memcpy(ret + n, t, c);
743 } else if ((c & 0xc0) == 0xc0) {
747 r = dns_packet_read_uint8(p, &d, NULL);
751 ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
752 if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= saved_rindex) {
757 if (after_rindex == 0)
758 after_rindex = p->rindex;
765 if (!GREEDY_REALLOC(ret, allocated, n + 1)) {
772 if (after_rindex != 0)
773 p->rindex= after_rindex;
779 *start = saved_rindex;
784 dns_packet_rewind(p, saved_rindex);
788 int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) {
789 _cleanup_free_ char *name = NULL;
790 uint16_t class, type;
798 saved_rindex = p->rindex;
800 r = dns_packet_read_name(p, &name, NULL);
804 r = dns_packet_read_uint16(p, &type, NULL);
808 r = dns_packet_read_uint16(p, &class, NULL);
812 key = dns_resource_key_new_consume(class, type, name);
822 *start = saved_rindex;
826 dns_packet_rewind(p, saved_rindex);
830 int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
831 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
832 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
833 size_t saved_rindex, offset;
841 saved_rindex = p->rindex;
843 r = dns_packet_read_key(p, &key, NULL);
847 rr = dns_resource_record_new(key);
853 r = dns_packet_read_uint32(p, &rr->ttl, NULL);
857 r = dns_packet_read_uint16(p, &rdlength, NULL);
861 if (p->rindex + rdlength > p->size) {
868 switch (rr->key->type) {
873 r = dns_packet_read_name(p, &rr->ptr.name, NULL);
877 r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL);
881 r = dns_packet_read_string(p, &rr->hinfo.os, NULL);
885 r = dns_packet_read_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
889 r = dns_packet_read_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
893 r = dns_packet_read_name(p, &rr->soa.mname, NULL);
897 r = dns_packet_read_name(p, &rr->soa.rname, NULL);
901 r = dns_packet_read_uint32(p, &rr->soa.serial, NULL);
905 r = dns_packet_read_uint32(p, &rr->soa.refresh, NULL);
909 r = dns_packet_read_uint32(p, &rr->soa.retry, NULL);
913 r = dns_packet_read_uint32(p, &rr->soa.expire, NULL);
917 r = dns_packet_read_uint32(p, &rr->soa.minimum, NULL);
926 r = dns_packet_read(p, rdlength, &d, NULL);
930 rr->generic.data = memdup(d, rdlength);
931 if (!rr->generic.data) {
936 rr->generic.size = rdlength;
941 if (p->rindex != offset + rdlength) {
950 *start = saved_rindex;
954 dns_packet_rewind(p, saved_rindex);
958 int dns_packet_extract(DnsPacket *p) {
959 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
960 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
965 saved_rindex = p->rindex;
966 dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
968 n = DNS_PACKET_QDCOUNT(p);
970 question = dns_question_new(n);
976 for (i = 0; i < n; i++) {
977 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
979 r = dns_packet_read_key(p, &key, NULL);
983 r = dns_question_add(question, key);
989 n = DNS_PACKET_RRCOUNT(p);
991 answer = dns_answer_new(n);
997 for (i = 0; i < n; i++) {
998 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
1000 r = dns_packet_read_rr(p, &rr, NULL);
1004 r = dns_answer_add(answer, rr);
1010 p->question = question;
1019 p->rindex = saved_rindex;
1023 static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
1024 [DNS_RCODE_SUCCESS] = "SUCCESS",
1025 [DNS_RCODE_FORMERR] = "FORMERR",
1026 [DNS_RCODE_SERVFAIL] = "SERVFAIL",
1027 [DNS_RCODE_NXDOMAIN] = "NXDOMAIN",
1028 [DNS_RCODE_NOTIMP] = "NOTIMP",
1029 [DNS_RCODE_REFUSED] = "REFUSED",
1030 [DNS_RCODE_YXDOMAIN] = "YXDOMAIN",
1031 [DNS_RCODE_YXRRSET] = "YRRSET",
1032 [DNS_RCODE_NXRRSET] = "NXRRSET",
1033 [DNS_RCODE_NOTAUTH] = "NOTAUTH",
1034 [DNS_RCODE_NOTZONE] = "NOTZONE",
1035 [DNS_RCODE_BADVERS] = "BADVERS",
1036 [DNS_RCODE_BADKEY] = "BADKEY",
1037 [DNS_RCODE_BADTIME] = "BADTIME",
1038 [DNS_RCODE_BADMODE] = "BADMODE",
1039 [DNS_RCODE_BADNAME] = "BADNAME",
1040 [DNS_RCODE_BADALG] = "BADALG",
1041 [DNS_RCODE_BADTRUNC] = "BADTRUNC",
1043 DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int);
1045 static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = {
1046 [DNS_PROTOCOL_DNS] = "dns",
1047 [DNS_PROTOCOL_MDNS] = "mdns",
1048 [DNS_PROTOCOL_LLMNR] = "llmnr",
1050 DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);