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