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 "resolved-dns-domain.h"
26 #include "resolved-dns-packet.h"
28 int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
35 a = DNS_PACKET_SIZE_START;
39 if (a < DNS_PACKET_HEADER_SIZE)
40 a = DNS_PACKET_HEADER_SIZE;
42 /* round up to next page size */
43 a = PAGE_ALIGN(ALIGN(sizeof(DnsPacket)) + a) - ALIGN(sizeof(DnsPacket));
45 /* make sure we never allocate more than useful */
46 if (a > DNS_PACKET_SIZE_MAX)
47 a = DNS_PACKET_SIZE_MAX;
49 p = malloc0(ALIGN(sizeof(DnsPacket)) + a);
53 p->size = p->rindex = DNS_PACKET_HEADER_SIZE;
55 p->protocol = protocol;
63 int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
70 r = dns_packet_new(&p, protocol, mtu);
74 h = DNS_PACKET_HEADER(p);
76 if (protocol == DNS_PROTOCOL_LLMNR)
77 h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
87 h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
91 1 /* rd (ask for recursion) */,
101 DnsPacket *dns_packet_ref(DnsPacket *p) {
106 assert(p->n_ref > 0);
111 static void dns_packet_free(DnsPacket *p) {
116 dns_question_unref(p->question);
117 dns_answer_unref(p->answer);
119 while ((s = hashmap_steal_first_key(p->names)))
121 hashmap_free(p->names);
127 DnsPacket *dns_packet_unref(DnsPacket *p) {
131 assert(p->n_ref > 0);
141 int dns_packet_validate(DnsPacket *p) {
144 if (p->size < DNS_PACKET_HEADER_SIZE)
147 if (p->size > DNS_PACKET_SIZE_MAX)
153 int dns_packet_validate_reply(DnsPacket *p) {
158 r = dns_packet_validate(p);
162 if (DNS_PACKET_QR(p) != 1)
165 if (DNS_PACKET_OPCODE(p) != 0)
168 /* RFC 4795, Section 2.1.1. says to discard all replies with QDCOUNT != 1 */
169 if (p->protocol == DNS_PROTOCOL_LLMNR &&
170 DNS_PACKET_QDCOUNT(p) != 1)
176 int dns_packet_validate_query(DnsPacket *p) {
181 r = dns_packet_validate(p);
185 if (DNS_PACKET_QR(p) != 0)
188 if (DNS_PACKET_OPCODE(p) != 0)
191 if (DNS_PACKET_TC(p))
194 /* RFC 4795, Section 2.1.1. says to discard all queries with QDCOUNT != 1 */
195 if (p->protocol == DNS_PROTOCOL_LLMNR &&
196 DNS_PACKET_QDCOUNT(p) != 1)
199 /* RFC 4795, Section 2.1.1. says to discard all queries with ANCOUNT != 0 */
200 if (DNS_PACKET_ANCOUNT(p) > 0)
203 /* RFC 4795, Section 2.1.1. says to discard all queries with NSCOUNT != 0 */
204 if (DNS_PACKET_NSCOUNT(p) > 0)
210 static int dns_packet_extend(DnsPacket *p, size_t add, void **ret, size_t *start) {
213 if (p->size + add > p->allocated) {
216 a = PAGE_ALIGN((p->size + add) * 2);
217 if (a > DNS_PACKET_SIZE_MAX)
218 a = DNS_PACKET_SIZE_MAX;
220 if (p->size + add > a)
226 d = realloc(p->_data, a);
232 p->_data = malloc(a);
236 memcpy(p->_data, (uint8_t*) p + ALIGN(sizeof(DnsPacket)), p->size);
237 memzero((uint8_t*) p->_data + p->size, a - p->size);
247 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->size;
253 static void dns_packet_truncate(DnsPacket *p, size_t sz) {
263 HASHMAP_FOREACH_KEY(s, n, p->names, i) {
265 if (PTR_TO_SIZE(n) < sz)
268 hashmap_remove(p->names, s);
275 int dns_packet_append_blob(DnsPacket *p, const void *d, size_t l, size_t *start) {
281 r = dns_packet_extend(p, l, &q, start);
289 int dns_packet_append_uint8(DnsPacket *p, uint8_t v, size_t *start) {
295 r = dns_packet_extend(p, sizeof(uint8_t), &d, start);
299 ((uint8_t*) d)[0] = v;
304 int dns_packet_append_uint16(DnsPacket *p, uint16_t v, size_t *start) {
310 r = dns_packet_extend(p, sizeof(uint16_t), &d, start);
314 ((uint8_t*) d)[0] = (uint8_t) (v >> 8);
315 ((uint8_t*) d)[1] = (uint8_t) v;
320 int dns_packet_append_uint32(DnsPacket *p, uint32_t v, size_t *start) {
326 r = dns_packet_extend(p, sizeof(uint32_t), &d, start);
330 ((uint8_t*) d)[0] = (uint8_t) (v >> 24);
331 ((uint8_t*) d)[1] = (uint8_t) (v >> 16);
332 ((uint8_t*) d)[2] = (uint8_t) (v >> 8);
333 ((uint8_t*) d)[3] = (uint8_t) v;
338 int dns_packet_append_string(DnsPacket *p, const char *s, size_t *start) {
350 r = dns_packet_extend(p, 1 + l, &d, start);
354 ((uint8_t*) d)[0] = (uint8_t) l;
355 memcpy(((uint8_t*) d) + 1, s, l);
360 int dns_packet_append_label(DnsPacket *p, const char *d, size_t l, size_t *start) {
367 if (l > DNS_LABEL_MAX)
370 r = dns_packet_extend(p, 1 + l, &w, start);
374 ((uint8_t*) w)[0] = (uint8_t) l;
375 memcpy(((uint8_t*) w) + 1, d, l);
380 int dns_packet_append_name(DnsPacket *p, const char *name, size_t *start) {
387 saved_size = p->size;
390 _cleanup_free_ char *s = NULL;
391 char label[DNS_LABEL_MAX];
394 n = PTR_TO_SIZE(hashmap_get(p->names, name));
399 r = dns_packet_append_uint16(p, 0xC000 | n, NULL);
413 r = dns_label_unescape(&name, label, sizeof(label));
417 r = dns_packet_append_label(p, label, r, &n);
421 r = hashmap_ensure_allocated(&p->names, dns_name_hash_func, dns_name_compare_func);
425 r = hashmap_put(p->names, s, SIZE_TO_PTR(n));
432 r = dns_packet_append_uint8(p, 0, NULL);
443 dns_packet_truncate(p, saved_size);
447 int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *k, size_t *start) {
454 saved_size = p->size;
456 r = dns_packet_append_name(p, DNS_RESOURCE_KEY_NAME(k), NULL);
460 r = dns_packet_append_uint16(p, k->type, NULL);
464 r = dns_packet_append_uint16(p, k->class, NULL);
474 dns_packet_truncate(p, saved_size);
478 int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start) {
479 size_t saved_size, rdlength_offset, end, rdlength;
485 saved_size = p->size;
487 r = dns_packet_append_key(p, rr->key, NULL);
491 r = dns_packet_append_uint32(p, rr->ttl, NULL);
495 /* Initially we write 0 here */
496 r = dns_packet_append_uint16(p, 0, &rdlength_offset);
500 switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
506 r = dns_packet_append_name(p, rr->ptr.name, NULL);
510 r = dns_packet_append_string(p, rr->hinfo.cpu, NULL);
514 r = dns_packet_append_string(p, rr->hinfo.os, NULL);
517 case DNS_TYPE_SPF: /* exactly the same as TXT */
521 STRV_FOREACH(s, rr->txt.strings) {
522 r = dns_packet_append_string(p, *s, NULL);
531 r = dns_packet_append_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
535 r = dns_packet_append_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
539 r = dns_packet_append_name(p, rr->soa.mname, NULL);
543 r = dns_packet_append_name(p, rr->soa.rname, NULL);
547 r = dns_packet_append_uint32(p, rr->soa.serial, NULL);
551 r = dns_packet_append_uint32(p, rr->soa.refresh, NULL);
555 r = dns_packet_append_uint32(p, rr->soa.retry, NULL);
559 r = dns_packet_append_uint32(p, rr->soa.expire, NULL);
563 r = dns_packet_append_uint32(p, rr->soa.minimum, NULL);
567 r = dns_packet_append_uint16(p, rr->mx.priority, NULL);
571 r = dns_packet_append_name(p, rr->mx.exchange, NULL);
575 r = dns_packet_append_uint8(p, rr->loc.version, NULL);
579 r = dns_packet_append_uint8(p, rr->loc.size, NULL);
583 r = dns_packet_append_uint8(p, rr->loc.horiz_pre, NULL);
587 r = dns_packet_append_uint8(p, rr->loc.vert_pre, NULL);
591 r = dns_packet_append_uint16(p, rr->loc.latitude, NULL);
595 r = dns_packet_append_uint16(p, rr->loc.longitude, NULL);
599 r = dns_packet_append_uint16(p, rr->loc.altitude, NULL);
604 case _DNS_TYPE_INVALID: /* unparseable */
607 r = dns_packet_append_blob(p, rr->generic.data, rr->generic.size, NULL);
613 /* Let's calculate the actual data size and update the field */
614 rdlength = p->size - rdlength_offset - sizeof(uint16_t);
615 if (rdlength > 0xFFFF) {
621 p->size = rdlength_offset;
622 r = dns_packet_append_uint16(p, rdlength, NULL);
633 dns_packet_truncate(p, saved_size);
638 int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) {
641 if (p->rindex + sz > p->size)
645 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->rindex;
654 void dns_packet_rewind(DnsPacket *p, size_t idx) {
656 assert(idx <= p->size);
657 assert(idx >= DNS_PACKET_HEADER_SIZE);
662 int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start) {
669 r = dns_packet_read(p, sz, &q, start);
677 int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) {
683 r = dns_packet_read(p, sizeof(uint8_t), &d, start);
687 *ret = ((uint8_t*) d)[0];
691 int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start) {
697 r = dns_packet_read(p, sizeof(uint16_t), &d, start);
701 *ret = (((uint16_t) ((uint8_t*) d)[0]) << 8) |
702 ((uint16_t) ((uint8_t*) d)[1]);
706 int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start) {
712 r = dns_packet_read(p, sizeof(uint32_t), &d, start);
716 *ret = (((uint32_t) ((uint8_t*) d)[0]) << 24) |
717 (((uint32_t) ((uint8_t*) d)[1]) << 16) |
718 (((uint32_t) ((uint8_t*) d)[2]) << 8) |
719 ((uint32_t) ((uint8_t*) d)[3]);
724 int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start) {
733 saved_rindex = p->rindex;
735 r = dns_packet_read_uint8(p, &c, NULL);
739 r = dns_packet_read(p, c, &d, NULL);
743 if (memchr(d, 0, c)) {
754 if (!utf8_is_valid(t)) {
763 *start = saved_rindex;
768 dns_packet_rewind(p, saved_rindex);
772 int dns_packet_read_name(DnsPacket *p, char **_ret, size_t *start) {
773 size_t saved_rindex, after_rindex = 0;
774 _cleanup_free_ char *ret = NULL;
775 size_t n = 0, allocated = 0;
782 saved_rindex = p->rindex;
787 r = dns_packet_read_uint8(p, &c, NULL);
795 _cleanup_free_ char *t = NULL;
799 r = dns_packet_read(p, c, (const void**) &label, NULL);
803 r = dns_label_escape(label, c, &t);
807 if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1)) {
817 memcpy(ret + n, t, c);
820 } else if ((c & 0xc0) == 0xc0) {
824 r = dns_packet_read_uint8(p, &d, NULL);
828 ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
829 if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= saved_rindex) {
834 if (after_rindex == 0)
835 after_rindex = p->rindex;
842 if (!GREEDY_REALLOC(ret, allocated, n + 1)) {
849 if (after_rindex != 0)
850 p->rindex= after_rindex;
856 *start = saved_rindex;
861 dns_packet_rewind(p, saved_rindex);
865 int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) {
866 _cleanup_free_ char *name = NULL;
867 uint16_t class, type;
875 saved_rindex = p->rindex;
877 r = dns_packet_read_name(p, &name, NULL);
881 r = dns_packet_read_uint16(p, &type, NULL);
885 r = dns_packet_read_uint16(p, &class, NULL);
889 key = dns_resource_key_new_consume(class, type, name);
899 *start = saved_rindex;
903 dns_packet_rewind(p, saved_rindex);
907 int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
908 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
909 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
910 size_t saved_rindex, offset;
918 saved_rindex = p->rindex;
920 r = dns_packet_read_key(p, &key, NULL);
924 if (key->class == DNS_CLASS_ANY ||
925 key->type == DNS_TYPE_ANY) {
930 rr = dns_resource_record_new(key);
936 r = dns_packet_read_uint32(p, &rr->ttl, NULL);
940 r = dns_packet_read_uint16(p, &rdlength, NULL);
944 if (p->rindex + rdlength > p->size) {
951 switch (rr->key->type) {
957 r = dns_packet_read_name(p, &rr->ptr.name, NULL);
961 r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL);
965 r = dns_packet_read_string(p, &rr->hinfo.os, NULL);
968 case DNS_TYPE_SPF: /* exactly the same as TXT */
972 while (p->rindex < offset + rdlength) {
973 r = dns_packet_read_string(p, &s, NULL);
977 r = strv_consume(&rr->txt.strings, s);
985 r = dns_packet_read_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
989 r = dns_packet_read_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
993 r = dns_packet_read_name(p, &rr->soa.mname, NULL);
997 r = dns_packet_read_name(p, &rr->soa.rname, NULL);
1001 r = dns_packet_read_uint32(p, &rr->soa.serial, NULL);
1005 r = dns_packet_read_uint32(p, &rr->soa.refresh, NULL);
1009 r = dns_packet_read_uint32(p, &rr->soa.retry, NULL);
1013 r = dns_packet_read_uint32(p, &rr->soa.expire, NULL);
1017 r = dns_packet_read_uint32(p, &rr->soa.minimum, NULL);
1021 r = dns_packet_read_uint16(p, &rr->mx.priority, NULL);
1025 r = dns_packet_read_name(p, &rr->mx.exchange, NULL);
1028 case DNS_TYPE_LOC: {
1032 r = dns_packet_read_uint8(p, &t, &pos);
1037 rr->loc.version = t;
1039 r = dns_packet_read_uint8(p, &rr->loc.size, NULL);
1043 r = dns_packet_read_uint8(p, &rr->loc.horiz_pre, NULL);
1047 r = dns_packet_read_uint8(p, &rr->loc.vert_pre, NULL);
1051 r = dns_packet_read_uint32(p, &rr->loc.latitude, NULL);
1055 r = dns_packet_read_uint32(p, &rr->loc.longitude, NULL);
1059 r = dns_packet_read_uint32(p, &rr->loc.altitude, NULL);
1065 dns_packet_rewind(p, pos);
1066 rr->unparseable = true;
1072 case DNS_TYPE_SSHFP:
1074 r = dns_packet_read(p, rdlength, &d, NULL);
1078 rr->generic.data = memdup(d, rdlength);
1079 if (!rr->generic.data) {
1084 rr->generic.size = rdlength;
1089 if (p->rindex != offset + rdlength) {
1098 *start = saved_rindex;
1102 dns_packet_rewind(p, saved_rindex);
1106 int dns_packet_extract(DnsPacket *p) {
1107 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
1108 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
1109 size_t saved_rindex;
1113 saved_rindex = p->rindex;
1114 dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
1116 n = DNS_PACKET_QDCOUNT(p);
1118 question = dns_question_new(n);
1124 for (i = 0; i < n; i++) {
1125 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
1127 r = dns_packet_read_key(p, &key, NULL);
1131 r = dns_question_add(question, key);
1137 n = DNS_PACKET_RRCOUNT(p);
1139 answer = dns_answer_new(n);
1145 for (i = 0; i < n; i++) {
1146 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
1148 r = dns_packet_read_rr(p, &rr, NULL);
1152 r = dns_answer_add(answer, rr);
1158 p->question = question;
1167 p->rindex = saved_rindex;
1171 static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
1172 [DNS_RCODE_SUCCESS] = "SUCCESS",
1173 [DNS_RCODE_FORMERR] = "FORMERR",
1174 [DNS_RCODE_SERVFAIL] = "SERVFAIL",
1175 [DNS_RCODE_NXDOMAIN] = "NXDOMAIN",
1176 [DNS_RCODE_NOTIMP] = "NOTIMP",
1177 [DNS_RCODE_REFUSED] = "REFUSED",
1178 [DNS_RCODE_YXDOMAIN] = "YXDOMAIN",
1179 [DNS_RCODE_YXRRSET] = "YRRSET",
1180 [DNS_RCODE_NXRRSET] = "NXRRSET",
1181 [DNS_RCODE_NOTAUTH] = "NOTAUTH",
1182 [DNS_RCODE_NOTZONE] = "NOTZONE",
1183 [DNS_RCODE_BADVERS] = "BADVERS",
1184 [DNS_RCODE_BADKEY] = "BADKEY",
1185 [DNS_RCODE_BADTIME] = "BADTIME",
1186 [DNS_RCODE_BADMODE] = "BADMODE",
1187 [DNS_RCODE_BADNAME] = "BADNAME",
1188 [DNS_RCODE_BADALG] = "BADALG",
1189 [DNS_RCODE_BADTRUNC] = "BADTRUNC",
1191 DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int);
1193 static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = {
1194 [DNS_PROTOCOL_DNS] = "dns",
1195 [DNS_PROTOCOL_MDNS] = "mdns",
1196 [DNS_PROTOCOL_LLMNR] = "llmnr",
1198 DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);