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