chiark / gitweb /
resolved: fix serialization of LOC records, check correctness
[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_uint32(p, rr->loc.latitude, NULL);
609                 if (r < 0)
610                         goto fail;
611
612                 r = dns_packet_append_uint32(p, rr->loc.longitude, NULL);
613                 if (r < 0)
614                         goto fail;
615
616                 r = dns_packet_append_uint32(p, rr->loc.altitude, NULL);
617                 break;
618
619         case DNS_TYPE_SSHFP:
620                 r = dns_packet_append_uint8(p, rr->sshfp.algorithm, NULL);
621                 if (r < 0)
622                         goto fail;
623                 r = dns_packet_append_uint8(p, rr->sshfp.fptype, NULL);
624                 if (r < 0)
625                         goto fail;
626
627                 r = dns_packet_append_blob(p, rr->sshfp.key, rr->sshfp.key_size, NULL);
628                 break;
629
630         case _DNS_TYPE_INVALID: /* unparseable */
631         default:
632
633                 r = dns_packet_append_blob(p, rr->generic.data, rr->generic.size, NULL);
634                 break;
635         }
636         if (r < 0)
637                 goto fail;
638
639         /* Let's calculate the actual data size and update the field */
640         rdlength = p->size - rdlength_offset - sizeof(uint16_t);
641         if (rdlength > 0xFFFF) {
642                 r = ENOSPC;
643                 goto fail;
644         }
645
646         end = p->size;
647         p->size = rdlength_offset;
648         r = dns_packet_append_uint16(p, rdlength, NULL);
649         if (r < 0)
650                 goto fail;
651         p->size = end;
652
653         if (start)
654                 *start = saved_size;
655
656         return 0;
657
658 fail:
659         dns_packet_truncate(p, saved_size);
660         return r;
661 }
662
663
664 int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) {
665         assert(p);
666
667         if (p->rindex + sz > p->size)
668                 return -EMSGSIZE;
669
670         if (ret)
671                 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->rindex;
672
673         if (start)
674                 *start = p->rindex;
675
676         p->rindex += sz;
677         return 0;
678 }
679
680 void dns_packet_rewind(DnsPacket *p, size_t idx) {
681         assert(p);
682         assert(idx <= p->size);
683         assert(idx >= DNS_PACKET_HEADER_SIZE);
684
685         p->rindex = idx;
686 }
687
688 int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start) {
689         const void *q;
690         int r;
691
692         assert(p);
693         assert(d);
694
695         r = dns_packet_read(p, sz, &q, start);
696         if (r < 0)
697                 return r;
698
699         memcpy(d, q, sz);
700         return 0;
701 }
702
703 int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) {
704         const void *d;
705         int r;
706
707         assert(p);
708
709         r = dns_packet_read(p, sizeof(uint8_t), &d, start);
710         if (r < 0)
711                 return r;
712
713         *ret = ((uint8_t*) d)[0];
714         return 0;
715 }
716
717 int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start) {
718         const void *d;
719         int r;
720
721         assert(p);
722
723         r = dns_packet_read(p, sizeof(uint16_t), &d, start);
724         if (r < 0)
725                 return r;
726
727         *ret = (((uint16_t) ((uint8_t*) d)[0]) << 8) |
728                 ((uint16_t) ((uint8_t*) d)[1]);
729         return 0;
730 }
731
732 int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start) {
733         const void *d;
734         int r;
735
736         assert(p);
737
738         r = dns_packet_read(p, sizeof(uint32_t), &d, start);
739         if (r < 0)
740                 return r;
741
742         *ret = (((uint32_t) ((uint8_t*) d)[0]) << 24) |
743                (((uint32_t) ((uint8_t*) d)[1]) << 16) |
744                (((uint32_t) ((uint8_t*) d)[2]) << 8) |
745                 ((uint32_t) ((uint8_t*) d)[3]);
746
747         return 0;
748 }
749
750 int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start) {
751         size_t saved_rindex;
752         const void *d;
753         char *t;
754         uint8_t c;
755         int r;
756
757         assert(p);
758
759         saved_rindex = p->rindex;
760
761         r = dns_packet_read_uint8(p, &c, NULL);
762         if (r < 0)
763                 goto fail;
764
765         r = dns_packet_read(p, c, &d, NULL);
766         if (r < 0)
767                 goto fail;
768
769         if (memchr(d, 0, c)) {
770                 r = -EBADMSG;
771                 goto fail;
772         }
773
774         t = strndup(d, c);
775         if (!t) {
776                 r = -ENOMEM;
777                 goto fail;
778         }
779
780         if (!utf8_is_valid(t)) {
781                 free(t);
782                 r = -EBADMSG;
783                 goto fail;
784         }
785
786         *ret = t;
787
788         if (start)
789                 *start = saved_rindex;
790
791         return 0;
792
793 fail:
794         dns_packet_rewind(p, saved_rindex);
795         return r;
796 }
797
798 int dns_packet_read_name(DnsPacket *p, char **_ret, size_t *start) {
799         size_t saved_rindex, after_rindex = 0;
800         _cleanup_free_ char *ret = NULL;
801         size_t n = 0, allocated = 0;
802         bool first = true;
803         int r;
804
805         assert(p);
806         assert(_ret);
807
808         saved_rindex = p->rindex;
809
810         for (;;) {
811                 uint8_t c, d;
812
813                 r = dns_packet_read_uint8(p, &c, NULL);
814                 if (r < 0)
815                         goto fail;
816
817                 if (c == 0)
818                         /* End of name */
819                         break;
820                 else if (c <= 63) {
821                         _cleanup_free_ char *t = NULL;
822                         const char *label;
823
824                         /* Literal label */
825                         r = dns_packet_read(p, c, (const void**) &label, NULL);
826                         if (r < 0)
827                                 goto fail;
828
829                         r = dns_label_escape(label, c, &t);
830                         if (r < 0)
831                                 goto fail;
832
833                         if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1)) {
834                                 r = -ENOMEM;
835                                 goto fail;
836                         }
837
838                         if (!first)
839                                 ret[n++] = '.';
840                         else
841                                 first = false;
842
843                         memcpy(ret + n, t, r);
844                         n += r;
845                         continue;
846                 } else if ((c & 0xc0) == 0xc0) {
847                         uint16_t ptr;
848
849                         /* Pointer */
850                         r = dns_packet_read_uint8(p, &d, NULL);
851                         if (r < 0)
852                                 goto fail;
853
854                         ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
855                         if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= saved_rindex) {
856                                 r = -EBADMSG;
857                                 goto fail;
858                         }
859
860                         if (after_rindex == 0)
861                                 after_rindex = p->rindex;
862
863                         p->rindex = ptr;
864                 } else
865                         goto fail;
866         }
867
868         if (!GREEDY_REALLOC(ret, allocated, n + 1)) {
869                 r = -ENOMEM;
870                 goto fail;
871         }
872
873         ret[n] = 0;
874
875         if (after_rindex != 0)
876                 p->rindex= after_rindex;
877
878         *_ret = ret;
879         ret = NULL;
880
881         if (start)
882                 *start = saved_rindex;
883
884         return 0;
885
886 fail:
887         dns_packet_rewind(p, saved_rindex);
888         return r;
889 }
890
891 int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) {
892         _cleanup_free_ char *name = NULL;
893         uint16_t class, type;
894         DnsResourceKey *key;
895         size_t saved_rindex;
896         int r;
897
898         assert(p);
899         assert(ret);
900
901         saved_rindex = p->rindex;
902
903         r = dns_packet_read_name(p, &name, NULL);
904         if (r < 0)
905                 goto fail;
906
907         r = dns_packet_read_uint16(p, &type, NULL);
908         if (r < 0)
909                 goto fail;
910
911         r = dns_packet_read_uint16(p, &class, NULL);
912         if (r < 0)
913                 goto fail;
914
915         key = dns_resource_key_new_consume(class, type, name);
916         if (!key) {
917                 r = -ENOMEM;
918                 goto fail;
919         }
920
921         name = NULL;
922         *ret = key;
923
924         if (start)
925                 *start = saved_rindex;
926
927         return 0;
928 fail:
929         dns_packet_rewind(p, saved_rindex);
930         return r;
931 }
932
933 static bool loc_size_ok(uint8_t size) {
934         uint8_t m = size >> 4, e = size & 0xF;
935
936         return m <= 9 && e <= 9 && (m > 0 || e == 0);
937 }
938
939 int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
940         _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
941         _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
942         size_t saved_rindex, offset;
943         uint16_t rdlength;
944         const void *d;
945         int r;
946
947         assert(p);
948         assert(ret);
949
950         saved_rindex = p->rindex;
951
952         r = dns_packet_read_key(p, &key, NULL);
953         if (r < 0)
954                 goto fail;
955
956         if (key->class == DNS_CLASS_ANY ||
957             key->type == DNS_TYPE_ANY) {
958                 r = -EBADMSG;
959                 goto fail;
960         }
961
962         rr = dns_resource_record_new(key);
963         if (!rr) {
964                 r = -ENOMEM;
965                 goto fail;
966         }
967
968         r = dns_packet_read_uint32(p, &rr->ttl, NULL);
969         if (r < 0)
970                 goto fail;
971
972         r = dns_packet_read_uint16(p, &rdlength, NULL);
973         if (r < 0)
974                 goto fail;
975
976         if (p->rindex + rdlength > p->size) {
977                 r = -EBADMSG;
978                 goto fail;
979         }
980
981         offset = p->rindex;
982
983         switch (rr->key->type) {
984
985         case DNS_TYPE_SRV:
986                 r = dns_packet_read_uint16(p, &rr->srv.priority, NULL);
987                 if (r < 0)
988                         goto fail;
989                 r = dns_packet_read_uint16(p, &rr->srv.weight, NULL);
990                 if (r < 0)
991                         goto fail;
992                 r = dns_packet_read_uint16(p, &rr->srv.port, NULL);
993                 if (r < 0)
994                         goto fail;
995                 r = dns_packet_read_name(p, &rr->srv.name, NULL);
996                 break;
997
998         case DNS_TYPE_PTR:
999         case DNS_TYPE_NS:
1000         case DNS_TYPE_CNAME:
1001         case DNS_TYPE_DNAME:
1002                 r = dns_packet_read_name(p, &rr->ptr.name, NULL);
1003                 break;
1004
1005         case DNS_TYPE_HINFO:
1006                 r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL);
1007                 if (r < 0)
1008                         goto fail;
1009
1010                 r = dns_packet_read_string(p, &rr->hinfo.os, NULL);
1011                 break;
1012
1013         case DNS_TYPE_SPF: /* exactly the same as TXT */
1014         case DNS_TYPE_TXT: {
1015                 char *s;
1016
1017                 while (p->rindex < offset + rdlength) {
1018                         r = dns_packet_read_string(p, &s, NULL);
1019                         if (r < 0)
1020                                 goto fail;
1021
1022                         r = strv_consume(&rr->txt.strings, s);
1023                         if (r < 0)
1024                                 goto fail;
1025                 }
1026
1027                 r = 0;
1028                 break;
1029         }
1030
1031         case DNS_TYPE_A:
1032                 r = dns_packet_read_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
1033                 break;
1034
1035         case DNS_TYPE_AAAA:
1036                 r = dns_packet_read_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
1037                 break;
1038
1039         case DNS_TYPE_SOA:
1040                 r = dns_packet_read_name(p, &rr->soa.mname, NULL);
1041                 if (r < 0)
1042                         goto fail;
1043
1044                 r = dns_packet_read_name(p, &rr->soa.rname, NULL);
1045                 if (r < 0)
1046                         goto fail;
1047
1048                 r = dns_packet_read_uint32(p, &rr->soa.serial, NULL);
1049                 if (r < 0)
1050                         goto fail;
1051
1052                 r = dns_packet_read_uint32(p, &rr->soa.refresh, NULL);
1053                 if (r < 0)
1054                         goto fail;
1055
1056                 r = dns_packet_read_uint32(p, &rr->soa.retry, NULL);
1057                 if (r < 0)
1058                         goto fail;
1059
1060                 r = dns_packet_read_uint32(p, &rr->soa.expire, NULL);
1061                 if (r < 0)
1062                         goto fail;
1063
1064                 r = dns_packet_read_uint32(p, &rr->soa.minimum, NULL);
1065                 break;
1066
1067         case DNS_TYPE_MX:
1068                 r = dns_packet_read_uint16(p, &rr->mx.priority, NULL);
1069                 if (r < 0)
1070                         goto fail;
1071
1072                 r = dns_packet_read_name(p, &rr->mx.exchange, NULL);
1073                 break;
1074
1075         case DNS_TYPE_LOC: {
1076                 uint8_t t;
1077                 size_t pos;
1078
1079                 r = dns_packet_read_uint8(p, &t, &pos);
1080                 if (r < 0)
1081                         goto fail;
1082
1083                 if (t == 0) {
1084                         rr->loc.version = t;
1085
1086                         r = dns_packet_read_uint8(p, &rr->loc.size, NULL);
1087                         if (r < 0)
1088                                 goto fail;
1089
1090                         if (!loc_size_ok(rr->loc.size)) {
1091                                 r = -EBADMSG;
1092                                 goto fail;
1093                         }
1094
1095                         r = dns_packet_read_uint8(p, &rr->loc.horiz_pre, NULL);
1096                         if (r < 0)
1097                                 goto fail;
1098
1099                         if (!loc_size_ok(rr->loc.horiz_pre)) {
1100                                 r = -EBADMSG;
1101                                 goto fail;
1102                         }
1103
1104                         r = dns_packet_read_uint8(p, &rr->loc.vert_pre, NULL);
1105                         if (r < 0)
1106                                 goto fail;
1107
1108                         if (!loc_size_ok(rr->loc.vert_pre)) {
1109                                 r = -EBADMSG;
1110                                 goto fail;
1111                         }
1112
1113                         r = dns_packet_read_uint32(p, &rr->loc.latitude, NULL);
1114                         if (r < 0)
1115                                 goto fail;
1116
1117                         r = dns_packet_read_uint32(p, &rr->loc.longitude, NULL);
1118                         if (r < 0)
1119                                 goto fail;
1120
1121                         r = dns_packet_read_uint32(p, &rr->loc.altitude, NULL);
1122                         if (r < 0)
1123                                 goto fail;
1124
1125                         break;
1126                 } else {
1127                         dns_packet_rewind(p, pos);
1128                         rr->unparseable = true;
1129                         goto unparseable;
1130                 }
1131         }
1132
1133         case DNS_TYPE_SSHFP:
1134
1135                 r = dns_packet_read_uint8(p, &rr->sshfp.algorithm, NULL);
1136                 if (r < 0)
1137                         goto fail;
1138
1139                 r = dns_packet_read_uint8(p, &rr->sshfp.fptype, NULL);
1140                 if (r < 0)
1141                         goto fail;
1142
1143                 r = dns_packet_read(p, rdlength - 2, &d, NULL);
1144                 if (r < 0)
1145                         goto fail;
1146
1147                 rr->sshfp.key = memdup(d, rdlength - 2);
1148                 if (!rr->sshfp.key) {
1149                         r = -ENOMEM;
1150                         goto fail;
1151                 }
1152
1153                 rr->sshfp.key_size = rdlength - 2;
1154                 break;
1155
1156         default:
1157         unparseable:
1158                 r = dns_packet_read(p, rdlength, &d, NULL);
1159                 if (r < 0)
1160                         goto fail;
1161
1162                 rr->generic.data = memdup(d, rdlength);
1163                 if (!rr->generic.data) {
1164                         r = -ENOMEM;
1165                         goto fail;
1166                 }
1167
1168                 rr->generic.size = rdlength;
1169                 break;
1170         }
1171         if (r < 0)
1172                 goto fail;
1173         if (p->rindex != offset + rdlength) {
1174                 r = -EBADMSG;
1175                 goto fail;
1176         }
1177
1178         *ret = rr;
1179         rr = NULL;
1180
1181         if (start)
1182                 *start = saved_rindex;
1183
1184         return 0;
1185 fail:
1186         dns_packet_rewind(p, saved_rindex);
1187         return r;
1188 }
1189
1190 int dns_packet_extract(DnsPacket *p) {
1191         _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
1192         _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
1193         size_t saved_rindex;
1194         unsigned n, i;
1195         int r;
1196
1197         saved_rindex = p->rindex;
1198         dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
1199
1200         n = DNS_PACKET_QDCOUNT(p);
1201         if (n > 0) {
1202                 question = dns_question_new(n);
1203                 if (!question) {
1204                         r = -ENOMEM;
1205                         goto finish;
1206                 }
1207
1208                 for (i = 0; i < n; i++) {
1209                         _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
1210
1211                         r = dns_packet_read_key(p, &key, NULL);
1212                         if (r < 0)
1213                                 goto finish;
1214
1215                         r = dns_question_add(question, key);
1216                         if (r < 0)
1217                                 goto finish;
1218                 }
1219         }
1220
1221         n = DNS_PACKET_RRCOUNT(p);
1222         if (n > 0) {
1223                 answer = dns_answer_new(n);
1224                 if (!answer) {
1225                         r = -ENOMEM;
1226                         goto finish;
1227                 }
1228
1229                 for (i = 0; i < n; i++) {
1230                         _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
1231
1232                         r = dns_packet_read_rr(p, &rr, NULL);
1233                         if (r < 0)
1234                                 goto finish;
1235
1236                         r = dns_answer_add(answer, rr);
1237                         if (r < 0)
1238                                 goto finish;
1239                 }
1240         }
1241
1242         p->question = question;
1243         question = NULL;
1244
1245         p->answer = answer;
1246         answer = NULL;
1247
1248         r = 0;
1249
1250 finish:
1251         p->rindex = saved_rindex;
1252         return r;
1253 }
1254
1255 static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
1256         [DNS_RCODE_SUCCESS] = "SUCCESS",
1257         [DNS_RCODE_FORMERR] = "FORMERR",
1258         [DNS_RCODE_SERVFAIL] = "SERVFAIL",
1259         [DNS_RCODE_NXDOMAIN] = "NXDOMAIN",
1260         [DNS_RCODE_NOTIMP] = "NOTIMP",
1261         [DNS_RCODE_REFUSED] = "REFUSED",
1262         [DNS_RCODE_YXDOMAIN] = "YXDOMAIN",
1263         [DNS_RCODE_YXRRSET] = "YRRSET",
1264         [DNS_RCODE_NXRRSET] = "NXRRSET",
1265         [DNS_RCODE_NOTAUTH] = "NOTAUTH",
1266         [DNS_RCODE_NOTZONE] = "NOTZONE",
1267         [DNS_RCODE_BADVERS] = "BADVERS",
1268         [DNS_RCODE_BADKEY] = "BADKEY",
1269         [DNS_RCODE_BADTIME] = "BADTIME",
1270         [DNS_RCODE_BADMODE] = "BADMODE",
1271         [DNS_RCODE_BADNAME] = "BADNAME",
1272         [DNS_RCODE_BADALG] = "BADALG",
1273         [DNS_RCODE_BADTRUNC] = "BADTRUNC",
1274 };
1275 DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int);
1276
1277 static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = {
1278         [DNS_PROTOCOL_DNS] = "dns",
1279         [DNS_PROTOCOL_MDNS] = "mdns",
1280         [DNS_PROTOCOL_LLMNR] = "llmnr",
1281 };
1282 DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);