]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-dns-packet.c
resolved: implement full LLMNR conflict detection logic
[thirdparty/systemd.git] / src / resolve / resolved-dns-packet.c
CommitLineData
74b2466e
LP
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"
c73ce96b 23#include "util.h"
2e276efc 24#include "strv.h"
74b2466e
LP
25#include "resolved-dns-domain.h"
26#include "resolved-dns-packet.h"
27
1716f6dc 28int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
74b2466e
LP
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
c73ce96b
LP
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
74b2466e
LP
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;
1716f6dc 55 p->protocol = protocol;
74b2466e
LP
56 p->n_ref = 1;
57
58 *ret = p;
59
60 return 0;
61}
62
1716f6dc 63int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
74b2466e
LP
64 DnsPacket *p;
65 DnsPacketHeader *h;
66 int r;
67
68 assert(ret);
69
1716f6dc 70 r = dns_packet_new(&p, protocol, mtu);
74b2466e
LP
71 if (r < 0)
72 return r;
73
74 h = DNS_PACKET_HEADER(p);
1716f6dc 75
ea917db9
LP
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 */));
1716f6dc 86 else
ea917db9
LP
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 */));
74b2466e
LP
96
97 *ret = p;
98 return 0;
99}
100
101DnsPacket *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
111static void dns_packet_free(DnsPacket *p) {
112 char *s;
113
114 assert(p);
115
faa133f3
LP
116 dns_question_unref(p->question);
117 dns_answer_unref(p->answer);
322345fd 118
74b2466e
LP
119 while ((s = hashmap_steal_first_key(p->names)))
120 free(s);
121 hashmap_free(p->names);
122
faa133f3 123 free(p->_data);
74b2466e
LP
124 free(p);
125}
126
127DnsPacket *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
141int dns_packet_validate(DnsPacket *p) {
142 assert(p);
143
144 if (p->size < DNS_PACKET_HEADER_SIZE)
145 return -EBADMSG;
146
c73ce96b
LP
147 if (p->size > DNS_PACKET_SIZE_MAX)
148 return -EBADMSG;
149
623a4c97 150 return 1;
74b2466e
LP
151}
152
153int dns_packet_validate_reply(DnsPacket *p) {
74b2466e
LP
154 int r;
155
156 assert(p);
157
158 r = dns_packet_validate(p);
159 if (r < 0)
160 return r;
161
623a4c97
LP
162 if (DNS_PACKET_QR(p) != 1)
163 return 0;
164
165 if (DNS_PACKET_OPCODE(p) != 0)
74b2466e
LP
166 return -EBADMSG;
167
ea917db9
LP
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
623a4c97
LP
173 return 1;
174}
175
176int 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
3cb10d3a 188 if (DNS_PACKET_OPCODE(p) != 0)
74b2466e
LP
189 return -EBADMSG;
190
623a4c97
LP
191 if (DNS_PACKET_TC(p))
192 return -EBADMSG;
193
ea917db9 194 /* RFC 4795, Section 2.1.1. says to discard all queries with QDCOUNT != 1 */
623a4c97
LP
195 if (p->protocol == DNS_PROTOCOL_LLMNR &&
196 DNS_PACKET_QDCOUNT(p) != 1)
197 return -EBADMSG;
198
ea917db9 199 /* RFC 4795, Section 2.1.1. says to discard all queries with ANCOUNT != 0 */
623a4c97
LP
200 if (DNS_PACKET_ANCOUNT(p) > 0)
201 return -EBADMSG;
202
ea917db9 203 /* RFC 4795, Section 2.1.1. says to discard all queries with NSCOUNT != 0 */
623a4c97
LP
204 if (DNS_PACKET_NSCOUNT(p) > 0)
205 return -EBADMSG;
206
207 return 1;
74b2466e
LP
208}
209
210static int dns_packet_extend(DnsPacket *p, size_t add, void **ret, size_t *start) {
211 assert(p);
212
c73ce96b
LP
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
faa133f3 223 if (p->_data) {
c73ce96b
LP
224 void *d;
225
faa133f3 226 d = realloc(p->_data, a);
c73ce96b
LP
227 if (!d)
228 return -ENOMEM;
229
faa133f3 230 p->_data = d;
c73ce96b 231 } else {
faa133f3
LP
232 p->_data = malloc(a);
233 if (!p->_data)
c73ce96b
LP
234 return -ENOMEM;
235
faa133f3
LP
236 memcpy(p->_data, (uint8_t*) p + ALIGN(sizeof(DnsPacket)), p->size);
237 memzero((uint8_t*) p->_data + p->size, a - p->size);
c73ce96b
LP
238 }
239
240 p->allocated = a;
241 }
74b2466e
LP
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
253static 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
623a4c97
LP
275int 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
74b2466e
LP
289int 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
304int 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);
623a4c97
LP
315 ((uint8_t*) d)[1] = (uint8_t) v;
316
317 return 0;
318}
319
320int 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;
74b2466e
LP
334
335 return 0;
336}
337
338int 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
360int 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
151226ab
ZJS
380int dns_packet_append_name(DnsPacket *p, const char *name,
381 bool allow_compression, size_t *start) {
74b2466e
LP
382 size_t saved_size;
383 int r;
384
385 assert(p);
386 assert(name);
387
388 saved_size = p->size;
389
390 while (*name) {
391 _cleanup_free_ char *s = NULL;
392 char label[DNS_LABEL_MAX];
151226ab 393 size_t n = 0;
bdf10b5b 394 int k;
74b2466e 395
151226ab
ZJS
396 if (allow_compression)
397 n = PTR_TO_SIZE(hashmap_get(p->names, name));
74b2466e
LP
398 if (n > 0) {
399 assert(n < p->size);
400
401 if (n < 0x4000) {
402 r = dns_packet_append_uint16(p, 0xC000 | n, NULL);
403 if (r < 0)
404 goto fail;
405
406 goto done;
407 }
408 }
409
410 s = strdup(name);
411 if (!s) {
412 r = -ENOMEM;
413 goto fail;
414 }
415
416 r = dns_label_unescape(&name, label, sizeof(label));
417 if (r < 0)
418 goto fail;
419
bdf10b5b
LP
420 if (p->protocol == DNS_PROTOCOL_DNS)
421 k = dns_label_apply_idna(label, r, label, sizeof(label));
422 else
423 k = dns_label_undo_idna(label, r, label, sizeof(label));
424 if (k < 0) {
425 r = k;
426 goto fail;
427 }
428 if (k > 0)
429 r = k;
430
74b2466e
LP
431 r = dns_packet_append_label(p, label, r, &n);
432 if (r < 0)
433 goto fail;
434
151226ab
ZJS
435 if (allow_compression) {
436 r = hashmap_ensure_allocated(&p->names,
437 dns_name_hash_func,
438 dns_name_compare_func);
439 if (r < 0)
440 goto fail;
74b2466e 441
151226ab
ZJS
442 r = hashmap_put(p->names, s, SIZE_TO_PTR(n));
443 if (r < 0)
444 goto fail;
74b2466e 445
151226ab
ZJS
446 s = NULL;
447 }
74b2466e
LP
448 }
449
450 r = dns_packet_append_uint8(p, 0, NULL);
451 if (r < 0)
452 return r;
453
454done:
455 if (start)
456 *start = saved_size;
457
458 return 0;
459
460fail:
461 dns_packet_truncate(p, saved_size);
462 return r;
463}
464
465int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *k, size_t *start) {
466 size_t saved_size;
467 int r;
468
469 assert(p);
470 assert(k);
471
472 saved_size = p->size;
473
151226ab 474 r = dns_packet_append_name(p, DNS_RESOURCE_KEY_NAME(k), true, NULL);
74b2466e
LP
475 if (r < 0)
476 goto fail;
477
478 r = dns_packet_append_uint16(p, k->type, NULL);
479 if (r < 0)
480 goto fail;
481
482 r = dns_packet_append_uint16(p, k->class, NULL);
483 if (r < 0)
484 goto fail;
485
486 if (start)
487 *start = saved_size;
488
489 return 0;
490
491fail:
492 dns_packet_truncate(p, saved_size);
493 return r;
494}
495
623a4c97
LP
496int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start) {
497 size_t saved_size, rdlength_offset, end, rdlength;
498 int r;
499
500 assert(p);
501 assert(rr);
502
503 saved_size = p->size;
504
505 r = dns_packet_append_key(p, rr->key, NULL);
506 if (r < 0)
507 goto fail;
508
509 r = dns_packet_append_uint32(p, rr->ttl, NULL);
510 if (r < 0)
511 goto fail;
512
513 /* Initially we write 0 here */
514 r = dns_packet_append_uint16(p, 0, &rdlength_offset);
515 if (r < 0)
516 goto fail;
517
0dae31d4 518 switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
623a4c97 519
9c92ce6d
LP
520 case DNS_TYPE_SRV:
521 r = dns_packet_append_uint16(p, rr->srv.priority, NULL);
522 if (r < 0)
523 goto fail;
524
525 r = dns_packet_append_uint16(p, rr->srv.weight, NULL);
526 if (r < 0)
527 goto fail;
528
529 r = dns_packet_append_uint16(p, rr->srv.port, NULL);
530 if (r < 0)
531 goto fail;
532
151226ab 533 r = dns_packet_append_name(p, rr->srv.name, true, NULL);
9c92ce6d
LP
534 break;
535
623a4c97
LP
536 case DNS_TYPE_PTR:
537 case DNS_TYPE_NS:
538 case DNS_TYPE_CNAME:
8ac4e9e1 539 case DNS_TYPE_DNAME:
151226ab 540 r = dns_packet_append_name(p, rr->ptr.name, true, NULL);
623a4c97
LP
541 break;
542
543 case DNS_TYPE_HINFO:
544 r = dns_packet_append_string(p, rr->hinfo.cpu, NULL);
545 if (r < 0)
546 goto fail;
547
548 r = dns_packet_append_string(p, rr->hinfo.os, NULL);
549 break;
550
9de3e329 551 case DNS_TYPE_SPF: /* exactly the same as TXT */
2e276efc
ZJS
552 case DNS_TYPE_TXT: {
553 char **s;
554
555 STRV_FOREACH(s, rr->txt.strings) {
556 r = dns_packet_append_string(p, *s, NULL);
557 if (r < 0)
558 goto fail;
559 }
560
6a6fc3df 561 r = 0;
2e276efc
ZJS
562 break;
563 }
564
623a4c97
LP
565 case DNS_TYPE_A:
566 r = dns_packet_append_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
567 break;
568
569 case DNS_TYPE_AAAA:
570 r = dns_packet_append_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
571 break;
572
573 case DNS_TYPE_SOA:
151226ab 574 r = dns_packet_append_name(p, rr->soa.mname, true, NULL);
623a4c97
LP
575 if (r < 0)
576 goto fail;
577
151226ab 578 r = dns_packet_append_name(p, rr->soa.rname, true, NULL);
623a4c97
LP
579 if (r < 0)
580 goto fail;
581
582 r = dns_packet_append_uint32(p, rr->soa.serial, NULL);
583 if (r < 0)
584 goto fail;
585
586 r = dns_packet_append_uint32(p, rr->soa.refresh, NULL);
587 if (r < 0)
588 goto fail;
589
590 r = dns_packet_append_uint32(p, rr->soa.retry, NULL);
591 if (r < 0)
592 goto fail;
593
594 r = dns_packet_append_uint32(p, rr->soa.expire, NULL);
595 if (r < 0)
596 goto fail;
597
598 r = dns_packet_append_uint32(p, rr->soa.minimum, NULL);
599 break;
600
601 case DNS_TYPE_MX:
946c7094
ZJS
602 r = dns_packet_append_uint16(p, rr->mx.priority, NULL);
603 if (r < 0)
604 goto fail;
605
151226ab 606 r = dns_packet_append_name(p, rr->mx.exchange, true, NULL);
946c7094
ZJS
607 break;
608
0dae31d4
ZJS
609 case DNS_TYPE_LOC:
610 r = dns_packet_append_uint8(p, rr->loc.version, NULL);
611 if (r < 0)
612 goto fail;
613
614 r = dns_packet_append_uint8(p, rr->loc.size, NULL);
615 if (r < 0)
616 goto fail;
617
618 r = dns_packet_append_uint8(p, rr->loc.horiz_pre, NULL);
619 if (r < 0)
620 goto fail;
621
622 r = dns_packet_append_uint8(p, rr->loc.vert_pre, NULL);
623 if (r < 0)
624 goto fail;
625
afbc4f26 626 r = dns_packet_append_uint32(p, rr->loc.latitude, NULL);
0dae31d4
ZJS
627 if (r < 0)
628 goto fail;
629
afbc4f26 630 r = dns_packet_append_uint32(p, rr->loc.longitude, NULL);
0dae31d4
ZJS
631 if (r < 0)
632 goto fail;
633
afbc4f26 634 r = dns_packet_append_uint32(p, rr->loc.altitude, NULL);
0dae31d4
ZJS
635 break;
636
623a4c97 637 case DNS_TYPE_SSHFP:
42cc2eeb
LP
638 r = dns_packet_append_uint8(p, rr->sshfp.algorithm, NULL);
639 if (r < 0)
640 goto fail;
8db0d2f5 641
42cc2eeb
LP
642 r = dns_packet_append_uint8(p, rr->sshfp.fptype, NULL);
643 if (r < 0)
644 goto fail;
645
646 r = dns_packet_append_blob(p, rr->sshfp.key, rr->sshfp.key_size, NULL);
647 break;
648
8db0d2f5
ZJS
649 case DNS_TYPE_DNSKEY:
650 r = dns_packet_append_uint16(p, dnskey_to_flags(rr), NULL);
651 if (r < 0)
652 goto fail;
653
654 r = dns_packet_append_uint8(p, 3u, NULL);
655 if (r < 0)
656 goto fail;
657
658 r = dns_packet_append_uint8(p, rr->dnskey.algorithm, NULL);
659 if (r < 0)
660 goto fail;
661
662 r = dns_packet_append_blob(p, rr->dnskey.key, rr->dnskey.key_size, NULL);
663 break;
664
151226ab
ZJS
665 case DNS_TYPE_RRSIG:
666 r = dns_packet_append_uint16(p, rr->rrsig.type_covered, NULL);
667 if (r < 0)
668 goto fail;
669
670 r = dns_packet_append_uint8(p, rr->rrsig.algorithm, NULL);
671 if (r < 0)
672 goto fail;
673
674 r = dns_packet_append_uint8(p, rr->rrsig.labels, NULL);
675 if (r < 0)
676 goto fail;
677
678 r = dns_packet_append_uint32(p, rr->rrsig.original_ttl, NULL);
679 if (r < 0)
680 goto fail;
681
682 r = dns_packet_append_uint32(p, rr->rrsig.expiration, NULL);
683 if (r < 0)
684 goto fail;
685
686 r = dns_packet_append_uint32(p, rr->rrsig.inception, NULL);
687 if (r < 0)
688 goto fail;
689
690 r = dns_packet_append_uint8(p, rr->rrsig.key_tag, NULL);
691 if (r < 0)
692 goto fail;
693
694 r = dns_packet_append_name(p, rr->rrsig.signer, false, NULL);
695 if (r < 0)
696 goto fail;
697
698 r = dns_packet_append_blob(p, rr->rrsig.signature, rr->rrsig.signature_size, NULL);
699 break;
700
0dae31d4 701 case _DNS_TYPE_INVALID: /* unparseable */
623a4c97 702 default:
0dae31d4 703
623a4c97
LP
704 r = dns_packet_append_blob(p, rr->generic.data, rr->generic.size, NULL);
705 break;
706 }
707 if (r < 0)
708 goto fail;
709
710 /* Let's calculate the actual data size and update the field */
711 rdlength = p->size - rdlength_offset - sizeof(uint16_t);
712 if (rdlength > 0xFFFF) {
713 r = ENOSPC;
714 goto fail;
715 }
716
717 end = p->size;
718 p->size = rdlength_offset;
719 r = dns_packet_append_uint16(p, rdlength, NULL);
720 if (r < 0)
721 goto fail;
722 p->size = end;
723
351e6342
LP
724 if (start)
725 *start = saved_size;
726
623a4c97
LP
727 return 0;
728
729fail:
730 dns_packet_truncate(p, saved_size);
731 return r;
732}
733
734
74b2466e
LP
735int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) {
736 assert(p);
737
738 if (p->rindex + sz > p->size)
739 return -EMSGSIZE;
740
741 if (ret)
742 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->rindex;
743
744 if (start)
745 *start = p->rindex;
746
747 p->rindex += sz;
748 return 0;
749}
750
8ba9fd9c 751void dns_packet_rewind(DnsPacket *p, size_t idx) {
74b2466e
LP
752 assert(p);
753 assert(idx <= p->size);
754 assert(idx >= DNS_PACKET_HEADER_SIZE);
755
756 p->rindex = idx;
757}
758
623a4c97
LP
759int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start) {
760 const void *q;
761 int r;
762
763 assert(p);
764 assert(d);
765
766 r = dns_packet_read(p, sz, &q, start);
767 if (r < 0)
768 return r;
769
770 memcpy(d, q, sz);
771 return 0;
772}
773
74b2466e
LP
774int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) {
775 const void *d;
776 int r;
777
778 assert(p);
779
780 r = dns_packet_read(p, sizeof(uint8_t), &d, start);
781 if (r < 0)
782 return r;
783
784 *ret = ((uint8_t*) d)[0];
785 return 0;
786}
787
788int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start) {
789 const void *d;
790 int r;
791
792 assert(p);
793
794 r = dns_packet_read(p, sizeof(uint16_t), &d, start);
795 if (r < 0)
796 return r;
797
798 *ret = (((uint16_t) ((uint8_t*) d)[0]) << 8) |
799 ((uint16_t) ((uint8_t*) d)[1]);
800 return 0;
801}
802
803int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start) {
804 const void *d;
805 int r;
806
807 assert(p);
808
809 r = dns_packet_read(p, sizeof(uint32_t), &d, start);
810 if (r < 0)
811 return r;
812
813 *ret = (((uint32_t) ((uint8_t*) d)[0]) << 24) |
814 (((uint32_t) ((uint8_t*) d)[1]) << 16) |
815 (((uint32_t) ((uint8_t*) d)[2]) << 8) |
816 ((uint32_t) ((uint8_t*) d)[3]);
817
818 return 0;
819}
820
821int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start) {
822 size_t saved_rindex;
823 const void *d;
824 char *t;
825 uint8_t c;
826 int r;
827
828 assert(p);
829
830 saved_rindex = p->rindex;
831
832 r = dns_packet_read_uint8(p, &c, NULL);
833 if (r < 0)
834 goto fail;
835
836 r = dns_packet_read(p, c, &d, NULL);
837 if (r < 0)
838 goto fail;
839
840 if (memchr(d, 0, c)) {
841 r = -EBADMSG;
842 goto fail;
843 }
844
845 t = strndup(d, c);
846 if (!t) {
847 r = -ENOMEM;
848 goto fail;
849 }
850
851 if (!utf8_is_valid(t)) {
852 free(t);
853 r = -EBADMSG;
854 goto fail;
855 }
856
857 *ret = t;
858
859 if (start)
860 *start = saved_rindex;
861
862 return 0;
863
864fail:
865 dns_packet_rewind(p, saved_rindex);
866 return r;
867}
868
151226ab
ZJS
869int dns_packet_read_name(DnsPacket *p, char **_ret,
870 bool allow_compression, size_t *start) {
74b2466e
LP
871 size_t saved_rindex, after_rindex = 0;
872 _cleanup_free_ char *ret = NULL;
873 size_t n = 0, allocated = 0;
874 bool first = true;
875 int r;
876
877 assert(p);
878 assert(_ret);
879
880 saved_rindex = p->rindex;
881
882 for (;;) {
883 uint8_t c, d;
884
885 r = dns_packet_read_uint8(p, &c, NULL);
886 if (r < 0)
887 goto fail;
888
889 if (c == 0)
890 /* End of name */
891 break;
892 else if (c <= 63) {
893 _cleanup_free_ char *t = NULL;
894 const char *label;
895
896 /* Literal label */
897 r = dns_packet_read(p, c, (const void**) &label, NULL);
898 if (r < 0)
899 goto fail;
900
901 r = dns_label_escape(label, c, &t);
902 if (r < 0)
903 goto fail;
904
905 if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1)) {
906 r = -ENOMEM;
907 goto fail;
908 }
909
910 if (!first)
911 ret[n++] = '.';
912 else
913 first = false;
914
85818582 915 memcpy(ret + n, t, r);
74b2466e
LP
916 n += r;
917 continue;
151226ab 918 } else if (allow_compression && (c & 0xc0) == 0xc0) {
74b2466e
LP
919 uint16_t ptr;
920
921 /* Pointer */
922 r = dns_packet_read_uint8(p, &d, NULL);
923 if (r < 0)
924 goto fail;
925
926 ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
927 if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= saved_rindex) {
928 r = -EBADMSG;
929 goto fail;
930 }
931
932 if (after_rindex == 0)
933 after_rindex = p->rindex;
934
935 p->rindex = ptr;
936 } else
937 goto fail;
938 }
939
940 if (!GREEDY_REALLOC(ret, allocated, n + 1)) {
941 r = -ENOMEM;
942 goto fail;
943 }
944
945 ret[n] = 0;
946
947 if (after_rindex != 0)
948 p->rindex= after_rindex;
949
950 *_ret = ret;
951 ret = NULL;
952
953 if (start)
954 *start = saved_rindex;
955
956 return 0;
957
958fail:
959 dns_packet_rewind(p, saved_rindex);
960 return r;
961}
962
faa133f3
LP
963int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) {
964 _cleanup_free_ char *name = NULL;
965 uint16_t class, type;
966 DnsResourceKey *key;
74b2466e
LP
967 size_t saved_rindex;
968 int r;
969
970 assert(p);
971 assert(ret);
972
973 saved_rindex = p->rindex;
974
151226ab 975 r = dns_packet_read_name(p, &name, true, NULL);
74b2466e
LP
976 if (r < 0)
977 goto fail;
978
faa133f3 979 r = dns_packet_read_uint16(p, &type, NULL);
74b2466e
LP
980 if (r < 0)
981 goto fail;
982
faa133f3 983 r = dns_packet_read_uint16(p, &class, NULL);
74b2466e
LP
984 if (r < 0)
985 goto fail;
986
faa133f3
LP
987 key = dns_resource_key_new_consume(class, type, name);
988 if (!key) {
989 r = -ENOMEM;
990 goto fail;
991 }
992
993 name = NULL;
994 *ret = key;
74b2466e
LP
995
996 if (start)
997 *start = saved_rindex;
998
999 return 0;
1000fail:
1001 dns_packet_rewind(p, saved_rindex);
1002 return r;
1003}
1004
8db0d2f5
ZJS
1005static int dns_packet_read_public_key(DnsPacket *p, size_t length,
1006 void **dp, size_t *lengthp,
1007 size_t *start) {
1008 int r;
1009 const void *d;
1010 void *d2;
1011
1012 r = dns_packet_read(p, length, &d, NULL);
1013 if (r < 0)
1014 return r;
1015
1016 d2 = memdup(d, length);
1017 if (!d2)
1018 return -ENOMEM;
1019
1020 *dp = d2;
1021 *lengthp = length;
1022 return 0;
1023}
1024
afbc4f26
ZJS
1025static bool loc_size_ok(uint8_t size) {
1026 uint8_t m = size >> 4, e = size & 0xF;
1027
1028 return m <= 9 && e <= 9 && (m > 0 || e == 0);
1029}
1030
8db0d2f5 1031static int dnskey_parse_flags(DnsResourceRecord *rr, uint16_t flags) {
3ef77d04
LP
1032 assert(rr);
1033
8db0d2f5
ZJS
1034 if (flags & ~(DNSKEY_FLAG_SEP | DNSKEY_FLAG_ZONE_KEY))
1035 return -EBADMSG;
1036
1037 rr->dnskey.zone_key_flag = flags & DNSKEY_FLAG_ZONE_KEY;
1038 rr->dnskey.sep_flag = flags & DNSKEY_FLAG_SEP;
1039 return 0;
1040}
1041
74b2466e 1042int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
faa133f3
LP
1043 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
1044 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
74b2466e
LP
1045 size_t saved_rindex, offset;
1046 uint16_t rdlength;
1047 const void *d;
1048 int r;
1049
1050 assert(p);
1051 assert(ret);
1052
4e0296a9 1053 saved_rindex = p->rindex;
74b2466e 1054
faa133f3 1055 r = dns_packet_read_key(p, &key, NULL);
74b2466e
LP
1056 if (r < 0)
1057 goto fail;
1058
0e2bcd6a
LP
1059 if (key->class == DNS_CLASS_ANY ||
1060 key->type == DNS_TYPE_ANY) {
1061 r = -EBADMSG;
1062 goto fail;
1063 }
1064
faa133f3
LP
1065 rr = dns_resource_record_new(key);
1066 if (!rr) {
1067 r = -ENOMEM;
1068 goto fail;
1069 }
1070
74b2466e
LP
1071 r = dns_packet_read_uint32(p, &rr->ttl, NULL);
1072 if (r < 0)
1073 goto fail;
1074
1075 r = dns_packet_read_uint16(p, &rdlength, NULL);
1076 if (r < 0)
1077 goto fail;
1078
1079 if (p->rindex + rdlength > p->size) {
1080 r = -EBADMSG;
1081 goto fail;
1082 }
1083
1084 offset = p->rindex;
1085
faa133f3 1086 switch (rr->key->type) {
74b2466e 1087
9c92ce6d
LP
1088 case DNS_TYPE_SRV:
1089 r = dns_packet_read_uint16(p, &rr->srv.priority, NULL);
1090 if (r < 0)
1091 goto fail;
1092 r = dns_packet_read_uint16(p, &rr->srv.weight, NULL);
1093 if (r < 0)
1094 goto fail;
1095 r = dns_packet_read_uint16(p, &rr->srv.port, NULL);
1096 if (r < 0)
1097 goto fail;
151226ab 1098 r = dns_packet_read_name(p, &rr->srv.name, true, NULL);
9c92ce6d
LP
1099 break;
1100
74b2466e
LP
1101 case DNS_TYPE_PTR:
1102 case DNS_TYPE_NS:
1103 case DNS_TYPE_CNAME:
8ac4e9e1 1104 case DNS_TYPE_DNAME:
151226ab 1105 r = dns_packet_read_name(p, &rr->ptr.name, true, NULL);
74b2466e
LP
1106 break;
1107
1108 case DNS_TYPE_HINFO:
1109 r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL);
1110 if (r < 0)
1111 goto fail;
1112
1113 r = dns_packet_read_string(p, &rr->hinfo.os, NULL);
1114 break;
1115
9de3e329 1116 case DNS_TYPE_SPF: /* exactly the same as TXT */
2e276efc
ZJS
1117 case DNS_TYPE_TXT: {
1118 char *s;
1119
cbd67a86 1120 while (p->rindex < offset + rdlength) {
2e276efc
ZJS
1121 r = dns_packet_read_string(p, &s, NULL);
1122 if (r < 0)
1123 goto fail;
1124
1125 r = strv_consume(&rr->txt.strings, s);
1126 if (r < 0)
1127 goto fail;
6a6fc3df
LP
1128 }
1129
1130 r = 0;
2e276efc
ZJS
1131 break;
1132 }
1133
74b2466e 1134 case DNS_TYPE_A:
623a4c97 1135 r = dns_packet_read_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
74b2466e
LP
1136 break;
1137
1138 case DNS_TYPE_AAAA:
623a4c97 1139 r = dns_packet_read_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
74b2466e
LP
1140 break;
1141
7e8e0422 1142 case DNS_TYPE_SOA:
151226ab 1143 r = dns_packet_read_name(p, &rr->soa.mname, true, NULL);
7e8e0422
LP
1144 if (r < 0)
1145 goto fail;
1146
151226ab 1147 r = dns_packet_read_name(p, &rr->soa.rname, true, NULL);
7e8e0422
LP
1148 if (r < 0)
1149 goto fail;
1150
1151 r = dns_packet_read_uint32(p, &rr->soa.serial, NULL);
1152 if (r < 0)
1153 goto fail;
1154
1155 r = dns_packet_read_uint32(p, &rr->soa.refresh, NULL);
1156 if (r < 0)
1157 goto fail;
1158
1159 r = dns_packet_read_uint32(p, &rr->soa.retry, NULL);
1160 if (r < 0)
1161 goto fail;
1162
1163 r = dns_packet_read_uint32(p, &rr->soa.expire, NULL);
1164 if (r < 0)
1165 goto fail;
1166
1167 r = dns_packet_read_uint32(p, &rr->soa.minimum, NULL);
1168 break;
1169
623a4c97 1170 case DNS_TYPE_MX:
946c7094
ZJS
1171 r = dns_packet_read_uint16(p, &rr->mx.priority, NULL);
1172 if (r < 0)
1173 goto fail;
1174
151226ab 1175 r = dns_packet_read_name(p, &rr->mx.exchange, true, NULL);
946c7094
ZJS
1176 break;
1177
0dae31d4
ZJS
1178 case DNS_TYPE_LOC: {
1179 uint8_t t;
1180 size_t pos;
1181
1182 r = dns_packet_read_uint8(p, &t, &pos);
1183 if (r < 0)
1184 goto fail;
1185
1186 if (t == 0) {
1187 rr->loc.version = t;
1188
1189 r = dns_packet_read_uint8(p, &rr->loc.size, NULL);
1190 if (r < 0)
1191 goto fail;
1192
afbc4f26
ZJS
1193 if (!loc_size_ok(rr->loc.size)) {
1194 r = -EBADMSG;
1195 goto fail;
1196 }
1197
0dae31d4
ZJS
1198 r = dns_packet_read_uint8(p, &rr->loc.horiz_pre, NULL);
1199 if (r < 0)
1200 goto fail;
1201
afbc4f26
ZJS
1202 if (!loc_size_ok(rr->loc.horiz_pre)) {
1203 r = -EBADMSG;
1204 goto fail;
1205 }
1206
0dae31d4
ZJS
1207 r = dns_packet_read_uint8(p, &rr->loc.vert_pre, NULL);
1208 if (r < 0)
1209 goto fail;
1210
afbc4f26
ZJS
1211 if (!loc_size_ok(rr->loc.vert_pre)) {
1212 r = -EBADMSG;
1213 goto fail;
1214 }
1215
0dae31d4
ZJS
1216 r = dns_packet_read_uint32(p, &rr->loc.latitude, NULL);
1217 if (r < 0)
1218 goto fail;
1219
1220 r = dns_packet_read_uint32(p, &rr->loc.longitude, NULL);
1221 if (r < 0)
1222 goto fail;
1223
1224 r = dns_packet_read_uint32(p, &rr->loc.altitude, NULL);
1225 if (r < 0)
1226 goto fail;
1227
1228 break;
1229 } else {
1230 dns_packet_rewind(p, pos);
1231 rr->unparseable = true;
afbc4f26 1232 goto unparseable;
0dae31d4
ZJS
1233 }
1234 }
1235
623a4c97 1236 case DNS_TYPE_SSHFP:
42cc2eeb
LP
1237 r = dns_packet_read_uint8(p, &rr->sshfp.algorithm, NULL);
1238 if (r < 0)
1239 goto fail;
1240
1241 r = dns_packet_read_uint8(p, &rr->sshfp.fptype, NULL);
1242 if (r < 0)
1243 goto fail;
1244
8db0d2f5
ZJS
1245 r = dns_packet_read_public_key(p, rdlength - 2,
1246 &rr->sshfp.key, &rr->sshfp.key_size,
1247 NULL);
1248 break;
1249
1250 case DNS_TYPE_DNSKEY: {
1251 uint16_t flags;
1252 uint8_t proto;
1253
1254 r = dns_packet_read_uint16(p, &flags, NULL);
42cc2eeb
LP
1255 if (r < 0)
1256 goto fail;
1257
8db0d2f5
ZJS
1258 r = dnskey_parse_flags(rr, flags);
1259 if (r < 0)
1260 goto fail;
1261
1262 r = dns_packet_read_uint8(p, &proto, NULL);
1263 if (r < 0)
1264 goto fail;
1265
1266 /* protocol is required to be always 3 */
1267 if (proto != 3) {
1268 r = -EBADMSG;
42cc2eeb
LP
1269 goto fail;
1270 }
1271
8db0d2f5
ZJS
1272 r = dns_packet_read_uint8(p, &rr->dnskey.algorithm, NULL);
1273 if (r < 0)
1274 goto fail;
1275
1276 r = dns_packet_read_public_key(p, rdlength - 4,
1277 &rr->dnskey.key, &rr->dnskey.key_size,
1278 NULL);
42cc2eeb 1279 break;
8db0d2f5 1280 }
42cc2eeb 1281
151226ab
ZJS
1282 case DNS_TYPE_RRSIG:
1283 r = dns_packet_read_uint16(p, &rr->rrsig.type_covered, NULL);
1284 if (r < 0)
1285 goto fail;
1286
1287 r = dns_packet_read_uint8(p, &rr->rrsig.algorithm, NULL);
1288 if (r < 0)
1289 goto fail;
1290
1291 r = dns_packet_read_uint8(p, &rr->rrsig.labels, NULL);
1292 if (r < 0)
1293 goto fail;
1294
1295 r = dns_packet_read_uint32(p, &rr->rrsig.original_ttl, NULL);
1296 if (r < 0)
1297 goto fail;
1298
1299 r = dns_packet_read_uint32(p, &rr->rrsig.expiration, NULL);
1300 if (r < 0)
1301 goto fail;
1302
1303 r = dns_packet_read_uint32(p, &rr->rrsig.inception, NULL);
1304 if (r < 0)
1305 goto fail;
1306
1307 r = dns_packet_read_uint16(p, &rr->rrsig.key_tag, NULL);
1308 if (r < 0)
1309 goto fail;
1310
1311 r = dns_packet_read_name(p, &rr->rrsig.signer, false, NULL);
1312 if (r < 0)
1313 goto fail;
1314
1315 r = dns_packet_read_public_key(p, offset + rdlength - p->rindex,
1316 &rr->rrsig.signature, &rr->rrsig.signature_size,
1317 NULL);
1318 break;
1319
74b2466e 1320 default:
afbc4f26 1321 unparseable:
74b2466e
LP
1322 r = dns_packet_read(p, rdlength, &d, NULL);
1323 if (r < 0)
1324 goto fail;
1325
1326 rr->generic.data = memdup(d, rdlength);
1327 if (!rr->generic.data) {
1328 r = -ENOMEM;
1329 goto fail;
1330 }
1331
1332 rr->generic.size = rdlength;
1333 break;
1334 }
1335 if (r < 0)
1336 goto fail;
1337 if (p->rindex != offset + rdlength) {
1338 r = -EBADMSG;
1339 goto fail;
1340 }
1341
1342 *ret = rr;
1343 rr = NULL;
1344
1345 if (start)
1346 *start = saved_rindex;
1347
1348 return 0;
1349fail:
1350 dns_packet_rewind(p, saved_rindex);
1351 return r;
1352}
1353
faa133f3
LP
1354int dns_packet_extract(DnsPacket *p) {
1355 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
1356 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
1357 size_t saved_rindex;
1358 unsigned n, i;
74b2466e
LP
1359 int r;
1360
a4076574
LP
1361 if (p->extracted)
1362 return 0;
1363
faa133f3 1364 saved_rindex = p->rindex;
322345fd
LP
1365 dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
1366
3cb10d3a 1367 n = DNS_PACKET_QDCOUNT(p);
faa133f3
LP
1368 if (n > 0) {
1369 question = dns_question_new(n);
1370 if (!question) {
1371 r = -ENOMEM;
1372 goto finish;
1373 }
74b2466e 1374
faa133f3
LP
1375 for (i = 0; i < n; i++) {
1376 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
74b2466e 1377
faa133f3
LP
1378 r = dns_packet_read_key(p, &key, NULL);
1379 if (r < 0)
1380 goto finish;
74b2466e 1381
faa133f3
LP
1382 r = dns_question_add(question, key);
1383 if (r < 0)
1384 goto finish;
1385 }
1386 }
322345fd 1387
faa133f3
LP
1388 n = DNS_PACKET_RRCOUNT(p);
1389 if (n > 0) {
1390 answer = dns_answer_new(n);
1391 if (!answer) {
1392 r = -ENOMEM;
1393 goto finish;
1394 }
322345fd 1395
faa133f3
LP
1396 for (i = 0; i < n; i++) {
1397 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
322345fd 1398
faa133f3
LP
1399 r = dns_packet_read_rr(p, &rr, NULL);
1400 if (r < 0)
1401 goto finish;
322345fd 1402
faa133f3
LP
1403 r = dns_answer_add(answer, rr);
1404 if (r < 0)
1405 goto finish;
1406 }
322345fd
LP
1407 }
1408
faa133f3
LP
1409 p->question = question;
1410 question = NULL;
322345fd 1411
faa133f3
LP
1412 p->answer = answer;
1413 answer = NULL;
322345fd 1414
a4076574
LP
1415 p->extracted = true;
1416
faa133f3 1417 r = 0;
322345fd
LP
1418
1419finish:
1420 p->rindex = saved_rindex;
1421 return r;
1422}
1423
74b2466e
LP
1424static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
1425 [DNS_RCODE_SUCCESS] = "SUCCESS",
1426 [DNS_RCODE_FORMERR] = "FORMERR",
1427 [DNS_RCODE_SERVFAIL] = "SERVFAIL",
1428 [DNS_RCODE_NXDOMAIN] = "NXDOMAIN",
1429 [DNS_RCODE_NOTIMP] = "NOTIMP",
1430 [DNS_RCODE_REFUSED] = "REFUSED",
1431 [DNS_RCODE_YXDOMAIN] = "YXDOMAIN",
1432 [DNS_RCODE_YXRRSET] = "YRRSET",
1433 [DNS_RCODE_NXRRSET] = "NXRRSET",
1434 [DNS_RCODE_NOTAUTH] = "NOTAUTH",
1435 [DNS_RCODE_NOTZONE] = "NOTZONE",
1436 [DNS_RCODE_BADVERS] = "BADVERS",
1437 [DNS_RCODE_BADKEY] = "BADKEY",
1438 [DNS_RCODE_BADTIME] = "BADTIME",
1439 [DNS_RCODE_BADMODE] = "BADMODE",
1440 [DNS_RCODE_BADNAME] = "BADNAME",
1441 [DNS_RCODE_BADALG] = "BADALG",
1442 [DNS_RCODE_BADTRUNC] = "BADTRUNC",
1443};
1444DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int);
1716f6dc
LP
1445
1446static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = {
1447 [DNS_PROTOCOL_DNS] = "dns",
1448 [DNS_PROTOCOL_MDNS] = "mdns",
1449 [DNS_PROTOCOL_LLMNR] = "llmnr",
1450};
1451DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);
ff3d6560
ZJS
1452
1453static const char* const dnssec_algorithm_table[_DNSSEC_ALGORITHM_MAX_DEFINED] = {
1454 [DNSSEC_ALGORITHM_RSAMD5] = "RSAMD5",
1455 [DNSSEC_ALGORITHM_DH] = "DH",
1456 [DNSSEC_ALGORITHM_DSA] = "DSA",
1457 [DNSSEC_ALGORITHM_ECC] = "ECC",
1458 [DNSSEC_ALGORITHM_RSASHA1] = "RSASHA1",
1459 [DNSSEC_ALGORITHM_INDIRECT] = "INDIRECT",
1460 [DNSSEC_ALGORITHM_PRIVATEDNS] = "PRIVATEDNS",
1461 [DNSSEC_ALGORITHM_PRIVATEOID] = "PRIVATEOID",
1462};
1463DEFINE_STRING_TABLE_LOOKUP(dnssec_algorithm, int);