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