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