]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-dns-packet.c
resolved: DNSKEY records
[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 "strv.h"
25 #include "resolved-dns-domain.h"
26 #include "resolved-dns-packet.h"
27
28 int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
29 DnsPacket *p;
30 size_t a;
31
32 assert(ret);
33
34 if (mtu <= 0)
35 a = DNS_PACKET_SIZE_START;
36 else
37 a = mtu;
38
39 if (a < DNS_PACKET_HEADER_SIZE)
40 a = DNS_PACKET_HEADER_SIZE;
41
42 /* round up to next page size */
43 a = PAGE_ALIGN(ALIGN(sizeof(DnsPacket)) + a) - ALIGN(sizeof(DnsPacket));
44
45 /* make sure we never allocate more than useful */
46 if (a > DNS_PACKET_SIZE_MAX)
47 a = DNS_PACKET_SIZE_MAX;
48
49 p = malloc0(ALIGN(sizeof(DnsPacket)) + a);
50 if (!p)
51 return -ENOMEM;
52
53 p->size = p->rindex = DNS_PACKET_HEADER_SIZE;
54 p->allocated = a;
55 p->protocol = protocol;
56 p->n_ref = 1;
57
58 *ret = p;
59
60 return 0;
61 }
62
63 int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
64 DnsPacket *p;
65 DnsPacketHeader *h;
66 int r;
67
68 assert(ret);
69
70 r = dns_packet_new(&p, protocol, mtu);
71 if (r < 0)
72 return r;
73
74 h = DNS_PACKET_HEADER(p);
75
76 if (protocol == DNS_PROTOCOL_LLMNR)
77 h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
78 0 /* opcode */,
79 0 /* c */,
80 0 /* tc */,
81 0 /* t */,
82 0 /* ra */,
83 0 /* ad */,
84 0 /* cd */,
85 0 /* rcode */));
86 else
87 h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
88 0 /* opcode */,
89 0 /* aa */,
90 0 /* tc */,
91 1 /* rd (ask for recursion) */,
92 0 /* ra */,
93 0 /* ad */,
94 0 /* cd */,
95 0 /* rcode */));
96
97 *ret = p;
98 return 0;
99 }
100
101 DnsPacket *dns_packet_ref(DnsPacket *p) {
102
103 if (!p)
104 return NULL;
105
106 assert(p->n_ref > 0);
107 p->n_ref++;
108 return p;
109 }
110
111 static void dns_packet_free(DnsPacket *p) {
112 char *s;
113
114 assert(p);
115
116 dns_question_unref(p->question);
117 dns_answer_unref(p->answer);
118
119 while ((s = hashmap_steal_first_key(p->names)))
120 free(s);
121 hashmap_free(p->names);
122
123 free(p->_data);
124 free(p);
125 }
126
127 DnsPacket *dns_packet_unref(DnsPacket *p) {
128 if (!p)
129 return NULL;
130
131 assert(p->n_ref > 0);
132
133 if (p->n_ref == 1)
134 dns_packet_free(p);
135 else
136 p->n_ref--;
137
138 return NULL;
139 }
140
141 int dns_packet_validate(DnsPacket *p) {
142 assert(p);
143
144 if (p->size < DNS_PACKET_HEADER_SIZE)
145 return -EBADMSG;
146
147 if (p->size > DNS_PACKET_SIZE_MAX)
148 return -EBADMSG;
149
150 return 1;
151 }
152
153 int dns_packet_validate_reply(DnsPacket *p) {
154 int r;
155
156 assert(p);
157
158 r = dns_packet_validate(p);
159 if (r < 0)
160 return r;
161
162 if (DNS_PACKET_QR(p) != 1)
163 return 0;
164
165 if (DNS_PACKET_OPCODE(p) != 0)
166 return -EBADMSG;
167
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)
171 return -EBADMSG;
172
173 return 1;
174 }
175
176 int dns_packet_validate_query(DnsPacket *p) {
177 int r;
178
179 assert(p);
180
181 r = dns_packet_validate(p);
182 if (r < 0)
183 return r;
184
185 if (DNS_PACKET_QR(p) != 0)
186 return 0;
187
188 if (DNS_PACKET_OPCODE(p) != 0)
189 return -EBADMSG;
190
191 if (DNS_PACKET_TC(p))
192 return -EBADMSG;
193
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)
197 return -EBADMSG;
198
199 /* RFC 4795, Section 2.1.1. says to discard all queries with ANCOUNT != 0 */
200 if (DNS_PACKET_ANCOUNT(p) > 0)
201 return -EBADMSG;
202
203 /* RFC 4795, Section 2.1.1. says to discard all queries with NSCOUNT != 0 */
204 if (DNS_PACKET_NSCOUNT(p) > 0)
205 return -EBADMSG;
206
207 return 1;
208 }
209
210 static int dns_packet_extend(DnsPacket *p, size_t add, void **ret, size_t *start) {
211 assert(p);
212
213 if (p->size + add > p->allocated) {
214 size_t a;
215
216 a = PAGE_ALIGN((p->size + add) * 2);
217 if (a > DNS_PACKET_SIZE_MAX)
218 a = DNS_PACKET_SIZE_MAX;
219
220 if (p->size + add > a)
221 return -EMSGSIZE;
222
223 if (p->_data) {
224 void *d;
225
226 d = realloc(p->_data, a);
227 if (!d)
228 return -ENOMEM;
229
230 p->_data = d;
231 } else {
232 p->_data = malloc(a);
233 if (!p->_data)
234 return -ENOMEM;
235
236 memcpy(p->_data, (uint8_t*) p + ALIGN(sizeof(DnsPacket)), p->size);
237 memzero((uint8_t*) p->_data + p->size, a - p->size);
238 }
239
240 p->allocated = a;
241 }
242
243 if (start)
244 *start = p->size;
245
246 if (ret)
247 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->size;
248
249 p->size += add;
250 return 0;
251 }
252
253 static void dns_packet_truncate(DnsPacket *p, size_t sz) {
254 Iterator i;
255 char *s;
256 void *n;
257
258 assert(p);
259
260 if (p->size <= sz)
261 return;
262
263 HASHMAP_FOREACH_KEY(s, n, p->names, i) {
264
265 if (PTR_TO_SIZE(n) < sz)
266 continue;
267
268 hashmap_remove(p->names, s);
269 free(s);
270 }
271
272 p->size = sz;
273 }
274
275 int dns_packet_append_blob(DnsPacket *p, const void *d, size_t l, size_t *start) {
276 void *q;
277 int r;
278
279 assert(p);
280
281 r = dns_packet_extend(p, l, &q, start);
282 if (r < 0)
283 return r;
284
285 memcpy(q, d, l);
286 return 0;
287 }
288
289 int dns_packet_append_uint8(DnsPacket *p, uint8_t v, size_t *start) {
290 void *d;
291 int r;
292
293 assert(p);
294
295 r = dns_packet_extend(p, sizeof(uint8_t), &d, start);
296 if (r < 0)
297 return r;
298
299 ((uint8_t*) d)[0] = v;
300
301 return 0;
302 }
303
304 int dns_packet_append_uint16(DnsPacket *p, uint16_t v, size_t *start) {
305 void *d;
306 int r;
307
308 assert(p);
309
310 r = dns_packet_extend(p, sizeof(uint16_t), &d, start);
311 if (r < 0)
312 return r;
313
314 ((uint8_t*) d)[0] = (uint8_t) (v >> 8);
315 ((uint8_t*) d)[1] = (uint8_t) v;
316
317 return 0;
318 }
319
320 int dns_packet_append_uint32(DnsPacket *p, uint32_t v, size_t *start) {
321 void *d;
322 int r;
323
324 assert(p);
325
326 r = dns_packet_extend(p, sizeof(uint32_t), &d, start);
327 if (r < 0)
328 return r;
329
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;
334
335 return 0;
336 }
337
338 int dns_packet_append_string(DnsPacket *p, const char *s, size_t *start) {
339 void *d;
340 size_t l;
341 int r;
342
343 assert(p);
344 assert(s);
345
346 l = strlen(s);
347 if (l > 255)
348 return -E2BIG;
349
350 r = dns_packet_extend(p, 1 + l, &d, start);
351 if (r < 0)
352 return r;
353
354 ((uint8_t*) d)[0] = (uint8_t) l;
355 memcpy(((uint8_t*) d) + 1, s, l);
356
357 return 0;
358 }
359
360 int dns_packet_append_label(DnsPacket *p, const char *d, size_t l, size_t *start) {
361 void *w;
362 int r;
363
364 assert(p);
365 assert(d);
366
367 if (l > DNS_LABEL_MAX)
368 return -E2BIG;
369
370 r = dns_packet_extend(p, 1 + l, &w, start);
371 if (r < 0)
372 return r;
373
374 ((uint8_t*) w)[0] = (uint8_t) l;
375 memcpy(((uint8_t*) w) + 1, d, l);
376
377 return 0;
378 }
379
380 int dns_packet_append_name(DnsPacket *p, const char *name, size_t *start) {
381 size_t saved_size;
382 int r;
383
384 assert(p);
385 assert(name);
386
387 saved_size = p->size;
388
389 while (*name) {
390 _cleanup_free_ char *s = NULL;
391 char label[DNS_LABEL_MAX];
392 size_t n;
393 int k;
394
395 n = PTR_TO_SIZE(hashmap_get(p->names, name));
396 if (n > 0) {
397 assert(n < p->size);
398
399 if (n < 0x4000) {
400 r = dns_packet_append_uint16(p, 0xC000 | n, NULL);
401 if (r < 0)
402 goto fail;
403
404 goto done;
405 }
406 }
407
408 s = strdup(name);
409 if (!s) {
410 r = -ENOMEM;
411 goto fail;
412 }
413
414 r = dns_label_unescape(&name, label, sizeof(label));
415 if (r < 0)
416 goto fail;
417
418 if (p->protocol == DNS_PROTOCOL_DNS)
419 k = dns_label_apply_idna(label, r, label, sizeof(label));
420 else
421 k = dns_label_undo_idna(label, r, label, sizeof(label));
422 if (k < 0) {
423 r = k;
424 goto fail;
425 }
426 if (k > 0)
427 r = k;
428
429 r = dns_packet_append_label(p, label, r, &n);
430 if (r < 0)
431 goto fail;
432
433 r = hashmap_ensure_allocated(&p->names, dns_name_hash_func, dns_name_compare_func);
434 if (r < 0)
435 goto fail;
436
437 r = hashmap_put(p->names, s, SIZE_TO_PTR(n));
438 if (r < 0)
439 goto fail;
440
441 s = NULL;
442 }
443
444 r = dns_packet_append_uint8(p, 0, NULL);
445 if (r < 0)
446 return r;
447
448 done:
449 if (start)
450 *start = saved_size;
451
452 return 0;
453
454 fail:
455 dns_packet_truncate(p, saved_size);
456 return r;
457 }
458
459 int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *k, size_t *start) {
460 size_t saved_size;
461 int r;
462
463 assert(p);
464 assert(k);
465
466 saved_size = p->size;
467
468 r = dns_packet_append_name(p, DNS_RESOURCE_KEY_NAME(k), NULL);
469 if (r < 0)
470 goto fail;
471
472 r = dns_packet_append_uint16(p, k->type, NULL);
473 if (r < 0)
474 goto fail;
475
476 r = dns_packet_append_uint16(p, k->class, NULL);
477 if (r < 0)
478 goto fail;
479
480 if (start)
481 *start = saved_size;
482
483 return 0;
484
485 fail:
486 dns_packet_truncate(p, saved_size);
487 return r;
488 }
489
490 int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start) {
491 size_t saved_size, rdlength_offset, end, rdlength;
492 int r;
493
494 assert(p);
495 assert(rr);
496
497 saved_size = p->size;
498
499 r = dns_packet_append_key(p, rr->key, NULL);
500 if (r < 0)
501 goto fail;
502
503 r = dns_packet_append_uint32(p, rr->ttl, NULL);
504 if (r < 0)
505 goto fail;
506
507 /* Initially we write 0 here */
508 r = dns_packet_append_uint16(p, 0, &rdlength_offset);
509 if (r < 0)
510 goto fail;
511
512 switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
513
514 case DNS_TYPE_SRV:
515 r = dns_packet_append_uint16(p, rr->srv.priority, NULL);
516 if (r < 0)
517 goto fail;
518
519 r = dns_packet_append_uint16(p, rr->srv.weight, NULL);
520 if (r < 0)
521 goto fail;
522
523 r = dns_packet_append_uint16(p, rr->srv.port, NULL);
524 if (r < 0)
525 goto fail;
526
527 r = dns_packet_append_name(p, rr->srv.name, NULL);
528 break;
529
530 case DNS_TYPE_PTR:
531 case DNS_TYPE_NS:
532 case DNS_TYPE_CNAME:
533 case DNS_TYPE_DNAME:
534 r = dns_packet_append_name(p, rr->ptr.name, NULL);
535 break;
536
537 case DNS_TYPE_HINFO:
538 r = dns_packet_append_string(p, rr->hinfo.cpu, NULL);
539 if (r < 0)
540 goto fail;
541
542 r = dns_packet_append_string(p, rr->hinfo.os, NULL);
543 break;
544
545 case DNS_TYPE_SPF: /* exactly the same as TXT */
546 case DNS_TYPE_TXT: {
547 char **s;
548
549 STRV_FOREACH(s, rr->txt.strings) {
550 r = dns_packet_append_string(p, *s, NULL);
551 if (r < 0)
552 goto fail;
553 }
554
555 r = 0;
556 break;
557 }
558
559 case DNS_TYPE_A:
560 r = dns_packet_append_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
561 break;
562
563 case DNS_TYPE_AAAA:
564 r = dns_packet_append_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
565 break;
566
567 case DNS_TYPE_SOA:
568 r = dns_packet_append_name(p, rr->soa.mname, NULL);
569 if (r < 0)
570 goto fail;
571
572 r = dns_packet_append_name(p, rr->soa.rname, NULL);
573 if (r < 0)
574 goto fail;
575
576 r = dns_packet_append_uint32(p, rr->soa.serial, NULL);
577 if (r < 0)
578 goto fail;
579
580 r = dns_packet_append_uint32(p, rr->soa.refresh, NULL);
581 if (r < 0)
582 goto fail;
583
584 r = dns_packet_append_uint32(p, rr->soa.retry, NULL);
585 if (r < 0)
586 goto fail;
587
588 r = dns_packet_append_uint32(p, rr->soa.expire, NULL);
589 if (r < 0)
590 goto fail;
591
592 r = dns_packet_append_uint32(p, rr->soa.minimum, NULL);
593 break;
594
595 case DNS_TYPE_MX:
596 r = dns_packet_append_uint16(p, rr->mx.priority, NULL);
597 if (r < 0)
598 goto fail;
599
600 r = dns_packet_append_name(p, rr->mx.exchange, NULL);
601 break;
602
603 case DNS_TYPE_LOC:
604 r = dns_packet_append_uint8(p, rr->loc.version, NULL);
605 if (r < 0)
606 goto fail;
607
608 r = dns_packet_append_uint8(p, rr->loc.size, NULL);
609 if (r < 0)
610 goto fail;
611
612 r = dns_packet_append_uint8(p, rr->loc.horiz_pre, NULL);
613 if (r < 0)
614 goto fail;
615
616 r = dns_packet_append_uint8(p, rr->loc.vert_pre, NULL);
617 if (r < 0)
618 goto fail;
619
620 r = dns_packet_append_uint32(p, rr->loc.latitude, NULL);
621 if (r < 0)
622 goto fail;
623
624 r = dns_packet_append_uint32(p, rr->loc.longitude, NULL);
625 if (r < 0)
626 goto fail;
627
628 r = dns_packet_append_uint32(p, rr->loc.altitude, NULL);
629 break;
630
631 case DNS_TYPE_SSHFP:
632 r = dns_packet_append_uint8(p, rr->sshfp.algorithm, NULL);
633 if (r < 0)
634 goto fail;
635
636 r = dns_packet_append_uint8(p, rr->sshfp.fptype, NULL);
637 if (r < 0)
638 goto fail;
639
640 r = dns_packet_append_blob(p, rr->sshfp.key, rr->sshfp.key_size, NULL);
641 break;
642
643 case DNS_TYPE_DNSKEY:
644 r = dns_packet_append_uint16(p, dnskey_to_flags(rr), NULL);
645 if (r < 0)
646 goto fail;
647
648 r = dns_packet_append_uint8(p, 3u, NULL);
649 if (r < 0)
650 goto fail;
651
652 r = dns_packet_append_uint8(p, rr->dnskey.algorithm, NULL);
653 if (r < 0)
654 goto fail;
655
656 r = dns_packet_append_blob(p, rr->dnskey.key, rr->dnskey.key_size, NULL);
657 break;
658
659 case _DNS_TYPE_INVALID: /* unparseable */
660 default:
661
662 r = dns_packet_append_blob(p, rr->generic.data, rr->generic.size, NULL);
663 break;
664 }
665 if (r < 0)
666 goto fail;
667
668 /* Let's calculate the actual data size and update the field */
669 rdlength = p->size - rdlength_offset - sizeof(uint16_t);
670 if (rdlength > 0xFFFF) {
671 r = ENOSPC;
672 goto fail;
673 }
674
675 end = p->size;
676 p->size = rdlength_offset;
677 r = dns_packet_append_uint16(p, rdlength, NULL);
678 if (r < 0)
679 goto fail;
680 p->size = end;
681
682 if (start)
683 *start = saved_size;
684
685 return 0;
686
687 fail:
688 dns_packet_truncate(p, saved_size);
689 return r;
690 }
691
692
693 int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) {
694 assert(p);
695
696 if (p->rindex + sz > p->size)
697 return -EMSGSIZE;
698
699 if (ret)
700 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->rindex;
701
702 if (start)
703 *start = p->rindex;
704
705 p->rindex += sz;
706 return 0;
707 }
708
709 void dns_packet_rewind(DnsPacket *p, size_t idx) {
710 assert(p);
711 assert(idx <= p->size);
712 assert(idx >= DNS_PACKET_HEADER_SIZE);
713
714 p->rindex = idx;
715 }
716
717 int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start) {
718 const void *q;
719 int r;
720
721 assert(p);
722 assert(d);
723
724 r = dns_packet_read(p, sz, &q, start);
725 if (r < 0)
726 return r;
727
728 memcpy(d, q, sz);
729 return 0;
730 }
731
732 int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) {
733 const void *d;
734 int r;
735
736 assert(p);
737
738 r = dns_packet_read(p, sizeof(uint8_t), &d, start);
739 if (r < 0)
740 return r;
741
742 *ret = ((uint8_t*) d)[0];
743 return 0;
744 }
745
746 int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start) {
747 const void *d;
748 int r;
749
750 assert(p);
751
752 r = dns_packet_read(p, sizeof(uint16_t), &d, start);
753 if (r < 0)
754 return r;
755
756 *ret = (((uint16_t) ((uint8_t*) d)[0]) << 8) |
757 ((uint16_t) ((uint8_t*) d)[1]);
758 return 0;
759 }
760
761 int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start) {
762 const void *d;
763 int r;
764
765 assert(p);
766
767 r = dns_packet_read(p, sizeof(uint32_t), &d, start);
768 if (r < 0)
769 return r;
770
771 *ret = (((uint32_t) ((uint8_t*) d)[0]) << 24) |
772 (((uint32_t) ((uint8_t*) d)[1]) << 16) |
773 (((uint32_t) ((uint8_t*) d)[2]) << 8) |
774 ((uint32_t) ((uint8_t*) d)[3]);
775
776 return 0;
777 }
778
779 int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start) {
780 size_t saved_rindex;
781 const void *d;
782 char *t;
783 uint8_t c;
784 int r;
785
786 assert(p);
787
788 saved_rindex = p->rindex;
789
790 r = dns_packet_read_uint8(p, &c, NULL);
791 if (r < 0)
792 goto fail;
793
794 r = dns_packet_read(p, c, &d, NULL);
795 if (r < 0)
796 goto fail;
797
798 if (memchr(d, 0, c)) {
799 r = -EBADMSG;
800 goto fail;
801 }
802
803 t = strndup(d, c);
804 if (!t) {
805 r = -ENOMEM;
806 goto fail;
807 }
808
809 if (!utf8_is_valid(t)) {
810 free(t);
811 r = -EBADMSG;
812 goto fail;
813 }
814
815 *ret = t;
816
817 if (start)
818 *start = saved_rindex;
819
820 return 0;
821
822 fail:
823 dns_packet_rewind(p, saved_rindex);
824 return r;
825 }
826
827 int dns_packet_read_name(DnsPacket *p, char **_ret, size_t *start) {
828 size_t saved_rindex, after_rindex = 0;
829 _cleanup_free_ char *ret = NULL;
830 size_t n = 0, allocated = 0;
831 bool first = true;
832 int r;
833
834 assert(p);
835 assert(_ret);
836
837 saved_rindex = p->rindex;
838
839 for (;;) {
840 uint8_t c, d;
841
842 r = dns_packet_read_uint8(p, &c, NULL);
843 if (r < 0)
844 goto fail;
845
846 if (c == 0)
847 /* End of name */
848 break;
849 else if (c <= 63) {
850 _cleanup_free_ char *t = NULL;
851 const char *label;
852
853 /* Literal label */
854 r = dns_packet_read(p, c, (const void**) &label, NULL);
855 if (r < 0)
856 goto fail;
857
858 r = dns_label_escape(label, c, &t);
859 if (r < 0)
860 goto fail;
861
862 if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1)) {
863 r = -ENOMEM;
864 goto fail;
865 }
866
867 if (!first)
868 ret[n++] = '.';
869 else
870 first = false;
871
872 memcpy(ret + n, t, r);
873 n += r;
874 continue;
875 } else if ((c & 0xc0) == 0xc0) {
876 uint16_t ptr;
877
878 /* Pointer */
879 r = dns_packet_read_uint8(p, &d, NULL);
880 if (r < 0)
881 goto fail;
882
883 ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
884 if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= saved_rindex) {
885 r = -EBADMSG;
886 goto fail;
887 }
888
889 if (after_rindex == 0)
890 after_rindex = p->rindex;
891
892 p->rindex = ptr;
893 } else
894 goto fail;
895 }
896
897 if (!GREEDY_REALLOC(ret, allocated, n + 1)) {
898 r = -ENOMEM;
899 goto fail;
900 }
901
902 ret[n] = 0;
903
904 if (after_rindex != 0)
905 p->rindex= after_rindex;
906
907 *_ret = ret;
908 ret = NULL;
909
910 if (start)
911 *start = saved_rindex;
912
913 return 0;
914
915 fail:
916 dns_packet_rewind(p, saved_rindex);
917 return r;
918 }
919
920 int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) {
921 _cleanup_free_ char *name = NULL;
922 uint16_t class, type;
923 DnsResourceKey *key;
924 size_t saved_rindex;
925 int r;
926
927 assert(p);
928 assert(ret);
929
930 saved_rindex = p->rindex;
931
932 r = dns_packet_read_name(p, &name, NULL);
933 if (r < 0)
934 goto fail;
935
936 r = dns_packet_read_uint16(p, &type, NULL);
937 if (r < 0)
938 goto fail;
939
940 r = dns_packet_read_uint16(p, &class, NULL);
941 if (r < 0)
942 goto fail;
943
944 key = dns_resource_key_new_consume(class, type, name);
945 if (!key) {
946 r = -ENOMEM;
947 goto fail;
948 }
949
950 name = NULL;
951 *ret = key;
952
953 if (start)
954 *start = saved_rindex;
955
956 return 0;
957 fail:
958 dns_packet_rewind(p, saved_rindex);
959 return r;
960 }
961
962 static int dns_packet_read_public_key(DnsPacket *p, size_t length,
963 void **dp, size_t *lengthp,
964 size_t *start) {
965 int r;
966 const void *d;
967 void *d2;
968
969 r = dns_packet_read(p, length, &d, NULL);
970 if (r < 0)
971 return r;
972
973 d2 = memdup(d, length);
974 if (!d2)
975 return -ENOMEM;
976
977 *dp = d2;
978 *lengthp = length;
979 return 0;
980 }
981
982 static bool loc_size_ok(uint8_t size) {
983 uint8_t m = size >> 4, e = size & 0xF;
984
985 return m <= 9 && e <= 9 && (m > 0 || e == 0);
986 }
987
988 static int dnskey_parse_flags(DnsResourceRecord *rr, uint16_t flags) {
989 if (flags & ~(DNSKEY_FLAG_SEP | DNSKEY_FLAG_ZONE_KEY))
990 return -EBADMSG;
991
992 rr->dnskey.zone_key_flag = flags & DNSKEY_FLAG_ZONE_KEY;
993 rr->dnskey.sep_flag = flags & DNSKEY_FLAG_SEP;
994 return 0;
995 }
996
997 int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
998 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
999 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
1000 size_t saved_rindex, offset;
1001 uint16_t rdlength;
1002 const void *d;
1003 int r;
1004
1005 assert(p);
1006 assert(ret);
1007
1008 saved_rindex = p->rindex;
1009
1010 r = dns_packet_read_key(p, &key, NULL);
1011 if (r < 0)
1012 goto fail;
1013
1014 if (key->class == DNS_CLASS_ANY ||
1015 key->type == DNS_TYPE_ANY) {
1016 r = -EBADMSG;
1017 goto fail;
1018 }
1019
1020 rr = dns_resource_record_new(key);
1021 if (!rr) {
1022 r = -ENOMEM;
1023 goto fail;
1024 }
1025
1026 r = dns_packet_read_uint32(p, &rr->ttl, NULL);
1027 if (r < 0)
1028 goto fail;
1029
1030 r = dns_packet_read_uint16(p, &rdlength, NULL);
1031 if (r < 0)
1032 goto fail;
1033
1034 if (p->rindex + rdlength > p->size) {
1035 r = -EBADMSG;
1036 goto fail;
1037 }
1038
1039 offset = p->rindex;
1040
1041 switch (rr->key->type) {
1042
1043 case DNS_TYPE_SRV:
1044 r = dns_packet_read_uint16(p, &rr->srv.priority, NULL);
1045 if (r < 0)
1046 goto fail;
1047 r = dns_packet_read_uint16(p, &rr->srv.weight, NULL);
1048 if (r < 0)
1049 goto fail;
1050 r = dns_packet_read_uint16(p, &rr->srv.port, NULL);
1051 if (r < 0)
1052 goto fail;
1053 r = dns_packet_read_name(p, &rr->srv.name, NULL);
1054 break;
1055
1056 case DNS_TYPE_PTR:
1057 case DNS_TYPE_NS:
1058 case DNS_TYPE_CNAME:
1059 case DNS_TYPE_DNAME:
1060 r = dns_packet_read_name(p, &rr->ptr.name, NULL);
1061 break;
1062
1063 case DNS_TYPE_HINFO:
1064 r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL);
1065 if (r < 0)
1066 goto fail;
1067
1068 r = dns_packet_read_string(p, &rr->hinfo.os, NULL);
1069 break;
1070
1071 case DNS_TYPE_SPF: /* exactly the same as TXT */
1072 case DNS_TYPE_TXT: {
1073 char *s;
1074
1075 while (p->rindex < offset + rdlength) {
1076 r = dns_packet_read_string(p, &s, NULL);
1077 if (r < 0)
1078 goto fail;
1079
1080 r = strv_consume(&rr->txt.strings, s);
1081 if (r < 0)
1082 goto fail;
1083 }
1084
1085 r = 0;
1086 break;
1087 }
1088
1089 case DNS_TYPE_A:
1090 r = dns_packet_read_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
1091 break;
1092
1093 case DNS_TYPE_AAAA:
1094 r = dns_packet_read_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
1095 break;
1096
1097 case DNS_TYPE_SOA:
1098 r = dns_packet_read_name(p, &rr->soa.mname, NULL);
1099 if (r < 0)
1100 goto fail;
1101
1102 r = dns_packet_read_name(p, &rr->soa.rname, NULL);
1103 if (r < 0)
1104 goto fail;
1105
1106 r = dns_packet_read_uint32(p, &rr->soa.serial, NULL);
1107 if (r < 0)
1108 goto fail;
1109
1110 r = dns_packet_read_uint32(p, &rr->soa.refresh, NULL);
1111 if (r < 0)
1112 goto fail;
1113
1114 r = dns_packet_read_uint32(p, &rr->soa.retry, NULL);
1115 if (r < 0)
1116 goto fail;
1117
1118 r = dns_packet_read_uint32(p, &rr->soa.expire, NULL);
1119 if (r < 0)
1120 goto fail;
1121
1122 r = dns_packet_read_uint32(p, &rr->soa.minimum, NULL);
1123 break;
1124
1125 case DNS_TYPE_MX:
1126 r = dns_packet_read_uint16(p, &rr->mx.priority, NULL);
1127 if (r < 0)
1128 goto fail;
1129
1130 r = dns_packet_read_name(p, &rr->mx.exchange, NULL);
1131 break;
1132
1133 case DNS_TYPE_LOC: {
1134 uint8_t t;
1135 size_t pos;
1136
1137 r = dns_packet_read_uint8(p, &t, &pos);
1138 if (r < 0)
1139 goto fail;
1140
1141 if (t == 0) {
1142 rr->loc.version = t;
1143
1144 r = dns_packet_read_uint8(p, &rr->loc.size, NULL);
1145 if (r < 0)
1146 goto fail;
1147
1148 if (!loc_size_ok(rr->loc.size)) {
1149 r = -EBADMSG;
1150 goto fail;
1151 }
1152
1153 r = dns_packet_read_uint8(p, &rr->loc.horiz_pre, NULL);
1154 if (r < 0)
1155 goto fail;
1156
1157 if (!loc_size_ok(rr->loc.horiz_pre)) {
1158 r = -EBADMSG;
1159 goto fail;
1160 }
1161
1162 r = dns_packet_read_uint8(p, &rr->loc.vert_pre, NULL);
1163 if (r < 0)
1164 goto fail;
1165
1166 if (!loc_size_ok(rr->loc.vert_pre)) {
1167 r = -EBADMSG;
1168 goto fail;
1169 }
1170
1171 r = dns_packet_read_uint32(p, &rr->loc.latitude, NULL);
1172 if (r < 0)
1173 goto fail;
1174
1175 r = dns_packet_read_uint32(p, &rr->loc.longitude, NULL);
1176 if (r < 0)
1177 goto fail;
1178
1179 r = dns_packet_read_uint32(p, &rr->loc.altitude, NULL);
1180 if (r < 0)
1181 goto fail;
1182
1183 break;
1184 } else {
1185 dns_packet_rewind(p, pos);
1186 rr->unparseable = true;
1187 goto unparseable;
1188 }
1189 }
1190
1191 case DNS_TYPE_SSHFP:
1192 r = dns_packet_read_uint8(p, &rr->sshfp.algorithm, NULL);
1193 if (r < 0)
1194 goto fail;
1195
1196 r = dns_packet_read_uint8(p, &rr->sshfp.fptype, NULL);
1197 if (r < 0)
1198 goto fail;
1199
1200 r = dns_packet_read_public_key(p, rdlength - 2,
1201 &rr->sshfp.key, &rr->sshfp.key_size,
1202 NULL);
1203 break;
1204
1205 case DNS_TYPE_DNSKEY: {
1206 uint16_t flags;
1207 uint8_t proto;
1208
1209 r = dns_packet_read_uint16(p, &flags, NULL);
1210 if (r < 0)
1211 goto fail;
1212
1213 r = dnskey_parse_flags(rr, flags);
1214 if (r < 0)
1215 goto fail;
1216
1217 r = dns_packet_read_uint8(p, &proto, NULL);
1218 if (r < 0)
1219 goto fail;
1220
1221 /* protocol is required to be always 3 */
1222 if (proto != 3) {
1223 r = -EBADMSG;
1224 goto fail;
1225 }
1226
1227 r = dns_packet_read_uint8(p, &rr->dnskey.algorithm, NULL);
1228 if (r < 0)
1229 goto fail;
1230
1231 r = dns_packet_read_public_key(p, rdlength - 4,
1232 &rr->dnskey.key, &rr->dnskey.key_size,
1233 NULL);
1234 break;
1235 }
1236
1237 default:
1238 unparseable:
1239 r = dns_packet_read(p, rdlength, &d, NULL);
1240 if (r < 0)
1241 goto fail;
1242
1243 rr->generic.data = memdup(d, rdlength);
1244 if (!rr->generic.data) {
1245 r = -ENOMEM;
1246 goto fail;
1247 }
1248
1249 rr->generic.size = rdlength;
1250 break;
1251 }
1252 if (r < 0)
1253 goto fail;
1254 if (p->rindex != offset + rdlength) {
1255 r = -EBADMSG;
1256 goto fail;
1257 }
1258
1259 *ret = rr;
1260 rr = NULL;
1261
1262 if (start)
1263 *start = saved_rindex;
1264
1265 return 0;
1266 fail:
1267 dns_packet_rewind(p, saved_rindex);
1268 return r;
1269 }
1270
1271 int dns_packet_extract(DnsPacket *p) {
1272 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
1273 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
1274 size_t saved_rindex;
1275 unsigned n, i;
1276 int r;
1277
1278 saved_rindex = p->rindex;
1279 dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
1280
1281 n = DNS_PACKET_QDCOUNT(p);
1282 if (n > 0) {
1283 question = dns_question_new(n);
1284 if (!question) {
1285 r = -ENOMEM;
1286 goto finish;
1287 }
1288
1289 for (i = 0; i < n; i++) {
1290 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
1291
1292 r = dns_packet_read_key(p, &key, NULL);
1293 if (r < 0)
1294 goto finish;
1295
1296 r = dns_question_add(question, key);
1297 if (r < 0)
1298 goto finish;
1299 }
1300 }
1301
1302 n = DNS_PACKET_RRCOUNT(p);
1303 if (n > 0) {
1304 answer = dns_answer_new(n);
1305 if (!answer) {
1306 r = -ENOMEM;
1307 goto finish;
1308 }
1309
1310 for (i = 0; i < n; i++) {
1311 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
1312
1313 r = dns_packet_read_rr(p, &rr, NULL);
1314 if (r < 0)
1315 goto finish;
1316
1317 r = dns_answer_add(answer, rr);
1318 if (r < 0)
1319 goto finish;
1320 }
1321 }
1322
1323 p->question = question;
1324 question = NULL;
1325
1326 p->answer = answer;
1327 answer = NULL;
1328
1329 r = 0;
1330
1331 finish:
1332 p->rindex = saved_rindex;
1333 return r;
1334 }
1335
1336 static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
1337 [DNS_RCODE_SUCCESS] = "SUCCESS",
1338 [DNS_RCODE_FORMERR] = "FORMERR",
1339 [DNS_RCODE_SERVFAIL] = "SERVFAIL",
1340 [DNS_RCODE_NXDOMAIN] = "NXDOMAIN",
1341 [DNS_RCODE_NOTIMP] = "NOTIMP",
1342 [DNS_RCODE_REFUSED] = "REFUSED",
1343 [DNS_RCODE_YXDOMAIN] = "YXDOMAIN",
1344 [DNS_RCODE_YXRRSET] = "YRRSET",
1345 [DNS_RCODE_NXRRSET] = "NXRRSET",
1346 [DNS_RCODE_NOTAUTH] = "NOTAUTH",
1347 [DNS_RCODE_NOTZONE] = "NOTZONE",
1348 [DNS_RCODE_BADVERS] = "BADVERS",
1349 [DNS_RCODE_BADKEY] = "BADKEY",
1350 [DNS_RCODE_BADTIME] = "BADTIME",
1351 [DNS_RCODE_BADMODE] = "BADMODE",
1352 [DNS_RCODE_BADNAME] = "BADNAME",
1353 [DNS_RCODE_BADALG] = "BADALG",
1354 [DNS_RCODE_BADTRUNC] = "BADTRUNC",
1355 };
1356 DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int);
1357
1358 static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = {
1359 [DNS_PROTOCOL_DNS] = "dns",
1360 [DNS_PROTOCOL_MDNS] = "mdns",
1361 [DNS_PROTOCOL_LLMNR] = "llmnr",
1362 };
1363 DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);