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