]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-dns-packet.c
resolved: LOC 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
394 n = PTR_TO_SIZE(hashmap_get(p->names, name));
395 if (n > 0) {
396 assert(n < p->size);
397
398 if (n < 0x4000) {
399 r = dns_packet_append_uint16(p, 0xC000 | n, NULL);
400 if (r < 0)
401 goto fail;
402
403 goto done;
404 }
405 }
406
407 s = strdup(name);
408 if (!s) {
409 r = -ENOMEM;
410 goto fail;
411 }
412
413 r = dns_label_unescape(&name, label, sizeof(label));
414 if (r < 0)
415 goto fail;
416
417 r = dns_packet_append_label(p, label, r, &n);
418 if (r < 0)
419 goto fail;
420
421 r = hashmap_ensure_allocated(&p->names, dns_name_hash_func, dns_name_compare_func);
422 if (r < 0)
423 goto fail;
424
425 r = hashmap_put(p->names, s, SIZE_TO_PTR(n));
426 if (r < 0)
427 goto fail;
428
429 s = NULL;
430 }
431
432 r = dns_packet_append_uint8(p, 0, NULL);
433 if (r < 0)
434 return r;
435
436 done:
437 if (start)
438 *start = saved_size;
439
440 return 0;
441
442 fail:
443 dns_packet_truncate(p, saved_size);
444 return r;
445 }
446
447 int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *k, size_t *start) {
448 size_t saved_size;
449 int r;
450
451 assert(p);
452 assert(k);
453
454 saved_size = p->size;
455
456 r = dns_packet_append_name(p, DNS_RESOURCE_KEY_NAME(k), NULL);
457 if (r < 0)
458 goto fail;
459
460 r = dns_packet_append_uint16(p, k->type, NULL);
461 if (r < 0)
462 goto fail;
463
464 r = dns_packet_append_uint16(p, k->class, NULL);
465 if (r < 0)
466 goto fail;
467
468 if (start)
469 *start = saved_size;
470
471 return 0;
472
473 fail:
474 dns_packet_truncate(p, saved_size);
475 return r;
476 }
477
478 int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start) {
479 size_t saved_size, rdlength_offset, end, rdlength;
480 int r;
481
482 assert(p);
483 assert(rr);
484
485 saved_size = p->size;
486
487 r = dns_packet_append_key(p, rr->key, NULL);
488 if (r < 0)
489 goto fail;
490
491 r = dns_packet_append_uint32(p, rr->ttl, NULL);
492 if (r < 0)
493 goto fail;
494
495 /* Initially we write 0 here */
496 r = dns_packet_append_uint16(p, 0, &rdlength_offset);
497 if (r < 0)
498 goto fail;
499
500 switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
501
502 case DNS_TYPE_PTR:
503 case DNS_TYPE_NS:
504 case DNS_TYPE_CNAME:
505 r = dns_packet_append_name(p, rr->ptr.name, NULL);
506 break;
507
508 case DNS_TYPE_HINFO:
509 r = dns_packet_append_string(p, rr->hinfo.cpu, NULL);
510 if (r < 0)
511 goto fail;
512
513 r = dns_packet_append_string(p, rr->hinfo.os, NULL);
514 break;
515
516 case DNS_TYPE_SPF: /* exactly the same as TXT */
517 case DNS_TYPE_TXT: {
518 char **s;
519
520 STRV_FOREACH(s, rr->txt.strings) {
521 r = dns_packet_append_string(p, *s, NULL);
522 if (r < 0)
523 goto fail;
524 }
525
526 break;
527 }
528
529 case DNS_TYPE_A:
530 r = dns_packet_append_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
531 break;
532
533 case DNS_TYPE_AAAA:
534 r = dns_packet_append_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
535 break;
536
537 case DNS_TYPE_SOA:
538 r = dns_packet_append_name(p, rr->soa.mname, NULL);
539 if (r < 0)
540 goto fail;
541
542 r = dns_packet_append_name(p, rr->soa.rname, NULL);
543 if (r < 0)
544 goto fail;
545
546 r = dns_packet_append_uint32(p, rr->soa.serial, NULL);
547 if (r < 0)
548 goto fail;
549
550 r = dns_packet_append_uint32(p, rr->soa.refresh, NULL);
551 if (r < 0)
552 goto fail;
553
554 r = dns_packet_append_uint32(p, rr->soa.retry, NULL);
555 if (r < 0)
556 goto fail;
557
558 r = dns_packet_append_uint32(p, rr->soa.expire, NULL);
559 if (r < 0)
560 goto fail;
561
562 r = dns_packet_append_uint32(p, rr->soa.minimum, NULL);
563 break;
564
565 case DNS_TYPE_MX:
566 r = dns_packet_append_uint16(p, rr->mx.priority, NULL);
567 if (r < 0)
568 goto fail;
569
570 r = dns_packet_append_name(p, rr->mx.exchange, NULL);
571 break;
572
573 case DNS_TYPE_LOC:
574 r = dns_packet_append_uint8(p, rr->loc.version, NULL);
575 if (r < 0)
576 goto fail;
577
578 r = dns_packet_append_uint8(p, rr->loc.size, NULL);
579 if (r < 0)
580 goto fail;
581
582 r = dns_packet_append_uint8(p, rr->loc.horiz_pre, NULL);
583 if (r < 0)
584 goto fail;
585
586 r = dns_packet_append_uint8(p, rr->loc.vert_pre, NULL);
587 if (r < 0)
588 goto fail;
589
590 r = dns_packet_append_uint16(p, rr->loc.latitude, NULL);
591 if (r < 0)
592 goto fail;
593
594 r = dns_packet_append_uint16(p, rr->loc.longitude, NULL);
595 if (r < 0)
596 goto fail;
597
598 r = dns_packet_append_uint16(p, rr->loc.altitude, NULL);
599 break;
600
601 case DNS_TYPE_SRV:
602 case DNS_TYPE_DNAME:
603 case DNS_TYPE_SSHFP:
604 case _DNS_TYPE_INVALID: /* unparseable */
605 default:
606
607 r = dns_packet_append_blob(p, rr->generic.data, rr->generic.size, NULL);
608 break;
609 }
610 if (r < 0)
611 goto fail;
612
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) {
616 r = ENOSPC;
617 goto fail;
618 }
619
620 end = p->size;
621 p->size = rdlength_offset;
622 r = dns_packet_append_uint16(p, rdlength, NULL);
623 if (r < 0)
624 goto fail;
625 p->size = end;
626
627 if (start)
628 *start = saved_size;
629
630 return 0;
631
632 fail:
633 dns_packet_truncate(p, saved_size);
634 return r;
635 }
636
637
638 int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) {
639 assert(p);
640
641 if (p->rindex + sz > p->size)
642 return -EMSGSIZE;
643
644 if (ret)
645 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->rindex;
646
647 if (start)
648 *start = p->rindex;
649
650 p->rindex += sz;
651 return 0;
652 }
653
654 void dns_packet_rewind(DnsPacket *p, size_t idx) {
655 assert(p);
656 assert(idx <= p->size);
657 assert(idx >= DNS_PACKET_HEADER_SIZE);
658
659 p->rindex = idx;
660 }
661
662 int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start) {
663 const void *q;
664 int r;
665
666 assert(p);
667 assert(d);
668
669 r = dns_packet_read(p, sz, &q, start);
670 if (r < 0)
671 return r;
672
673 memcpy(d, q, sz);
674 return 0;
675 }
676
677 int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) {
678 const void *d;
679 int r;
680
681 assert(p);
682
683 r = dns_packet_read(p, sizeof(uint8_t), &d, start);
684 if (r < 0)
685 return r;
686
687 *ret = ((uint8_t*) d)[0];
688 return 0;
689 }
690
691 int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start) {
692 const void *d;
693 int r;
694
695 assert(p);
696
697 r = dns_packet_read(p, sizeof(uint16_t), &d, start);
698 if (r < 0)
699 return r;
700
701 *ret = (((uint16_t) ((uint8_t*) d)[0]) << 8) |
702 ((uint16_t) ((uint8_t*) d)[1]);
703 return 0;
704 }
705
706 int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start) {
707 const void *d;
708 int r;
709
710 assert(p);
711
712 r = dns_packet_read(p, sizeof(uint32_t), &d, start);
713 if (r < 0)
714 return r;
715
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]);
720
721 return 0;
722 }
723
724 int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start) {
725 size_t saved_rindex;
726 const void *d;
727 char *t;
728 uint8_t c;
729 int r;
730
731 assert(p);
732
733 saved_rindex = p->rindex;
734
735 r = dns_packet_read_uint8(p, &c, NULL);
736 if (r < 0)
737 goto fail;
738
739 r = dns_packet_read(p, c, &d, NULL);
740 if (r < 0)
741 goto fail;
742
743 if (memchr(d, 0, c)) {
744 r = -EBADMSG;
745 goto fail;
746 }
747
748 t = strndup(d, c);
749 if (!t) {
750 r = -ENOMEM;
751 goto fail;
752 }
753
754 if (!utf8_is_valid(t)) {
755 free(t);
756 r = -EBADMSG;
757 goto fail;
758 }
759
760 *ret = t;
761
762 if (start)
763 *start = saved_rindex;
764
765 return 0;
766
767 fail:
768 dns_packet_rewind(p, saved_rindex);
769 return r;
770 }
771
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;
776 bool first = true;
777 int r;
778
779 assert(p);
780 assert(_ret);
781
782 saved_rindex = p->rindex;
783
784 for (;;) {
785 uint8_t c, d;
786
787 r = dns_packet_read_uint8(p, &c, NULL);
788 if (r < 0)
789 goto fail;
790
791 if (c == 0)
792 /* End of name */
793 break;
794 else if (c <= 63) {
795 _cleanup_free_ char *t = NULL;
796 const char *label;
797
798 /* Literal label */
799 r = dns_packet_read(p, c, (const void**) &label, NULL);
800 if (r < 0)
801 goto fail;
802
803 r = dns_label_escape(label, c, &t);
804 if (r < 0)
805 goto fail;
806
807 if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1)) {
808 r = -ENOMEM;
809 goto fail;
810 }
811
812 if (!first)
813 ret[n++] = '.';
814 else
815 first = false;
816
817 memcpy(ret + n, t, c);
818 n += r;
819 continue;
820 } else if ((c & 0xc0) == 0xc0) {
821 uint16_t ptr;
822
823 /* Pointer */
824 r = dns_packet_read_uint8(p, &d, NULL);
825 if (r < 0)
826 goto fail;
827
828 ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
829 if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= saved_rindex) {
830 r = -EBADMSG;
831 goto fail;
832 }
833
834 if (after_rindex == 0)
835 after_rindex = p->rindex;
836
837 p->rindex = ptr;
838 } else
839 goto fail;
840 }
841
842 if (!GREEDY_REALLOC(ret, allocated, n + 1)) {
843 r = -ENOMEM;
844 goto fail;
845 }
846
847 ret[n] = 0;
848
849 if (after_rindex != 0)
850 p->rindex= after_rindex;
851
852 *_ret = ret;
853 ret = NULL;
854
855 if (start)
856 *start = saved_rindex;
857
858 return 0;
859
860 fail:
861 dns_packet_rewind(p, saved_rindex);
862 return r;
863 }
864
865 int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) {
866 _cleanup_free_ char *name = NULL;
867 uint16_t class, type;
868 DnsResourceKey *key;
869 size_t saved_rindex;
870 int r;
871
872 assert(p);
873 assert(ret);
874
875 saved_rindex = p->rindex;
876
877 r = dns_packet_read_name(p, &name, NULL);
878 if (r < 0)
879 goto fail;
880
881 r = dns_packet_read_uint16(p, &type, NULL);
882 if (r < 0)
883 goto fail;
884
885 r = dns_packet_read_uint16(p, &class, NULL);
886 if (r < 0)
887 goto fail;
888
889 key = dns_resource_key_new_consume(class, type, name);
890 if (!key) {
891 r = -ENOMEM;
892 goto fail;
893 }
894
895 name = NULL;
896 *ret = key;
897
898 if (start)
899 *start = saved_rindex;
900
901 return 0;
902 fail:
903 dns_packet_rewind(p, saved_rindex);
904 return r;
905 }
906
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;
911 uint16_t rdlength;
912 const void *d;
913 int r;
914
915 assert(p);
916 assert(ret);
917
918 saved_rindex = p->rindex;
919
920 r = dns_packet_read_key(p, &key, NULL);
921 if (r < 0)
922 goto fail;
923
924 if (key->class == DNS_CLASS_ANY ||
925 key->type == DNS_TYPE_ANY) {
926 r = -EBADMSG;
927 goto fail;
928 }
929
930 rr = dns_resource_record_new(key);
931 if (!rr) {
932 r = -ENOMEM;
933 goto fail;
934 }
935
936 r = dns_packet_read_uint32(p, &rr->ttl, NULL);
937 if (r < 0)
938 goto fail;
939
940 r = dns_packet_read_uint16(p, &rdlength, NULL);
941 if (r < 0)
942 goto fail;
943
944 if (p->rindex + rdlength > p->size) {
945 r = -EBADMSG;
946 goto fail;
947 }
948
949 offset = p->rindex;
950
951 switch (rr->key->type) {
952
953 case DNS_TYPE_PTR:
954 case DNS_TYPE_NS:
955 case DNS_TYPE_CNAME:
956 r = dns_packet_read_name(p, &rr->ptr.name, NULL);
957 break;
958
959 case DNS_TYPE_HINFO:
960 r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL);
961 if (r < 0)
962 goto fail;
963
964 r = dns_packet_read_string(p, &rr->hinfo.os, NULL);
965 break;
966
967 case DNS_TYPE_SPF: /* exactly the same as TXT */
968 case DNS_TYPE_TXT: {
969 char *s;
970
971 while (p->rindex < p->size) {
972 r = dns_packet_read_string(p, &s, NULL);
973 if (r < 0)
974 goto fail;
975
976 r = strv_consume(&rr->txt.strings, s);
977 if (r < 0)
978 goto fail;
979 };
980 break;
981 }
982
983 case DNS_TYPE_A:
984 r = dns_packet_read_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
985 break;
986
987 case DNS_TYPE_AAAA:
988 r = dns_packet_read_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
989 break;
990
991 case DNS_TYPE_SOA:
992 r = dns_packet_read_name(p, &rr->soa.mname, NULL);
993 if (r < 0)
994 goto fail;
995
996 r = dns_packet_read_name(p, &rr->soa.rname, NULL);
997 if (r < 0)
998 goto fail;
999
1000 r = dns_packet_read_uint32(p, &rr->soa.serial, NULL);
1001 if (r < 0)
1002 goto fail;
1003
1004 r = dns_packet_read_uint32(p, &rr->soa.refresh, NULL);
1005 if (r < 0)
1006 goto fail;
1007
1008 r = dns_packet_read_uint32(p, &rr->soa.retry, NULL);
1009 if (r < 0)
1010 goto fail;
1011
1012 r = dns_packet_read_uint32(p, &rr->soa.expire, NULL);
1013 if (r < 0)
1014 goto fail;
1015
1016 r = dns_packet_read_uint32(p, &rr->soa.minimum, NULL);
1017 break;
1018
1019 case DNS_TYPE_MX:
1020 r = dns_packet_read_uint16(p, &rr->mx.priority, NULL);
1021 if (r < 0)
1022 goto fail;
1023
1024 r = dns_packet_read_name(p, &rr->mx.exchange, NULL);
1025 break;
1026
1027 case DNS_TYPE_LOC: {
1028 uint8_t t;
1029 size_t pos;
1030
1031 r = dns_packet_read_uint8(p, &t, &pos);
1032 if (r < 0)
1033 goto fail;
1034
1035 if (t == 0) {
1036 rr->loc.version = t;
1037
1038 r = dns_packet_read_uint8(p, &rr->loc.size, NULL);
1039 if (r < 0)
1040 goto fail;
1041
1042 r = dns_packet_read_uint8(p, &rr->loc.horiz_pre, NULL);
1043 if (r < 0)
1044 goto fail;
1045
1046 r = dns_packet_read_uint8(p, &rr->loc.vert_pre, NULL);
1047 if (r < 0)
1048 goto fail;
1049
1050 r = dns_packet_read_uint32(p, &rr->loc.latitude, NULL);
1051 if (r < 0)
1052 goto fail;
1053
1054 r = dns_packet_read_uint32(p, &rr->loc.longitude, NULL);
1055 if (r < 0)
1056 goto fail;
1057
1058 r = dns_packet_read_uint32(p, &rr->loc.altitude, NULL);
1059 if (r < 0)
1060 goto fail;
1061
1062 break;
1063 } else {
1064 dns_packet_rewind(p, pos);
1065 rr->unparseable = true;
1066 /* fall through */
1067 }
1068 }
1069
1070 case DNS_TYPE_SRV:
1071 case DNS_TYPE_DNAME:
1072 case DNS_TYPE_SSHFP:
1073 default:
1074 r = dns_packet_read(p, rdlength, &d, NULL);
1075 if (r < 0)
1076 goto fail;
1077
1078 rr->generic.data = memdup(d, rdlength);
1079 if (!rr->generic.data) {
1080 r = -ENOMEM;
1081 goto fail;
1082 }
1083
1084 rr->generic.size = rdlength;
1085 break;
1086 }
1087 if (r < 0)
1088 goto fail;
1089 if (p->rindex != offset + rdlength) {
1090 r = -EBADMSG;
1091 goto fail;
1092 }
1093
1094 *ret = rr;
1095 rr = NULL;
1096
1097 if (start)
1098 *start = saved_rindex;
1099
1100 return 0;
1101 fail:
1102 dns_packet_rewind(p, saved_rindex);
1103 return r;
1104 }
1105
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;
1110 unsigned n, i;
1111 int r;
1112
1113 saved_rindex = p->rindex;
1114 dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
1115
1116 n = DNS_PACKET_QDCOUNT(p);
1117 if (n > 0) {
1118 question = dns_question_new(n);
1119 if (!question) {
1120 r = -ENOMEM;
1121 goto finish;
1122 }
1123
1124 for (i = 0; i < n; i++) {
1125 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
1126
1127 r = dns_packet_read_key(p, &key, NULL);
1128 if (r < 0)
1129 goto finish;
1130
1131 r = dns_question_add(question, key);
1132 if (r < 0)
1133 goto finish;
1134 }
1135 }
1136
1137 n = DNS_PACKET_RRCOUNT(p);
1138 if (n > 0) {
1139 answer = dns_answer_new(n);
1140 if (!answer) {
1141 r = -ENOMEM;
1142 goto finish;
1143 }
1144
1145 for (i = 0; i < n; i++) {
1146 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
1147
1148 r = dns_packet_read_rr(p, &rr, NULL);
1149 if (r < 0)
1150 goto finish;
1151
1152 r = dns_answer_add(answer, rr);
1153 if (r < 0)
1154 goto finish;
1155 }
1156 }
1157
1158 p->question = question;
1159 question = NULL;
1160
1161 p->answer = answer;
1162 answer = NULL;
1163
1164 r = 0;
1165
1166 finish:
1167 p->rindex = saved_rindex;
1168 return r;
1169 }
1170
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",
1190 };
1191 DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int);
1192
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",
1197 };
1198 DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);