]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-dns-packet.c
resolved: add LLMNR support for looking up names
[thirdparty/systemd.git] / src / resolve / resolved-dns-packet.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2014 Lennart Poettering
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include "utf8.h"
23 #include "util.h"
24 #include "resolved-dns-domain.h"
25 #include "resolved-dns-packet.h"
26
27 int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
28 DnsPacket *p;
29 size_t a;
30
31 assert(ret);
32
33 if (mtu <= 0)
34 a = DNS_PACKET_SIZE_START;
35 else
36 a = mtu;
37
38 if (a < DNS_PACKET_HEADER_SIZE)
39 a = DNS_PACKET_HEADER_SIZE;
40
41 /* round up to next page size */
42 a = PAGE_ALIGN(ALIGN(sizeof(DnsPacket)) + a) - ALIGN(sizeof(DnsPacket));
43
44 /* make sure we never allocate more than useful */
45 if (a > DNS_PACKET_SIZE_MAX)
46 a = DNS_PACKET_SIZE_MAX;
47
48 p = malloc0(ALIGN(sizeof(DnsPacket)) + a);
49 if (!p)
50 return -ENOMEM;
51
52 p->size = p->rindex = DNS_PACKET_HEADER_SIZE;
53 p->allocated = a;
54 p->protocol = protocol;
55 p->n_ref = 1;
56
57 *ret = p;
58
59 return 0;
60 }
61
62 int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
63 DnsPacket *p;
64 DnsPacketHeader *h;
65 int r;
66
67 assert(ret);
68
69 r = dns_packet_new(&p, protocol, mtu);
70 if (r < 0)
71 return r;
72
73 h = DNS_PACKET_HEADER(p);
74
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 */
77 else
78 h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0, 0, 0, 0, 0, 0, 0, 0, 0));
79
80 *ret = p;
81 return 0;
82 }
83
84 DnsPacket *dns_packet_ref(DnsPacket *p) {
85
86 if (!p)
87 return NULL;
88
89 assert(p->n_ref > 0);
90 p->n_ref++;
91 return p;
92 }
93
94 static void dns_packet_free(DnsPacket *p) {
95 char *s;
96
97 assert(p);
98
99 if (p->rrs)
100 dns_resource_record_freev(p->rrs, DNS_PACKET_RRCOUNT(p));
101
102 while ((s = hashmap_steal_first_key(p->names)))
103 free(s);
104 hashmap_free(p->names);
105
106 free(p->data);
107 free(p);
108 }
109
110 DnsPacket *dns_packet_unref(DnsPacket *p) {
111 if (!p)
112 return NULL;
113
114 assert(p->n_ref > 0);
115
116 if (p->n_ref == 1)
117 dns_packet_free(p);
118 else
119 p->n_ref--;
120
121 return NULL;
122 }
123
124 int dns_packet_validate(DnsPacket *p) {
125 assert(p);
126
127 if (p->size < DNS_PACKET_HEADER_SIZE)
128 return -EBADMSG;
129
130 if (p->size > DNS_PACKET_SIZE_MAX)
131 return -EBADMSG;
132
133 return 0;
134 }
135
136 int dns_packet_validate_reply(DnsPacket *p) {
137 int r;
138
139 assert(p);
140
141 r = dns_packet_validate(p);
142 if (r < 0)
143 return r;
144
145 if (DNS_PACKET_QR(p) == 0)
146 return -EBADMSG;
147
148 if (DNS_PACKET_OPCODE(p) != 0)
149 return -EBADMSG;
150
151 return 0;
152 }
153
154 static int dns_packet_extend(DnsPacket *p, size_t add, void **ret, size_t *start) {
155 assert(p);
156
157 if (p->size + add > p->allocated) {
158 size_t a;
159
160 a = PAGE_ALIGN((p->size + add) * 2);
161 if (a > DNS_PACKET_SIZE_MAX)
162 a = DNS_PACKET_SIZE_MAX;
163
164 if (p->size + add > a)
165 return -EMSGSIZE;
166
167 if (p->data) {
168 void *d;
169
170 d = realloc(p->data, a);
171 if (!d)
172 return -ENOMEM;
173
174 p->data = d;
175 } else {
176 p->data = malloc(a);
177 if (!p->data)
178 return -ENOMEM;
179
180 memcpy(p->data, (uint8_t*) p + ALIGN(sizeof(DnsPacket)), p->size);
181 memzero((uint8_t*) p->data + p->size, a - p->size);
182 }
183
184 p->allocated = a;
185 }
186
187 if (start)
188 *start = p->size;
189
190 if (ret)
191 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->size;
192
193 p->size += add;
194 return 0;
195 }
196
197 static void dns_packet_truncate(DnsPacket *p, size_t sz) {
198 Iterator i;
199 char *s;
200 void *n;
201
202 assert(p);
203
204 if (p->size <= sz)
205 return;
206
207 HASHMAP_FOREACH_KEY(s, n, p->names, i) {
208
209 if (PTR_TO_SIZE(n) < sz)
210 continue;
211
212 hashmap_remove(p->names, s);
213 free(s);
214 }
215
216 p->size = sz;
217 }
218
219 int dns_packet_append_uint8(DnsPacket *p, uint8_t v, size_t *start) {
220 void *d;
221 int r;
222
223 assert(p);
224
225 r = dns_packet_extend(p, sizeof(uint8_t), &d, start);
226 if (r < 0)
227 return r;
228
229 ((uint8_t*) d)[0] = v;
230
231 return 0;
232 }
233
234 int dns_packet_append_uint16(DnsPacket *p, uint16_t v, size_t *start) {
235 void *d;
236 int r;
237
238 assert(p);
239
240 r = dns_packet_extend(p, sizeof(uint16_t), &d, start);
241 if (r < 0)
242 return r;
243
244 ((uint8_t*) d)[0] = (uint8_t) (v >> 8);
245 ((uint8_t*) d)[1] = (uint8_t) (v & 255);
246
247 return 0;
248 }
249
250 int dns_packet_append_string(DnsPacket *p, const char *s, size_t *start) {
251 void *d;
252 size_t l;
253 int r;
254
255 assert(p);
256 assert(s);
257
258 l = strlen(s);
259 if (l > 255)
260 return -E2BIG;
261
262 r = dns_packet_extend(p, 1 + l, &d, start);
263 if (r < 0)
264 return r;
265
266 ((uint8_t*) d)[0] = (uint8_t) l;
267 memcpy(((uint8_t*) d) + 1, s, l);
268
269 return 0;
270 }
271
272 int dns_packet_append_label(DnsPacket *p, const char *d, size_t l, size_t *start) {
273 void *w;
274 int r;
275
276 assert(p);
277 assert(d);
278
279 if (l > DNS_LABEL_MAX)
280 return -E2BIG;
281
282 r = dns_packet_extend(p, 1 + l, &w, start);
283 if (r < 0)
284 return r;
285
286 ((uint8_t*) w)[0] = (uint8_t) l;
287 memcpy(((uint8_t*) w) + 1, d, l);
288
289 return 0;
290 }
291
292 int dns_packet_append_name(DnsPacket *p, const char *name, size_t *start) {
293 size_t saved_size;
294 int r;
295
296 assert(p);
297 assert(name);
298
299 saved_size = p->size;
300
301 while (*name) {
302 _cleanup_free_ char *s = NULL;
303 char label[DNS_LABEL_MAX];
304 size_t n;
305
306 n = PTR_TO_SIZE(hashmap_get(p->names, name));
307 if (n > 0) {
308 assert(n < p->size);
309
310 if (n < 0x4000) {
311 r = dns_packet_append_uint16(p, 0xC000 | n, NULL);
312 if (r < 0)
313 goto fail;
314
315 goto done;
316 }
317 }
318
319 s = strdup(name);
320 if (!s) {
321 r = -ENOMEM;
322 goto fail;
323 }
324
325 r = dns_label_unescape(&name, label, sizeof(label));
326 if (r < 0)
327 goto fail;
328
329 r = dns_packet_append_label(p, label, r, &n);
330 if (r < 0)
331 goto fail;
332
333 r = hashmap_ensure_allocated(&p->names, dns_name_hash_func, dns_name_compare_func);
334 if (r < 0)
335 goto fail;
336
337 r = hashmap_put(p->names, s, SIZE_TO_PTR(n));
338 if (r < 0)
339 goto fail;
340
341 s = NULL;
342 }
343
344 r = dns_packet_append_uint8(p, 0, NULL);
345 if (r < 0)
346 return r;
347
348 done:
349 if (start)
350 *start = saved_size;
351
352 return 0;
353
354 fail:
355 dns_packet_truncate(p, saved_size);
356 return r;
357 }
358
359 int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *k, size_t *start) {
360 size_t saved_size;
361 int r;
362
363 assert(p);
364 assert(k);
365
366 saved_size = p->size;
367
368 r = dns_packet_append_name(p, k->name, NULL);
369 if (r < 0)
370 goto fail;
371
372 r = dns_packet_append_uint16(p, k->type, NULL);
373 if (r < 0)
374 goto fail;
375
376 r = dns_packet_append_uint16(p, k->class, NULL);
377 if (r < 0)
378 goto fail;
379
380 if (start)
381 *start = saved_size;
382
383 return 0;
384
385 fail:
386 dns_packet_truncate(p, saved_size);
387 return r;
388 }
389
390 int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) {
391 assert(p);
392
393 if (p->rindex + sz > p->size)
394 return -EMSGSIZE;
395
396 if (ret)
397 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->rindex;
398
399 if (start)
400 *start = p->rindex;
401
402 p->rindex += sz;
403 return 0;
404 }
405
406 void dns_packet_rewind(DnsPacket *p, size_t idx) {
407 assert(p);
408 assert(idx <= p->size);
409 assert(idx >= DNS_PACKET_HEADER_SIZE);
410
411 p->rindex = idx;
412 }
413
414 int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) {
415 const void *d;
416 int r;
417
418 assert(p);
419
420 r = dns_packet_read(p, sizeof(uint8_t), &d, start);
421 if (r < 0)
422 return r;
423
424 *ret = ((uint8_t*) d)[0];
425 return 0;
426 }
427
428 int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start) {
429 const void *d;
430 int r;
431
432 assert(p);
433
434 r = dns_packet_read(p, sizeof(uint16_t), &d, start);
435 if (r < 0)
436 return r;
437
438 *ret = (((uint16_t) ((uint8_t*) d)[0]) << 8) |
439 ((uint16_t) ((uint8_t*) d)[1]);
440 return 0;
441 }
442
443 int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start) {
444 const void *d;
445 int r;
446
447 assert(p);
448
449 r = dns_packet_read(p, sizeof(uint32_t), &d, start);
450 if (r < 0)
451 return r;
452
453 *ret = (((uint32_t) ((uint8_t*) d)[0]) << 24) |
454 (((uint32_t) ((uint8_t*) d)[1]) << 16) |
455 (((uint32_t) ((uint8_t*) d)[2]) << 8) |
456 ((uint32_t) ((uint8_t*) d)[3]);
457
458 return 0;
459 }
460
461 int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start) {
462 size_t saved_rindex;
463 const void *d;
464 char *t;
465 uint8_t c;
466 int r;
467
468 assert(p);
469
470 saved_rindex = p->rindex;
471
472 r = dns_packet_read_uint8(p, &c, NULL);
473 if (r < 0)
474 goto fail;
475
476 r = dns_packet_read(p, c, &d, NULL);
477 if (r < 0)
478 goto fail;
479
480 if (memchr(d, 0, c)) {
481 r = -EBADMSG;
482 goto fail;
483 }
484
485 t = strndup(d, c);
486 if (!t) {
487 r = -ENOMEM;
488 goto fail;
489 }
490
491 if (!utf8_is_valid(t)) {
492 free(t);
493 r = -EBADMSG;
494 goto fail;
495 }
496
497 *ret = t;
498
499 if (start)
500 *start = saved_rindex;
501
502 return 0;
503
504 fail:
505 dns_packet_rewind(p, saved_rindex);
506 return r;
507 }
508
509 int dns_packet_read_name(DnsPacket *p, char **_ret, size_t *start) {
510 size_t saved_rindex, after_rindex = 0;
511 _cleanup_free_ char *ret = NULL;
512 size_t n = 0, allocated = 0;
513 bool first = true;
514 int r;
515
516 assert(p);
517 assert(_ret);
518
519 saved_rindex = p->rindex;
520
521 for (;;) {
522 uint8_t c, d;
523
524 r = dns_packet_read_uint8(p, &c, NULL);
525 if (r < 0)
526 goto fail;
527
528 if (c == 0)
529 /* End of name */
530 break;
531 else if (c <= 63) {
532 _cleanup_free_ char *t = NULL;
533 const char *label;
534
535 /* Literal label */
536 r = dns_packet_read(p, c, (const void**) &label, NULL);
537 if (r < 0)
538 goto fail;
539
540 r = dns_label_escape(label, c, &t);
541 if (r < 0)
542 goto fail;
543
544 if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1)) {
545 r = -ENOMEM;
546 goto fail;
547 }
548
549 if (!first)
550 ret[n++] = '.';
551 else
552 first = false;
553
554 memcpy(ret + n, t, c);
555 n += r;
556 continue;
557 } else if ((c & 0xc0) == 0xc0) {
558 uint16_t ptr;
559
560 /* Pointer */
561 r = dns_packet_read_uint8(p, &d, NULL);
562 if (r < 0)
563 goto fail;
564
565 ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
566 if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= saved_rindex) {
567 r = -EBADMSG;
568 goto fail;
569 }
570
571 if (after_rindex == 0)
572 after_rindex = p->rindex;
573
574 p->rindex = ptr;
575 } else
576 goto fail;
577 }
578
579 if (!GREEDY_REALLOC(ret, allocated, n + 1)) {
580 r = -ENOMEM;
581 goto fail;
582 }
583
584 ret[n] = 0;
585
586 if (after_rindex != 0)
587 p->rindex= after_rindex;
588
589 *_ret = ret;
590 ret = NULL;
591
592 if (start)
593 *start = saved_rindex;
594
595 return 0;
596
597 fail:
598 dns_packet_rewind(p, saved_rindex);
599 return r;
600 }
601
602 int dns_packet_read_key(DnsPacket *p, DnsResourceKey *ret, size_t *start) {
603 _cleanup_(dns_resource_key_free) DnsResourceKey k = {};
604 size_t saved_rindex;
605 int r;
606
607 assert(p);
608 assert(ret);
609
610 saved_rindex = p->rindex;
611
612 r = dns_packet_read_name(p, &k.name, NULL);
613 if (r < 0)
614 goto fail;
615
616 r = dns_packet_read_uint16(p, &k.type, NULL);
617 if (r < 0)
618 goto fail;
619
620 r = dns_packet_read_uint16(p, &k.class, NULL);
621 if (r < 0)
622 goto fail;
623
624 *ret = k;
625 zero(k);
626
627 if (start)
628 *start = saved_rindex;
629
630 return 0;
631 fail:
632 dns_packet_rewind(p, saved_rindex);
633 return r;
634 }
635
636 int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
637 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr;
638 size_t saved_rindex, offset;
639 uint16_t rdlength;
640 const void *d;
641 int r;
642
643 assert(p);
644 assert(ret);
645
646 rr = dns_resource_record_new();
647 if (!rr)
648 return -ENOMEM;
649
650 saved_rindex = p->rindex;
651
652 r = dns_packet_read_key(p, &rr->key, NULL);
653 if (r < 0)
654 goto fail;
655
656 r = dns_packet_read_uint32(p, &rr->ttl, NULL);
657 if (r < 0)
658 goto fail;
659
660 r = dns_packet_read_uint16(p, &rdlength, NULL);
661 if (r < 0)
662 goto fail;
663
664 if (p->rindex + rdlength > p->size) {
665 r = -EBADMSG;
666 goto fail;
667 }
668
669 offset = p->rindex;
670
671 switch (rr->key.type) {
672
673 case DNS_TYPE_PTR:
674 case DNS_TYPE_NS:
675 case DNS_TYPE_CNAME:
676 r = dns_packet_read_name(p, &rr->ptr.name, NULL);
677 break;
678
679 case DNS_TYPE_HINFO:
680 r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL);
681 if (r < 0)
682 goto fail;
683
684 r = dns_packet_read_string(p, &rr->hinfo.os, NULL);
685 break;
686
687 case DNS_TYPE_A:
688 r = dns_packet_read(p, sizeof(struct in_addr), &d, NULL);
689 if (r < 0)
690 goto fail;
691
692 memcpy(&rr->a.in_addr, d, sizeof(struct in_addr));
693 break;
694
695 case DNS_TYPE_AAAA:
696 r = dns_packet_read(p, sizeof(struct in6_addr), &d, NULL);
697 if (r < 0)
698 goto fail;
699
700 memcpy(&rr->aaaa.in6_addr, d, sizeof(struct in6_addr));
701 break;
702
703 default:
704 r = dns_packet_read(p, rdlength, &d, NULL);
705 if (r < 0)
706 goto fail;
707
708 rr->generic.data = memdup(d, rdlength);
709 if (!rr->generic.data) {
710 r = -ENOMEM;
711 goto fail;
712 }
713
714 rr->generic.size = rdlength;
715 break;
716 }
717 if (r < 0)
718 goto fail;
719 if (p->rindex != offset + rdlength) {
720 r = -EBADMSG;
721 goto fail;
722 }
723
724 *ret = rr;
725 rr = NULL;
726
727 if (start)
728 *start = saved_rindex;
729
730 return 0;
731 fail:
732 dns_packet_rewind(p, saved_rindex);
733 return r;
734 }
735
736 int dns_packet_skip_question(DnsPacket *p) {
737 unsigned i, n;
738 int r;
739
740 assert(p);
741
742 dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
743
744 n = DNS_PACKET_QDCOUNT(p);
745 for (i = 0; i < n; i++) {
746 _cleanup_(dns_resource_key_free) DnsResourceKey key = {};
747
748 r = dns_packet_read_key(p, &key, NULL);
749 if (r < 0)
750 return r;
751 }
752
753 return 0;
754 }
755
756 int dns_packet_extract_rrs(DnsPacket *p) {
757 DnsResourceRecord **rrs = NULL;
758 size_t saved_rindex;
759 unsigned n, added = 0;
760 int r;
761
762 if (p->rrs)
763 return (int) DNS_PACKET_RRCOUNT(p);
764
765 saved_rindex = p->rindex;
766
767 r = dns_packet_skip_question(p);
768 if (r < 0)
769 goto finish;
770
771 n = DNS_PACKET_RRCOUNT(p);
772 if (n <= 0) {
773 r = 0;
774 goto finish;
775 }
776
777 rrs = new0(DnsResourceRecord*, n);
778 if (!rrs) {
779 r = -ENOMEM;
780 goto finish;
781 }
782
783 for (added = 0; added < n; added++) {
784 r = dns_packet_read_rr(p, &rrs[added], NULL);
785 if (r < 0) {
786 dns_resource_record_freev(rrs, added);
787 goto finish;
788 }
789 }
790
791 p->rrs = rrs;
792 r = (int) n;
793
794 finish:
795 p->rindex = saved_rindex;
796 return r;
797 }
798
799 static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
800 [DNS_RCODE_SUCCESS] = "SUCCESS",
801 [DNS_RCODE_FORMERR] = "FORMERR",
802 [DNS_RCODE_SERVFAIL] = "SERVFAIL",
803 [DNS_RCODE_NXDOMAIN] = "NXDOMAIN",
804 [DNS_RCODE_NOTIMP] = "NOTIMP",
805 [DNS_RCODE_REFUSED] = "REFUSED",
806 [DNS_RCODE_YXDOMAIN] = "YXDOMAIN",
807 [DNS_RCODE_YXRRSET] = "YRRSET",
808 [DNS_RCODE_NXRRSET] = "NXRRSET",
809 [DNS_RCODE_NOTAUTH] = "NOTAUTH",
810 [DNS_RCODE_NOTZONE] = "NOTZONE",
811 [DNS_RCODE_BADVERS] = "BADVERS",
812 [DNS_RCODE_BADKEY] = "BADKEY",
813 [DNS_RCODE_BADTIME] = "BADTIME",
814 [DNS_RCODE_BADMODE] = "BADMODE",
815 [DNS_RCODE_BADNAME] = "BADNAME",
816 [DNS_RCODE_BADALG] = "BADALG",
817 [DNS_RCODE_BADTRUNC] = "BADTRUNC",
818 };
819 DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int);
820
821 static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = {
822 [DNS_PROTOCOL_DNS] = "dns",
823 [DNS_PROTOCOL_MDNS] = "mdns",
824 [DNS_PROTOCOL_LLMNR] = "llmnr",
825 };
826 DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);