]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-dns-packet.c
resolved: set LLMNR TCP and UDP TTLs to the values suggested by the RFC
[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_LLMNR)
76 h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
77 0 /* opcode */,
78 0 /* c */,
79 0 /* tc */,
80 0 /* t */,
81 0 /* ra */,
82 0 /* ad */,
83 0 /* cd */,
84 0 /* rcode */));
85 else
86 h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
87 0 /* opcode */,
88 0 /* aa */,
89 0 /* tc */,
90 1 /* rd (ask for recursion) */,
91 0 /* ra */,
92 0 /* ad */,
93 0 /* cd */,
94 0 /* rcode */));
95
96 *ret = p;
97 return 0;
98 }
99
100 DnsPacket *dns_packet_ref(DnsPacket *p) {
101
102 if (!p)
103 return NULL;
104
105 assert(p->n_ref > 0);
106 p->n_ref++;
107 return p;
108 }
109
110 static void dns_packet_free(DnsPacket *p) {
111 char *s;
112
113 assert(p);
114
115 dns_question_unref(p->question);
116 dns_answer_unref(p->answer);
117
118 while ((s = hashmap_steal_first_key(p->names)))
119 free(s);
120 hashmap_free(p->names);
121
122 free(p->_data);
123 free(p);
124 }
125
126 DnsPacket *dns_packet_unref(DnsPacket *p) {
127 if (!p)
128 return NULL;
129
130 assert(p->n_ref > 0);
131
132 if (p->n_ref == 1)
133 dns_packet_free(p);
134 else
135 p->n_ref--;
136
137 return NULL;
138 }
139
140 int dns_packet_validate(DnsPacket *p) {
141 assert(p);
142
143 if (p->size < DNS_PACKET_HEADER_SIZE)
144 return -EBADMSG;
145
146 if (p->size > DNS_PACKET_SIZE_MAX)
147 return -EBADMSG;
148
149 return 1;
150 }
151
152 int dns_packet_validate_reply(DnsPacket *p) {
153 int r;
154
155 assert(p);
156
157 r = dns_packet_validate(p);
158 if (r < 0)
159 return r;
160
161 if (DNS_PACKET_QR(p) != 1)
162 return 0;
163
164 if (DNS_PACKET_OPCODE(p) != 0)
165 return -EBADMSG;
166
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)
170 return -EBADMSG;
171
172 return 1;
173 }
174
175 int dns_packet_validate_query(DnsPacket *p) {
176 int r;
177
178 assert(p);
179
180 r = dns_packet_validate(p);
181 if (r < 0)
182 return r;
183
184 if (DNS_PACKET_QR(p) != 0)
185 return 0;
186
187 if (DNS_PACKET_OPCODE(p) != 0)
188 return -EBADMSG;
189
190 if (DNS_PACKET_TC(p))
191 return -EBADMSG;
192
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)
196 return -EBADMSG;
197
198 /* RFC 4795, Section 2.1.1. says to discard all queries with ANCOUNT != 0 */
199 if (DNS_PACKET_ANCOUNT(p) > 0)
200 return -EBADMSG;
201
202 /* RFC 4795, Section 2.1.1. says to discard all queries with NSCOUNT != 0 */
203 if (DNS_PACKET_NSCOUNT(p) > 0)
204 return -EBADMSG;
205
206 return 1;
207 }
208
209 static int dns_packet_extend(DnsPacket *p, size_t add, void **ret, size_t *start) {
210 assert(p);
211
212 if (p->size + add > p->allocated) {
213 size_t a;
214
215 a = PAGE_ALIGN((p->size + add) * 2);
216 if (a > DNS_PACKET_SIZE_MAX)
217 a = DNS_PACKET_SIZE_MAX;
218
219 if (p->size + add > a)
220 return -EMSGSIZE;
221
222 if (p->_data) {
223 void *d;
224
225 d = realloc(p->_data, a);
226 if (!d)
227 return -ENOMEM;
228
229 p->_data = d;
230 } else {
231 p->_data = malloc(a);
232 if (!p->_data)
233 return -ENOMEM;
234
235 memcpy(p->_data, (uint8_t*) p + ALIGN(sizeof(DnsPacket)), p->size);
236 memzero((uint8_t*) p->_data + p->size, a - p->size);
237 }
238
239 p->allocated = a;
240 }
241
242 if (start)
243 *start = p->size;
244
245 if (ret)
246 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->size;
247
248 p->size += add;
249 return 0;
250 }
251
252 static void dns_packet_truncate(DnsPacket *p, size_t sz) {
253 Iterator i;
254 char *s;
255 void *n;
256
257 assert(p);
258
259 if (p->size <= sz)
260 return;
261
262 HASHMAP_FOREACH_KEY(s, n, p->names, i) {
263
264 if (PTR_TO_SIZE(n) < sz)
265 continue;
266
267 hashmap_remove(p->names, s);
268 free(s);
269 }
270
271 p->size = sz;
272 }
273
274 int dns_packet_append_blob(DnsPacket *p, const void *d, size_t l, size_t *start) {
275 void *q;
276 int r;
277
278 assert(p);
279
280 r = dns_packet_extend(p, l, &q, start);
281 if (r < 0)
282 return r;
283
284 memcpy(q, d, l);
285 return 0;
286 }
287
288 int dns_packet_append_uint8(DnsPacket *p, uint8_t v, size_t *start) {
289 void *d;
290 int r;
291
292 assert(p);
293
294 r = dns_packet_extend(p, sizeof(uint8_t), &d, start);
295 if (r < 0)
296 return r;
297
298 ((uint8_t*) d)[0] = v;
299
300 return 0;
301 }
302
303 int dns_packet_append_uint16(DnsPacket *p, uint16_t v, size_t *start) {
304 void *d;
305 int r;
306
307 assert(p);
308
309 r = dns_packet_extend(p, sizeof(uint16_t), &d, start);
310 if (r < 0)
311 return r;
312
313 ((uint8_t*) d)[0] = (uint8_t) (v >> 8);
314 ((uint8_t*) d)[1] = (uint8_t) v;
315
316 return 0;
317 }
318
319 int dns_packet_append_uint32(DnsPacket *p, uint32_t v, size_t *start) {
320 void *d;
321 int r;
322
323 assert(p);
324
325 r = dns_packet_extend(p, sizeof(uint32_t), &d, start);
326 if (r < 0)
327 return r;
328
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;
333
334 return 0;
335 }
336
337 int dns_packet_append_string(DnsPacket *p, const char *s, size_t *start) {
338 void *d;
339 size_t l;
340 int r;
341
342 assert(p);
343 assert(s);
344
345 l = strlen(s);
346 if (l > 255)
347 return -E2BIG;
348
349 r = dns_packet_extend(p, 1 + l, &d, start);
350 if (r < 0)
351 return r;
352
353 ((uint8_t*) d)[0] = (uint8_t) l;
354 memcpy(((uint8_t*) d) + 1, s, l);
355
356 return 0;
357 }
358
359 int dns_packet_append_label(DnsPacket *p, const char *d, size_t l, size_t *start) {
360 void *w;
361 int r;
362
363 assert(p);
364 assert(d);
365
366 if (l > DNS_LABEL_MAX)
367 return -E2BIG;
368
369 r = dns_packet_extend(p, 1 + l, &w, start);
370 if (r < 0)
371 return r;
372
373 ((uint8_t*) w)[0] = (uint8_t) l;
374 memcpy(((uint8_t*) w) + 1, d, l);
375
376 return 0;
377 }
378
379 int dns_packet_append_name(DnsPacket *p, const char *name, size_t *start) {
380 size_t saved_size;
381 int r;
382
383 assert(p);
384 assert(name);
385
386 saved_size = p->size;
387
388 while (*name) {
389 _cleanup_free_ char *s = NULL;
390 char label[DNS_LABEL_MAX];
391 size_t n;
392
393 n = PTR_TO_SIZE(hashmap_get(p->names, name));
394 if (n > 0) {
395 assert(n < p->size);
396
397 if (n < 0x4000) {
398 r = dns_packet_append_uint16(p, 0xC000 | n, NULL);
399 if (r < 0)
400 goto fail;
401
402 goto done;
403 }
404 }
405
406 s = strdup(name);
407 if (!s) {
408 r = -ENOMEM;
409 goto fail;
410 }
411
412 r = dns_label_unescape(&name, label, sizeof(label));
413 if (r < 0)
414 goto fail;
415
416 r = dns_packet_append_label(p, label, r, &n);
417 if (r < 0)
418 goto fail;
419
420 r = hashmap_ensure_allocated(&p->names, dns_name_hash_func, dns_name_compare_func);
421 if (r < 0)
422 goto fail;
423
424 r = hashmap_put(p->names, s, SIZE_TO_PTR(n));
425 if (r < 0)
426 goto fail;
427
428 s = NULL;
429 }
430
431 r = dns_packet_append_uint8(p, 0, NULL);
432 if (r < 0)
433 return r;
434
435 done:
436 if (start)
437 *start = saved_size;
438
439 return 0;
440
441 fail:
442 dns_packet_truncate(p, saved_size);
443 return r;
444 }
445
446 int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *k, size_t *start) {
447 size_t saved_size;
448 int r;
449
450 assert(p);
451 assert(k);
452
453 saved_size = p->size;
454
455 r = dns_packet_append_name(p, DNS_RESOURCE_KEY_NAME(k), NULL);
456 if (r < 0)
457 goto fail;
458
459 r = dns_packet_append_uint16(p, k->type, NULL);
460 if (r < 0)
461 goto fail;
462
463 r = dns_packet_append_uint16(p, k->class, NULL);
464 if (r < 0)
465 goto fail;
466
467 if (start)
468 *start = saved_size;
469
470 return 0;
471
472 fail:
473 dns_packet_truncate(p, saved_size);
474 return r;
475 }
476
477 int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start) {
478 size_t saved_size, rdlength_offset, end, rdlength;
479 int r;
480
481 assert(p);
482 assert(rr);
483
484 saved_size = p->size;
485
486 r = dns_packet_append_key(p, rr->key, NULL);
487 if (r < 0)
488 goto fail;
489
490 r = dns_packet_append_uint32(p, rr->ttl, NULL);
491 if (r < 0)
492 goto fail;
493
494 /* Initially we write 0 here */
495 r = dns_packet_append_uint16(p, 0, &rdlength_offset);
496 if (r < 0)
497 goto fail;
498
499 switch (rr->key->type) {
500
501 case DNS_TYPE_PTR:
502 case DNS_TYPE_NS:
503 case DNS_TYPE_CNAME:
504 r = dns_packet_append_name(p, rr->ptr.name, NULL);
505 break;
506
507 case DNS_TYPE_HINFO:
508 r = dns_packet_append_string(p, rr->hinfo.cpu, NULL);
509 if (r < 0)
510 goto fail;
511
512 r = dns_packet_append_string(p, rr->hinfo.os, NULL);
513 break;
514
515 case DNS_TYPE_A:
516 r = dns_packet_append_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
517 break;
518
519 case DNS_TYPE_AAAA:
520 r = dns_packet_append_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
521 break;
522
523 case DNS_TYPE_SOA:
524 r = dns_packet_append_name(p, rr->soa.mname, NULL);
525 if (r < 0)
526 goto fail;
527
528 r = dns_packet_append_name(p, rr->soa.rname, NULL);
529 if (r < 0)
530 goto fail;
531
532 r = dns_packet_append_uint32(p, rr->soa.serial, NULL);
533 if (r < 0)
534 goto fail;
535
536 r = dns_packet_append_uint32(p, rr->soa.refresh, NULL);
537 if (r < 0)
538 goto fail;
539
540 r = dns_packet_append_uint32(p, rr->soa.retry, NULL);
541 if (r < 0)
542 goto fail;
543
544 r = dns_packet_append_uint32(p, rr->soa.expire, NULL);
545 if (r < 0)
546 goto fail;
547
548 r = dns_packet_append_uint32(p, rr->soa.minimum, NULL);
549 break;
550
551 case DNS_TYPE_MX:
552 case DNS_TYPE_TXT:
553 case DNS_TYPE_SRV:
554 case DNS_TYPE_DNAME:
555 case DNS_TYPE_SSHFP:
556 default:
557 r = dns_packet_append_blob(p, rr->generic.data, rr->generic.size, NULL);
558 break;
559 }
560 if (r < 0)
561 goto fail;
562
563 /* Let's calculate the actual data size and update the field */
564 rdlength = p->size - rdlength_offset - sizeof(uint16_t);
565 if (rdlength > 0xFFFF) {
566 r = ENOSPC;
567 goto fail;
568 }
569
570 end = p->size;
571 p->size = rdlength_offset;
572 r = dns_packet_append_uint16(p, rdlength, NULL);
573 if (r < 0)
574 goto fail;
575 p->size = end;
576
577 return 0;
578
579 fail:
580 dns_packet_truncate(p, saved_size);
581 return r;
582 }
583
584
585 int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) {
586 assert(p);
587
588 if (p->rindex + sz > p->size)
589 return -EMSGSIZE;
590
591 if (ret)
592 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->rindex;
593
594 if (start)
595 *start = p->rindex;
596
597 p->rindex += sz;
598 return 0;
599 }
600
601 void dns_packet_rewind(DnsPacket *p, size_t idx) {
602 assert(p);
603 assert(idx <= p->size);
604 assert(idx >= DNS_PACKET_HEADER_SIZE);
605
606 p->rindex = idx;
607 }
608
609 int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start) {
610 const void *q;
611 int r;
612
613 assert(p);
614 assert(d);
615
616 r = dns_packet_read(p, sz, &q, start);
617 if (r < 0)
618 return r;
619
620 memcpy(d, q, sz);
621 return 0;
622 }
623
624 int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) {
625 const void *d;
626 int r;
627
628 assert(p);
629
630 r = dns_packet_read(p, sizeof(uint8_t), &d, start);
631 if (r < 0)
632 return r;
633
634 *ret = ((uint8_t*) d)[0];
635 return 0;
636 }
637
638 int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start) {
639 const void *d;
640 int r;
641
642 assert(p);
643
644 r = dns_packet_read(p, sizeof(uint16_t), &d, start);
645 if (r < 0)
646 return r;
647
648 *ret = (((uint16_t) ((uint8_t*) d)[0]) << 8) |
649 ((uint16_t) ((uint8_t*) d)[1]);
650 return 0;
651 }
652
653 int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start) {
654 const void *d;
655 int r;
656
657 assert(p);
658
659 r = dns_packet_read(p, sizeof(uint32_t), &d, start);
660 if (r < 0)
661 return r;
662
663 *ret = (((uint32_t) ((uint8_t*) d)[0]) << 24) |
664 (((uint32_t) ((uint8_t*) d)[1]) << 16) |
665 (((uint32_t) ((uint8_t*) d)[2]) << 8) |
666 ((uint32_t) ((uint8_t*) d)[3]);
667
668 return 0;
669 }
670
671 int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start) {
672 size_t saved_rindex;
673 const void *d;
674 char *t;
675 uint8_t c;
676 int r;
677
678 assert(p);
679
680 saved_rindex = p->rindex;
681
682 r = dns_packet_read_uint8(p, &c, NULL);
683 if (r < 0)
684 goto fail;
685
686 r = dns_packet_read(p, c, &d, NULL);
687 if (r < 0)
688 goto fail;
689
690 if (memchr(d, 0, c)) {
691 r = -EBADMSG;
692 goto fail;
693 }
694
695 t = strndup(d, c);
696 if (!t) {
697 r = -ENOMEM;
698 goto fail;
699 }
700
701 if (!utf8_is_valid(t)) {
702 free(t);
703 r = -EBADMSG;
704 goto fail;
705 }
706
707 *ret = t;
708
709 if (start)
710 *start = saved_rindex;
711
712 return 0;
713
714 fail:
715 dns_packet_rewind(p, saved_rindex);
716 return r;
717 }
718
719 int dns_packet_read_name(DnsPacket *p, char **_ret, size_t *start) {
720 size_t saved_rindex, after_rindex = 0;
721 _cleanup_free_ char *ret = NULL;
722 size_t n = 0, allocated = 0;
723 bool first = true;
724 int r;
725
726 assert(p);
727 assert(_ret);
728
729 saved_rindex = p->rindex;
730
731 for (;;) {
732 uint8_t c, d;
733
734 r = dns_packet_read_uint8(p, &c, NULL);
735 if (r < 0)
736 goto fail;
737
738 if (c == 0)
739 /* End of name */
740 break;
741 else if (c <= 63) {
742 _cleanup_free_ char *t = NULL;
743 const char *label;
744
745 /* Literal label */
746 r = dns_packet_read(p, c, (const void**) &label, NULL);
747 if (r < 0)
748 goto fail;
749
750 r = dns_label_escape(label, c, &t);
751 if (r < 0)
752 goto fail;
753
754 if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1)) {
755 r = -ENOMEM;
756 goto fail;
757 }
758
759 if (!first)
760 ret[n++] = '.';
761 else
762 first = false;
763
764 memcpy(ret + n, t, c);
765 n += r;
766 continue;
767 } else if ((c & 0xc0) == 0xc0) {
768 uint16_t ptr;
769
770 /* Pointer */
771 r = dns_packet_read_uint8(p, &d, NULL);
772 if (r < 0)
773 goto fail;
774
775 ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
776 if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= saved_rindex) {
777 r = -EBADMSG;
778 goto fail;
779 }
780
781 if (after_rindex == 0)
782 after_rindex = p->rindex;
783
784 p->rindex = ptr;
785 } else
786 goto fail;
787 }
788
789 if (!GREEDY_REALLOC(ret, allocated, n + 1)) {
790 r = -ENOMEM;
791 goto fail;
792 }
793
794 ret[n] = 0;
795
796 if (after_rindex != 0)
797 p->rindex= after_rindex;
798
799 *_ret = ret;
800 ret = NULL;
801
802 if (start)
803 *start = saved_rindex;
804
805 return 0;
806
807 fail:
808 dns_packet_rewind(p, saved_rindex);
809 return r;
810 }
811
812 int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) {
813 _cleanup_free_ char *name = NULL;
814 uint16_t class, type;
815 DnsResourceKey *key;
816 size_t saved_rindex;
817 int r;
818
819 assert(p);
820 assert(ret);
821
822 saved_rindex = p->rindex;
823
824 r = dns_packet_read_name(p, &name, NULL);
825 if (r < 0)
826 goto fail;
827
828 r = dns_packet_read_uint16(p, &type, NULL);
829 if (r < 0)
830 goto fail;
831
832 r = dns_packet_read_uint16(p, &class, NULL);
833 if (r < 0)
834 goto fail;
835
836 key = dns_resource_key_new_consume(class, type, name);
837 if (!key) {
838 r = -ENOMEM;
839 goto fail;
840 }
841
842 name = NULL;
843 *ret = key;
844
845 if (start)
846 *start = saved_rindex;
847
848 return 0;
849 fail:
850 dns_packet_rewind(p, saved_rindex);
851 return r;
852 }
853
854 int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
855 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
856 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
857 size_t saved_rindex, offset;
858 uint16_t rdlength;
859 const void *d;
860 int r;
861
862 assert(p);
863 assert(ret);
864
865 saved_rindex = p->rindex;
866
867 r = dns_packet_read_key(p, &key, NULL);
868 if (r < 0)
869 goto fail;
870
871 rr = dns_resource_record_new(key);
872 if (!rr) {
873 r = -ENOMEM;
874 goto fail;
875 }
876
877 r = dns_packet_read_uint32(p, &rr->ttl, NULL);
878 if (r < 0)
879 goto fail;
880
881 r = dns_packet_read_uint16(p, &rdlength, NULL);
882 if (r < 0)
883 goto fail;
884
885 if (p->rindex + rdlength > p->size) {
886 r = -EBADMSG;
887 goto fail;
888 }
889
890 offset = p->rindex;
891
892 switch (rr->key->type) {
893
894 case DNS_TYPE_PTR:
895 case DNS_TYPE_NS:
896 case DNS_TYPE_CNAME:
897 r = dns_packet_read_name(p, &rr->ptr.name, NULL);
898 break;
899
900 case DNS_TYPE_HINFO:
901 r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL);
902 if (r < 0)
903 goto fail;
904
905 r = dns_packet_read_string(p, &rr->hinfo.os, NULL);
906 break;
907
908 case DNS_TYPE_A:
909 r = dns_packet_read_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
910 break;
911
912 case DNS_TYPE_AAAA:
913 r = dns_packet_read_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
914 break;
915
916 case DNS_TYPE_SOA:
917 r = dns_packet_read_name(p, &rr->soa.mname, NULL);
918 if (r < 0)
919 goto fail;
920
921 r = dns_packet_read_name(p, &rr->soa.rname, NULL);
922 if (r < 0)
923 goto fail;
924
925 r = dns_packet_read_uint32(p, &rr->soa.serial, NULL);
926 if (r < 0)
927 goto fail;
928
929 r = dns_packet_read_uint32(p, &rr->soa.refresh, NULL);
930 if (r < 0)
931 goto fail;
932
933 r = dns_packet_read_uint32(p, &rr->soa.retry, NULL);
934 if (r < 0)
935 goto fail;
936
937 r = dns_packet_read_uint32(p, &rr->soa.expire, NULL);
938 if (r < 0)
939 goto fail;
940
941 r = dns_packet_read_uint32(p, &rr->soa.minimum, NULL);
942 break;
943
944 case DNS_TYPE_MX:
945 case DNS_TYPE_TXT:
946 case DNS_TYPE_SRV:
947 case DNS_TYPE_DNAME:
948 case DNS_TYPE_SSHFP:
949 default:
950 r = dns_packet_read(p, rdlength, &d, NULL);
951 if (r < 0)
952 goto fail;
953
954 rr->generic.data = memdup(d, rdlength);
955 if (!rr->generic.data) {
956 r = -ENOMEM;
957 goto fail;
958 }
959
960 rr->generic.size = rdlength;
961 break;
962 }
963 if (r < 0)
964 goto fail;
965 if (p->rindex != offset + rdlength) {
966 r = -EBADMSG;
967 goto fail;
968 }
969
970 *ret = rr;
971 rr = NULL;
972
973 if (start)
974 *start = saved_rindex;
975
976 return 0;
977 fail:
978 dns_packet_rewind(p, saved_rindex);
979 return r;
980 }
981
982 int dns_packet_extract(DnsPacket *p) {
983 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
984 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
985 size_t saved_rindex;
986 unsigned n, i;
987 int r;
988
989 saved_rindex = p->rindex;
990 dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
991
992 n = DNS_PACKET_QDCOUNT(p);
993 if (n > 0) {
994 question = dns_question_new(n);
995 if (!question) {
996 r = -ENOMEM;
997 goto finish;
998 }
999
1000 for (i = 0; i < n; i++) {
1001 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
1002
1003 r = dns_packet_read_key(p, &key, NULL);
1004 if (r < 0)
1005 goto finish;
1006
1007 r = dns_question_add(question, key);
1008 if (r < 0)
1009 goto finish;
1010 }
1011 }
1012
1013 n = DNS_PACKET_RRCOUNT(p);
1014 if (n > 0) {
1015 answer = dns_answer_new(n);
1016 if (!answer) {
1017 r = -ENOMEM;
1018 goto finish;
1019 }
1020
1021 for (i = 0; i < n; i++) {
1022 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
1023
1024 r = dns_packet_read_rr(p, &rr, NULL);
1025 if (r < 0)
1026 goto finish;
1027
1028 r = dns_answer_add(answer, rr);
1029 if (r < 0)
1030 goto finish;
1031 }
1032 }
1033
1034 p->question = question;
1035 question = NULL;
1036
1037 p->answer = answer;
1038 answer = NULL;
1039
1040 r = 0;
1041
1042 finish:
1043 p->rindex = saved_rindex;
1044 return r;
1045 }
1046
1047 static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
1048 [DNS_RCODE_SUCCESS] = "SUCCESS",
1049 [DNS_RCODE_FORMERR] = "FORMERR",
1050 [DNS_RCODE_SERVFAIL] = "SERVFAIL",
1051 [DNS_RCODE_NXDOMAIN] = "NXDOMAIN",
1052 [DNS_RCODE_NOTIMP] = "NOTIMP",
1053 [DNS_RCODE_REFUSED] = "REFUSED",
1054 [DNS_RCODE_YXDOMAIN] = "YXDOMAIN",
1055 [DNS_RCODE_YXRRSET] = "YRRSET",
1056 [DNS_RCODE_NXRRSET] = "NXRRSET",
1057 [DNS_RCODE_NOTAUTH] = "NOTAUTH",
1058 [DNS_RCODE_NOTZONE] = "NOTZONE",
1059 [DNS_RCODE_BADVERS] = "BADVERS",
1060 [DNS_RCODE_BADKEY] = "BADKEY",
1061 [DNS_RCODE_BADTIME] = "BADTIME",
1062 [DNS_RCODE_BADMODE] = "BADMODE",
1063 [DNS_RCODE_BADNAME] = "BADNAME",
1064 [DNS_RCODE_BADALG] = "BADALG",
1065 [DNS_RCODE_BADTRUNC] = "BADTRUNC",
1066 };
1067 DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int);
1068
1069 static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = {
1070 [DNS_PROTOCOL_DNS] = "dns",
1071 [DNS_PROTOCOL_MDNS] = "mdns",
1072 [DNS_PROTOCOL_LLMNR] = "llmnr",
1073 };
1074 DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);