LCOV - code coverage report
Current view: top level - resolve - resolved-dns-packet.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 625 1349 46.3 %
Date: 2019-08-22 15:41:25 Functions: 35 54 64.8 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #if HAVE_GCRYPT
       4             : #include <gcrypt.h>
       5             : #endif
       6             : 
       7             : #include "alloc-util.h"
       8             : #include "dns-domain.h"
       9             : #include "memory-util.h"
      10             : #include "resolved-dns-packet.h"
      11             : #include "set.h"
      12             : #include "string-table.h"
      13             : #include "strv.h"
      14             : #include "unaligned.h"
      15             : #include "utf8.h"
      16             : #include "util.h"
      17             : 
      18             : #define EDNS0_OPT_DO (1<<15)
      19             : 
      20             : assert_cc(DNS_PACKET_SIZE_START > DNS_PACKET_HEADER_SIZE);
      21             : 
      22             : typedef struct DnsPacketRewinder {
      23             :         DnsPacket *packet;
      24             :         size_t saved_rindex;
      25             : } DnsPacketRewinder;
      26             : 
      27        1820 : static void rewind_dns_packet(DnsPacketRewinder *rewinder) {
      28        1820 :         if (rewinder->packet)
      29           0 :                 dns_packet_rewind(rewinder->packet, rewinder->saved_rindex);
      30        1820 : }
      31             : 
      32             : #define INIT_REWINDER(rewinder, p) do { rewinder.packet = p; rewinder.saved_rindex = p->rindex; } while (0)
      33             : #define CANCEL_REWINDER(rewinder) do { rewinder.packet = NULL; } while (0)
      34             : 
      35        1017 : int dns_packet_new(
      36             :                 DnsPacket **ret,
      37             :                 DnsProtocol protocol,
      38             :                 size_t min_alloc_dsize,
      39             :                 size_t max_size) {
      40             : 
      41             :         DnsPacket *p;
      42             :         size_t a;
      43             : 
      44        1017 :         assert(ret);
      45        1017 :         assert(max_size >= DNS_PACKET_HEADER_SIZE);
      46             : 
      47        1017 :         if (max_size > DNS_PACKET_SIZE_MAX)
      48           0 :                 max_size = DNS_PACKET_SIZE_MAX;
      49             : 
      50             :         /* The caller may not check what is going to be truly allocated, so do not allow to
      51             :          * allocate a DNS packet bigger than DNS_PACKET_SIZE_MAX.
      52             :          */
      53        1017 :         if (min_alloc_dsize > DNS_PACKET_SIZE_MAX)
      54           1 :                 return log_error_errno(SYNTHETIC_ERRNO(EFBIG),
      55             :                                        "Requested packet data size too big: %zu",
      56             :                                        min_alloc_dsize);
      57             : 
      58             :         /* When dns_packet_new() is called with min_alloc_dsize == 0, allocate more than the
      59             :          * absolute minimum (which is the dns packet header size), to avoid
      60             :          * resizing immediately again after appending the first data to the packet.
      61             :          */
      62        1016 :         if (min_alloc_dsize < DNS_PACKET_HEADER_SIZE)
      63         488 :                 a = DNS_PACKET_SIZE_START;
      64             :         else
      65         528 :                 a = min_alloc_dsize;
      66             : 
      67             :         /* round up to next page size */
      68        1016 :         a = PAGE_ALIGN(ALIGN(sizeof(DnsPacket)) + a) - ALIGN(sizeof(DnsPacket));
      69             : 
      70             :         /* make sure we never allocate more than useful */
      71        1016 :         if (a > max_size)
      72          10 :                 a = max_size;
      73             : 
      74        1016 :         p = malloc0(ALIGN(sizeof(DnsPacket)) + a);
      75        1016 :         if (!p)
      76           0 :                 return -ENOMEM;
      77             : 
      78        1016 :         p->size = p->rindex = DNS_PACKET_HEADER_SIZE;
      79        1016 :         p->allocated = a;
      80        1016 :         p->max_size = max_size;
      81        1016 :         p->protocol = protocol;
      82        1016 :         p->opt_start = p->opt_size = (size_t) -1;
      83        1016 :         p->n_ref = 1;
      84             : 
      85        1016 :         *ret = p;
      86             : 
      87        1016 :         return 0;
      88             : }
      89             : 
      90           0 : void dns_packet_set_flags(DnsPacket *p, bool dnssec_checking_disabled, bool truncated) {
      91             : 
      92             :         DnsPacketHeader *h;
      93             : 
      94           0 :         assert(p);
      95             : 
      96           0 :         h = DNS_PACKET_HEADER(p);
      97             : 
      98           0 :         switch(p->protocol) {
      99           0 :         case DNS_PROTOCOL_LLMNR:
     100           0 :                 assert(!truncated);
     101             : 
     102           0 :                 h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
     103             :                                                          0 /* opcode */,
     104             :                                                          0 /* c */,
     105             :                                                          0 /* tc */,
     106             :                                                          0 /* t */,
     107             :                                                          0 /* ra */,
     108             :                                                          0 /* ad */,
     109             :                                                          0 /* cd */,
     110             :                                                          0 /* rcode */));
     111           0 :                 break;
     112             : 
     113           0 :         case DNS_PROTOCOL_MDNS:
     114           0 :                 h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0         /* qr */,
     115             :                                                          0         /* opcode */,
     116             :                                                          0         /* aa */,
     117             :                                                          truncated /* tc */,
     118             :                                                          0         /* rd (ask for recursion) */,
     119             :                                                          0         /* ra */,
     120             :                                                          0         /* ad */,
     121             :                                                          0         /* cd */,
     122             :                                                          0         /* rcode */));
     123           0 :                 break;
     124             : 
     125           0 :         default:
     126           0 :                 assert(!truncated);
     127             : 
     128           0 :                 h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
     129             :                                                          0 /* opcode */,
     130             :                                                          0 /* aa */,
     131             :                                                          0 /* tc */,
     132             :                                                          1 /* rd (ask for recursion) */,
     133             :                                                          0 /* ra */,
     134             :                                                          0 /* ad */,
     135             :                                                          dnssec_checking_disabled /* cd */,
     136             :                                                          0 /* rcode */));
     137             :         }
     138           0 : }
     139             : 
     140           0 : int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t min_alloc_dsize, bool dnssec_checking_disabled) {
     141             :         DnsPacket *p;
     142             :         int r;
     143             : 
     144           0 :         assert(ret);
     145             : 
     146           0 :         r = dns_packet_new(&p, protocol, min_alloc_dsize, DNS_PACKET_SIZE_MAX);
     147           0 :         if (r < 0)
     148           0 :                 return r;
     149             : 
     150             :         /* Always set the TC bit to 0 initially.
     151             :          * If there are multiple packets later, we'll update the bit shortly before sending.
     152             :          */
     153           0 :         dns_packet_set_flags(p, dnssec_checking_disabled, false);
     154             : 
     155           0 :         *ret = p;
     156           0 :         return 0;
     157             : }
     158             : 
     159           0 : DnsPacket *dns_packet_ref(DnsPacket *p) {
     160             : 
     161           0 :         if (!p)
     162           0 :                 return NULL;
     163             : 
     164           0 :         assert(!p->on_stack);
     165             : 
     166           0 :         assert(p->n_ref > 0);
     167           0 :         p->n_ref++;
     168           0 :         return p;
     169             : }
     170             : 
     171        1258 : static void dns_packet_free(DnsPacket *p) {
     172             :         char *s;
     173             : 
     174        1258 :         assert(p);
     175             : 
     176        1258 :         dns_question_unref(p->question);
     177        1258 :         dns_answer_unref(p->answer);
     178        1258 :         dns_resource_record_unref(p->opt);
     179             : 
     180        1258 :         while ((s = hashmap_steal_first_key(p->names)))
     181           0 :                 free(s);
     182        1258 :         hashmap_free(p->names);
     183             : 
     184        1258 :         free(p->_data);
     185             : 
     186        1258 :         if (!p->on_stack)
     187        1016 :                 free(p);
     188        1258 : }
     189             : 
     190        2516 : DnsPacket *dns_packet_unref(DnsPacket *p) {
     191        2516 :         if (!p)
     192        1258 :                 return NULL;
     193             : 
     194        1258 :         assert(p->n_ref > 0);
     195             : 
     196        1258 :         dns_packet_unref(p->more);
     197             : 
     198        1258 :         if (p->n_ref == 1)
     199        1258 :                 dns_packet_free(p);
     200             :         else
     201           0 :                 p->n_ref--;
     202             : 
     203        1258 :         return NULL;
     204             : }
     205             : 
     206           0 : int dns_packet_validate(DnsPacket *p) {
     207           0 :         assert(p);
     208             : 
     209           0 :         if (p->size < DNS_PACKET_HEADER_SIZE)
     210           0 :                 return -EBADMSG;
     211             : 
     212           0 :         if (p->size > DNS_PACKET_SIZE_MAX)
     213           0 :                 return -EBADMSG;
     214             : 
     215           0 :         return 1;
     216             : }
     217             : 
     218           0 : int dns_packet_validate_reply(DnsPacket *p) {
     219             :         int r;
     220             : 
     221           0 :         assert(p);
     222             : 
     223           0 :         r = dns_packet_validate(p);
     224           0 :         if (r < 0)
     225           0 :                 return r;
     226             : 
     227           0 :         if (DNS_PACKET_QR(p) != 1)
     228           0 :                 return 0;
     229             : 
     230           0 :         if (DNS_PACKET_OPCODE(p) != 0)
     231           0 :                 return -EBADMSG;
     232             : 
     233           0 :         switch (p->protocol) {
     234             : 
     235           0 :         case DNS_PROTOCOL_LLMNR:
     236             :                 /* RFC 4795, Section 2.1.1. says to discard all replies with QDCOUNT != 1 */
     237           0 :                 if (DNS_PACKET_QDCOUNT(p) != 1)
     238           0 :                         return -EBADMSG;
     239             : 
     240           0 :                 break;
     241             : 
     242           0 :         case DNS_PROTOCOL_MDNS:
     243             :                 /* RFC 6762, Section 18 */
     244           0 :                 if (DNS_PACKET_RCODE(p) != 0)
     245           0 :                         return -EBADMSG;
     246             : 
     247           0 :                 break;
     248             : 
     249           0 :         default:
     250           0 :                 break;
     251             :         }
     252             : 
     253           0 :         return 1;
     254             : }
     255             : 
     256           0 : int dns_packet_validate_query(DnsPacket *p) {
     257             :         int r;
     258             : 
     259           0 :         assert(p);
     260             : 
     261           0 :         r = dns_packet_validate(p);
     262           0 :         if (r < 0)
     263           0 :                 return r;
     264             : 
     265           0 :         if (DNS_PACKET_QR(p) != 0)
     266           0 :                 return 0;
     267             : 
     268           0 :         if (DNS_PACKET_OPCODE(p) != 0)
     269           0 :                 return -EBADMSG;
     270             : 
     271           0 :         if (DNS_PACKET_TC(p))
     272           0 :                 return -EBADMSG;
     273             : 
     274           0 :         switch (p->protocol) {
     275             : 
     276           0 :         case DNS_PROTOCOL_LLMNR:
     277             :         case DNS_PROTOCOL_DNS:
     278             :                 /* RFC 4795, Section 2.1.1. says to discard all queries with QDCOUNT != 1 */
     279           0 :                 if (DNS_PACKET_QDCOUNT(p) != 1)
     280           0 :                         return -EBADMSG;
     281             : 
     282             :                 /* RFC 4795, Section 2.1.1. says to discard all queries with ANCOUNT != 0 */
     283           0 :                 if (DNS_PACKET_ANCOUNT(p) > 0)
     284           0 :                         return -EBADMSG;
     285             : 
     286             :                 /* RFC 4795, Section 2.1.1. says to discard all queries with NSCOUNT != 0 */
     287           0 :                 if (DNS_PACKET_NSCOUNT(p) > 0)
     288           0 :                         return -EBADMSG;
     289             : 
     290           0 :                 break;
     291             : 
     292           0 :         case DNS_PROTOCOL_MDNS:
     293             :                 /* RFC 6762, Section 18 */
     294           0 :                 if (DNS_PACKET_AA(p)    != 0 ||
     295           0 :                     DNS_PACKET_RD(p)    != 0 ||
     296           0 :                     DNS_PACKET_RA(p)    != 0 ||
     297           0 :                     DNS_PACKET_AD(p)    != 0 ||
     298           0 :                     DNS_PACKET_CD(p)    != 0 ||
     299           0 :                     DNS_PACKET_RCODE(p) != 0)
     300           0 :                         return -EBADMSG;
     301             : 
     302           0 :                 break;
     303             : 
     304           0 :         default:
     305           0 :                 break;
     306             :         }
     307             : 
     308           0 :         return 1;
     309             : }
     310             : 
     311        3403 : static int dns_packet_extend(DnsPacket *p, size_t add, void **ret, size_t *start) {
     312        3403 :         assert(p);
     313             : 
     314        3403 :         if (p->size + add > p->allocated) {
     315             :                 size_t a, ms;
     316             : 
     317         242 :                 a = PAGE_ALIGN((p->size + add) * 2);
     318             : 
     319         242 :                 ms = dns_packet_size_max(p);
     320         242 :                 if (a > ms)
     321           0 :                         a = ms;
     322             : 
     323         242 :                 if (p->size + add > a)
     324           0 :                         return -EMSGSIZE;
     325             : 
     326         242 :                 if (p->_data) {
     327             :                         void *d;
     328             : 
     329           0 :                         d = realloc(p->_data, a);
     330           0 :                         if (!d)
     331           0 :                                 return -ENOMEM;
     332             : 
     333           0 :                         p->_data = d;
     334             :                 } else {
     335         242 :                         p->_data = malloc(a);
     336         242 :                         if (!p->_data)
     337           0 :                                 return -ENOMEM;
     338             : 
     339         242 :                         memcpy(p->_data, (uint8_t*) p + ALIGN(sizeof(DnsPacket)), p->size);
     340         242 :                         memzero((uint8_t*) p->_data + p->size, a - p->size);
     341             :                 }
     342             : 
     343         242 :                 p->allocated = a;
     344             :         }
     345             : 
     346        3403 :         if (start)
     347        1185 :                 *start = p->size;
     348             : 
     349        3403 :         if (ret)
     350        3403 :                 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->size;
     351             : 
     352        3403 :         p->size += add;
     353        3403 :         return 0;
     354             : }
     355             : 
     356           0 : void dns_packet_truncate(DnsPacket *p, size_t sz) {
     357             :         Iterator i;
     358             :         char *s;
     359             :         void *n;
     360             : 
     361           0 :         assert(p);
     362             : 
     363           0 :         if (p->size <= sz)
     364           0 :                 return;
     365             : 
     366           0 :         HASHMAP_FOREACH_KEY(n, s, p->names, i) {
     367             : 
     368           0 :                 if (PTR_TO_SIZE(n) < sz)
     369           0 :                         continue;
     370             : 
     371           0 :                 hashmap_remove(p->names, s);
     372           0 :                 free(s);
     373             :         }
     374             : 
     375           0 :         p->size = sz;
     376             : }
     377             : 
     378         575 : int dns_packet_append_blob(DnsPacket *p, const void *d, size_t l, size_t *start) {
     379             :         void *q;
     380             :         int r;
     381             : 
     382         575 :         assert(p);
     383             : 
     384         575 :         r = dns_packet_extend(p, l, &q, start);
     385         575 :         if (r < 0)
     386           0 :                 return r;
     387             : 
     388         575 :         memcpy_safe(q, d, l);
     389         575 :         return 0;
     390             : }
     391             : 
     392         513 : int dns_packet_append_uint8(DnsPacket *p, uint8_t v, size_t *start) {
     393             :         void *d;
     394             :         int r;
     395             : 
     396         513 :         assert(p);
     397             : 
     398         513 :         r = dns_packet_extend(p, sizeof(uint8_t), &d, start);
     399         513 :         if (r < 0)
     400           0 :                 return r;
     401             : 
     402         513 :         ((uint8_t*) d)[0] = v;
     403             : 
     404         513 :         return 0;
     405             : }
     406             : 
     407        1014 : int dns_packet_append_uint16(DnsPacket *p, uint16_t v, size_t *start) {
     408             :         void *d;
     409             :         int r;
     410             : 
     411        1014 :         assert(p);
     412             : 
     413        1014 :         r = dns_packet_extend(p, sizeof(uint16_t), &d, start);
     414        1014 :         if (r < 0)
     415           0 :                 return r;
     416             : 
     417        1014 :         unaligned_write_be16(d, v);
     418             : 
     419        1014 :         return 0;
     420             : }
     421             : 
     422         330 : int dns_packet_append_uint32(DnsPacket *p, uint32_t v, size_t *start) {
     423             :         void *d;
     424             :         int r;
     425             : 
     426         330 :         assert(p);
     427             : 
     428         330 :         r = dns_packet_extend(p, sizeof(uint32_t), &d, start);
     429         330 :         if (r < 0)
     430           0 :                 return r;
     431             : 
     432         330 :         unaligned_write_be32(d, v);
     433             : 
     434         330 :         return 0;
     435             : }
     436             : 
     437          10 : int dns_packet_append_string(DnsPacket *p, const char *s, size_t *start) {
     438          10 :         assert(p);
     439          10 :         assert(s);
     440             : 
     441          10 :         return dns_packet_append_raw_string(p, s, strlen(s), start);
     442             : }
     443             : 
     444          28 : int dns_packet_append_raw_string(DnsPacket *p, const void *s, size_t size, size_t *start) {
     445             :         void *d;
     446             :         int r;
     447             : 
     448          28 :         assert(p);
     449          28 :         assert(s || size == 0);
     450             : 
     451          28 :         if (size > 255)
     452           0 :                 return -E2BIG;
     453             : 
     454          28 :         r = dns_packet_extend(p, 1 + size, &d, start);
     455          28 :         if (r < 0)
     456           0 :                 return r;
     457             : 
     458          28 :         ((uint8_t*) d)[0] = (uint8_t) size;
     459             : 
     460          28 :         memcpy_safe(((uint8_t*) d) + 1, s, size);
     461             : 
     462          28 :         return 0;
     463             : }
     464             : 
     465         943 : int dns_packet_append_label(DnsPacket *p, const char *d, size_t l, bool canonical_candidate, size_t *start) {
     466             :         uint8_t *w;
     467             :         int r;
     468             : 
     469             :         /* Append a label to a packet. Optionally, does this in DNSSEC
     470             :          * canonical form, if this label is marked as a candidate for
     471             :          * it, and the canonical form logic is enabled for the
     472             :          * packet */
     473             : 
     474         943 :         assert(p);
     475         943 :         assert(d);
     476             : 
     477         943 :         if (l > DNS_LABEL_MAX)
     478           0 :                 return -E2BIG;
     479             : 
     480         943 :         r = dns_packet_extend(p, 1 + l, (void**) &w, start);
     481         943 :         if (r < 0)
     482           0 :                 return r;
     483             : 
     484         943 :         *(w++) = (uint8_t) l;
     485             : 
     486        1182 :         if (p->canonical_form && canonical_candidate) {
     487             :                 size_t i;
     488             : 
     489             :                 /* Generate in canonical form, as defined by DNSSEC
     490             :                  * RFC 4034, Section 6.2, i.e. all lower-case. */
     491             : 
     492        1700 :                 for (i = 0; i < l; i++)
     493        1461 :                         w[i] = (uint8_t) ascii_tolower(d[i]);
     494             :         } else
     495             :                 /* Otherwise, just copy the string unaltered. This is
     496             :                  * essential for DNS-SD, where the casing of labels
     497             :                  * matters and needs to be retained. */
     498         704 :                 memcpy(w, d, l);
     499             : 
     500         943 :         return 0;
     501             : }
     502             : 
     503         389 : int dns_packet_append_name(
     504             :                 DnsPacket *p,
     505             :                 const char *name,
     506             :                 bool allow_compression,
     507             :                 bool canonical_candidate,
     508             :                 size_t *start) {
     509             : 
     510             :         size_t saved_size;
     511             :         int r;
     512             : 
     513         389 :         assert(p);
     514         389 :         assert(name);
     515             : 
     516         389 :         if (p->refuse_compression)
     517         389 :                 allow_compression = false;
     518             : 
     519         389 :         saved_size = p->size;
     520             : 
     521        1332 :         while (!dns_name_is_root(name)) {
     522         943 :                 const char *z = name;
     523             :                 char label[DNS_LABEL_MAX];
     524         943 :                 size_t n = 0;
     525             : 
     526         943 :                 if (allow_compression)
     527           0 :                         n = PTR_TO_SIZE(hashmap_get(p->names, name));
     528         943 :                 if (n > 0) {
     529           0 :                         assert(n < p->size);
     530             : 
     531           0 :                         if (n < 0x4000) {
     532           0 :                                 r = dns_packet_append_uint16(p, 0xC000 | n, NULL);
     533           0 :                                 if (r < 0)
     534           0 :                                         goto fail;
     535             : 
     536           0 :                                 goto done;
     537             :                         }
     538             :                 }
     539             : 
     540         943 :                 r = dns_label_unescape(&name, label, sizeof label, 0);
     541         943 :                 if (r < 0)
     542           0 :                         goto fail;
     543             : 
     544         943 :                 r = dns_packet_append_label(p, label, r, canonical_candidate, &n);
     545         943 :                 if (r < 0)
     546           0 :                         goto fail;
     547             : 
     548         943 :                 if (allow_compression) {
     549           0 :                         _cleanup_free_ char *s = NULL;
     550             : 
     551           0 :                         s = strdup(z);
     552           0 :                         if (!s) {
     553           0 :                                 r = -ENOMEM;
     554           0 :                                 goto fail;
     555             :                         }
     556             : 
     557           0 :                         r = hashmap_ensure_allocated(&p->names, &dns_name_hash_ops);
     558           0 :                         if (r < 0)
     559           0 :                                 goto fail;
     560             : 
     561           0 :                         r = hashmap_put(p->names, s, SIZE_TO_PTR(n));
     562           0 :                         if (r < 0)
     563           0 :                                 goto fail;
     564             : 
     565           0 :                         s = NULL;
     566             :                 }
     567             :         }
     568             : 
     569         389 :         r = dns_packet_append_uint8(p, 0, NULL);
     570         389 :         if (r < 0)
     571           0 :                 return r;
     572             : 
     573         389 : done:
     574         389 :         if (start)
     575           0 :                 *start = saved_size;
     576             : 
     577         389 :         return 0;
     578             : 
     579           0 : fail:
     580           0 :         dns_packet_truncate(p, saved_size);
     581           0 :         return r;
     582             : }
     583             : 
     584         242 : int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *k, const DnsAnswerFlags flags, size_t *start) {
     585             :         size_t saved_size;
     586             :         uint16_t class;
     587             :         int r;
     588             : 
     589         242 :         assert(p);
     590         242 :         assert(k);
     591             : 
     592         242 :         saved_size = p->size;
     593             : 
     594         242 :         r = dns_packet_append_name(p, dns_resource_key_name(k), true, true, NULL);
     595         242 :         if (r < 0)
     596           0 :                 goto fail;
     597             : 
     598         242 :         r = dns_packet_append_uint16(p, k->type, NULL);
     599         242 :         if (r < 0)
     600           0 :                 goto fail;
     601             : 
     602         242 :         class = flags & DNS_ANSWER_CACHE_FLUSH ? k->class | MDNS_RR_CACHE_FLUSH : k->class;
     603         242 :         r = dns_packet_append_uint16(p, class, NULL);
     604         242 :         if (r < 0)
     605           0 :                 goto fail;
     606             : 
     607         242 :         if (start)
     608           0 :                 *start = saved_size;
     609             : 
     610         242 :         return 0;
     611             : 
     612           0 : fail:
     613           0 :         dns_packet_truncate(p, saved_size);
     614           0 :         return r;
     615             : }
     616             : 
     617          14 : static int dns_packet_append_type_window(DnsPacket *p, uint8_t window, uint8_t length, const uint8_t *types, size_t *start) {
     618             :         size_t saved_size;
     619             :         int r;
     620             : 
     621          14 :         assert(p);
     622          14 :         assert(types);
     623          14 :         assert(length > 0);
     624             : 
     625          14 :         saved_size = p->size;
     626             : 
     627          14 :         r = dns_packet_append_uint8(p, window, NULL);
     628          14 :         if (r < 0)
     629           0 :                 goto fail;
     630             : 
     631          14 :         r = dns_packet_append_uint8(p, length, NULL);
     632          14 :         if (r < 0)
     633           0 :                 goto fail;
     634             : 
     635          14 :         r = dns_packet_append_blob(p, types, length, NULL);
     636          14 :         if (r < 0)
     637           0 :                 goto fail;
     638             : 
     639          14 :         if (start)
     640           0 :                 *start = saved_size;
     641             : 
     642          14 :         return 0;
     643           0 : fail:
     644           0 :         dns_packet_truncate(p, saved_size);
     645           0 :         return r;
     646             : }
     647             : 
     648          13 : static int dns_packet_append_types(DnsPacket *p, Bitmap *types, size_t *start) {
     649             :         Iterator i;
     650          13 :         uint8_t window = 0;
     651          13 :         uint8_t entry = 0;
     652          13 :         uint8_t bitmaps[32] = {};
     653             :         unsigned n;
     654             :         size_t saved_size;
     655             :         int r;
     656             : 
     657          13 :         assert(p);
     658             : 
     659          13 :         saved_size = p->size;
     660             : 
     661          92 :         BITMAP_FOREACH(n, types, i) {
     662          79 :                 assert(n <= 0xffff);
     663             : 
     664          79 :                 if ((n >> 8) != window && bitmaps[entry / 8] != 0) {
     665           1 :                         r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL);
     666           1 :                         if (r < 0)
     667           0 :                                 goto fail;
     668             : 
     669           1 :                         zero(bitmaps);
     670             :                 }
     671             : 
     672          79 :                 window = n >> 8;
     673          79 :                 entry = n & 255;
     674             : 
     675          79 :                 bitmaps[entry / 8] |= 1 << (7 - (entry % 8));
     676             :         }
     677             : 
     678          13 :         if (bitmaps[entry / 8] != 0) {
     679          13 :                 r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL);
     680          13 :                 if (r < 0)
     681           0 :                         goto fail;
     682             :         }
     683             : 
     684          13 :         if (start)
     685           0 :                 *start = saved_size;
     686             : 
     687          13 :         return 0;
     688           0 : fail:
     689           0 :         dns_packet_truncate(p, saved_size);
     690           0 :         return r;
     691             : }
     692             : 
     693             : /* Append the OPT pseudo-RR described in RFC6891 */
     694           0 : int dns_packet_append_opt(DnsPacket *p, uint16_t max_udp_size, bool edns0_do, int rcode, size_t *start) {
     695             :         size_t saved_size;
     696             :         int r;
     697             : 
     698           0 :         assert(p);
     699             :         /* we must never advertise supported packet size smaller than the legacy max */
     700           0 :         assert(max_udp_size >= DNS_PACKET_UNICAST_SIZE_MAX);
     701           0 :         assert(rcode >= 0);
     702           0 :         assert(rcode <= _DNS_RCODE_MAX);
     703             : 
     704           0 :         if (p->opt_start != (size_t) -1)
     705           0 :                 return -EBUSY;
     706             : 
     707           0 :         assert(p->opt_size == (size_t) -1);
     708             : 
     709           0 :         saved_size = p->size;
     710             : 
     711             :         /* empty name */
     712           0 :         r = dns_packet_append_uint8(p, 0, NULL);
     713           0 :         if (r < 0)
     714           0 :                 return r;
     715             : 
     716             :         /* type */
     717           0 :         r = dns_packet_append_uint16(p, DNS_TYPE_OPT, NULL);
     718           0 :         if (r < 0)
     719           0 :                 goto fail;
     720             : 
     721             :         /* class: maximum udp packet that can be received */
     722           0 :         r = dns_packet_append_uint16(p, max_udp_size, NULL);
     723           0 :         if (r < 0)
     724           0 :                 goto fail;
     725             : 
     726             :         /* extended RCODE and VERSION */
     727           0 :         r = dns_packet_append_uint16(p, ((uint16_t) rcode & 0x0FF0) << 4, NULL);
     728           0 :         if (r < 0)
     729           0 :                 goto fail;
     730             : 
     731             :         /* flags: DNSSEC OK (DO), see RFC3225 */
     732           0 :         r = dns_packet_append_uint16(p, edns0_do ? EDNS0_OPT_DO : 0, NULL);
     733           0 :         if (r < 0)
     734           0 :                 goto fail;
     735             : 
     736             :         /* RDLENGTH */
     737           0 :         if (edns0_do && !DNS_PACKET_QR(p)) {
     738             :                 /* If DO is on and this is not a reply, also append RFC6975 Algorithm data */
     739             : 
     740             :                 static const uint8_t rfc6975[] = {
     741             : 
     742             :                         0, 5, /* OPTION_CODE: DAU */
     743             : #if HAVE_GCRYPT && GCRYPT_VERSION_NUMBER >= 0x010600
     744             :                         0, 7, /* LIST_LENGTH */
     745             : #else
     746             :                         0, 6, /* LIST_LENGTH */
     747             : #endif
     748             :                         DNSSEC_ALGORITHM_RSASHA1,
     749             :                         DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1,
     750             :                         DNSSEC_ALGORITHM_RSASHA256,
     751             :                         DNSSEC_ALGORITHM_RSASHA512,
     752             :                         DNSSEC_ALGORITHM_ECDSAP256SHA256,
     753             :                         DNSSEC_ALGORITHM_ECDSAP384SHA384,
     754             : #if HAVE_GCRYPT && GCRYPT_VERSION_NUMBER >= 0x010600
     755             :                         DNSSEC_ALGORITHM_ED25519,
     756             : #endif
     757             : 
     758             :                         0, 6, /* OPTION_CODE: DHU */
     759             :                         0, 3, /* LIST_LENGTH */
     760             :                         DNSSEC_DIGEST_SHA1,
     761             :                         DNSSEC_DIGEST_SHA256,
     762             :                         DNSSEC_DIGEST_SHA384,
     763             : 
     764             :                         0, 7, /* OPTION_CODE: N3U */
     765             :                         0, 1, /* LIST_LENGTH */
     766             :                         NSEC3_ALGORITHM_SHA1,
     767             :                 };
     768             : 
     769           0 :                 r = dns_packet_append_uint16(p, sizeof(rfc6975), NULL);
     770           0 :                 if (r < 0)
     771           0 :                         goto fail;
     772             : 
     773           0 :                 r = dns_packet_append_blob(p, rfc6975, sizeof(rfc6975), NULL);
     774             :         } else
     775           0 :                 r = dns_packet_append_uint16(p, 0, NULL);
     776           0 :         if (r < 0)
     777           0 :                 goto fail;
     778             : 
     779           0 :         DNS_PACKET_HEADER(p)->arcount = htobe16(DNS_PACKET_ARCOUNT(p) + 1);
     780             : 
     781           0 :         p->opt_start = saved_size;
     782           0 :         p->opt_size = p->size - saved_size;
     783             : 
     784           0 :         if (start)
     785           0 :                 *start = saved_size;
     786             : 
     787           0 :         return 0;
     788             : 
     789           0 : fail:
     790           0 :         dns_packet_truncate(p, saved_size);
     791           0 :         return r;
     792             : }
     793             : 
     794           0 : int dns_packet_truncate_opt(DnsPacket *p) {
     795           0 :         assert(p);
     796             : 
     797           0 :         if (p->opt_start == (size_t) -1) {
     798           0 :                 assert(p->opt_size == (size_t) -1);
     799           0 :                 return 0;
     800             :         }
     801             : 
     802           0 :         assert(p->opt_size != (size_t) -1);
     803           0 :         assert(DNS_PACKET_ARCOUNT(p) > 0);
     804             : 
     805           0 :         if (p->opt_start + p->opt_size != p->size)
     806           0 :                 return -EBUSY;
     807             : 
     808           0 :         dns_packet_truncate(p, p->opt_start);
     809           0 :         DNS_PACKET_HEADER(p)->arcount = htobe16(DNS_PACKET_ARCOUNT(p) - 1);
     810           0 :         p->opt_start = p->opt_size = (size_t) -1;
     811             : 
     812           0 :         return 1;
     813             : }
     814             : 
     815         242 : int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, const DnsAnswerFlags flags, size_t *start, size_t *rdata_start) {
     816             : 
     817             :         size_t saved_size, rdlength_offset, end, rdlength, rds;
     818             :         uint32_t ttl;
     819             :         int r;
     820             : 
     821         242 :         assert(p);
     822         242 :         assert(rr);
     823             : 
     824         242 :         saved_size = p->size;
     825             : 
     826         242 :         r = dns_packet_append_key(p, rr->key, flags, NULL);
     827         242 :         if (r < 0)
     828           0 :                 goto fail;
     829             : 
     830         242 :         ttl = flags & DNS_ANSWER_GOODBYE ? 0 : rr->ttl;
     831         242 :         r = dns_packet_append_uint32(p, ttl, NULL);
     832         242 :         if (r < 0)
     833           0 :                 goto fail;
     834             : 
     835             :         /* Initially we write 0 here */
     836         242 :         r = dns_packet_append_uint16(p, 0, &rdlength_offset);
     837         242 :         if (r < 0)
     838           0 :                 goto fail;
     839             : 
     840         242 :         rds = p->size - saved_size;
     841             : 
     842         242 :         switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
     843             : 
     844           0 :         case DNS_TYPE_SRV:
     845           0 :                 r = dns_packet_append_uint16(p, rr->srv.priority, NULL);
     846           0 :                 if (r < 0)
     847           0 :                         goto fail;
     848             : 
     849           0 :                 r = dns_packet_append_uint16(p, rr->srv.weight, NULL);
     850           0 :                 if (r < 0)
     851           0 :                         goto fail;
     852             : 
     853           0 :                 r = dns_packet_append_uint16(p, rr->srv.port, NULL);
     854           0 :                 if (r < 0)
     855           0 :                         goto fail;
     856             : 
     857             :                 /* RFC 2782 states "Unless and until permitted by future standards
     858             :                  * action, name compression is not to be used for this field." */
     859           0 :                 r = dns_packet_append_name(p, rr->srv.name, false, false, NULL);
     860           0 :                 break;
     861             : 
     862          76 :         case DNS_TYPE_PTR:
     863             :         case DNS_TYPE_NS:
     864             :         case DNS_TYPE_CNAME:
     865             :         case DNS_TYPE_DNAME:
     866          76 :                 r = dns_packet_append_name(p, rr->ptr.name, true, false, NULL);
     867          76 :                 break;
     868             : 
     869           0 :         case DNS_TYPE_HINFO:
     870           0 :                 r = dns_packet_append_string(p, rr->hinfo.cpu, NULL);
     871           0 :                 if (r < 0)
     872           0 :                         goto fail;
     873             : 
     874           0 :                 r = dns_packet_append_string(p, rr->hinfo.os, NULL);
     875           0 :                 break;
     876             : 
     877          18 :         case DNS_TYPE_SPF: /* exactly the same as TXT */
     878             :         case DNS_TYPE_TXT:
     879             : 
     880          18 :                 if (!rr->txt.items) {
     881             :                         /* RFC 6763, section 6.1 suggests to generate
     882             :                          * single empty string for an empty array. */
     883             : 
     884           0 :                         r = dns_packet_append_raw_string(p, NULL, 0, NULL);
     885           0 :                         if (r < 0)
     886           0 :                                 goto fail;
     887          18 :                 } else {
     888             :                         DnsTxtItem *i;
     889             : 
     890          36 :                         LIST_FOREACH(items, i, rr->txt.items) {
     891          18 :                                 r = dns_packet_append_raw_string(p, i->data, i->length, NULL);
     892          18 :                                 if (r < 0)
     893           0 :                                         goto fail;
     894             :                         }
     895             :                 }
     896             : 
     897          18 :                 r = 0;
     898          18 :                 break;
     899             : 
     900          29 :         case DNS_TYPE_A:
     901          29 :                 r = dns_packet_append_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
     902          29 :                 break;
     903             : 
     904          14 :         case DNS_TYPE_AAAA:
     905          14 :                 r = dns_packet_append_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
     906          14 :                 break;
     907             : 
     908          14 :         case DNS_TYPE_SOA:
     909          14 :                 r = dns_packet_append_name(p, rr->soa.mname, true, false, NULL);
     910          14 :                 if (r < 0)
     911           0 :                         goto fail;
     912             : 
     913          14 :                 r = dns_packet_append_name(p, rr->soa.rname, true, false, NULL);
     914          14 :                 if (r < 0)
     915           0 :                         goto fail;
     916             : 
     917          14 :                 r = dns_packet_append_uint32(p, rr->soa.serial, NULL);
     918          14 :                 if (r < 0)
     919           0 :                         goto fail;
     920             : 
     921          14 :                 r = dns_packet_append_uint32(p, rr->soa.refresh, NULL);
     922          14 :                 if (r < 0)
     923           0 :                         goto fail;
     924             : 
     925          14 :                 r = dns_packet_append_uint32(p, rr->soa.retry, NULL);
     926          14 :                 if (r < 0)
     927           0 :                         goto fail;
     928             : 
     929          14 :                 r = dns_packet_append_uint32(p, rr->soa.expire, NULL);
     930          14 :                 if (r < 0)
     931           0 :                         goto fail;
     932             : 
     933          14 :                 r = dns_packet_append_uint32(p, rr->soa.minimum, NULL);
     934          14 :                 break;
     935             : 
     936          30 :         case DNS_TYPE_MX:
     937          30 :                 r = dns_packet_append_uint16(p, rr->mx.priority, NULL);
     938          30 :                 if (r < 0)
     939           0 :                         goto fail;
     940             : 
     941          30 :                 r = dns_packet_append_name(p, rr->mx.exchange, true, false, NULL);
     942          30 :                 break;
     943             : 
     944           6 :         case DNS_TYPE_LOC:
     945           6 :                 r = dns_packet_append_uint8(p, rr->loc.version, NULL);
     946           6 :                 if (r < 0)
     947           0 :                         goto fail;
     948             : 
     949           6 :                 r = dns_packet_append_uint8(p, rr->loc.size, NULL);
     950           6 :                 if (r < 0)
     951           0 :                         goto fail;
     952             : 
     953           6 :                 r = dns_packet_append_uint8(p, rr->loc.horiz_pre, NULL);
     954           6 :                 if (r < 0)
     955           0 :                         goto fail;
     956             : 
     957           6 :                 r = dns_packet_append_uint8(p, rr->loc.vert_pre, NULL);
     958           6 :                 if (r < 0)
     959           0 :                         goto fail;
     960             : 
     961           6 :                 r = dns_packet_append_uint32(p, rr->loc.latitude, NULL);
     962           6 :                 if (r < 0)
     963           0 :                         goto fail;
     964             : 
     965           6 :                 r = dns_packet_append_uint32(p, rr->loc.longitude, NULL);
     966           6 :                 if (r < 0)
     967           0 :                         goto fail;
     968             : 
     969           6 :                 r = dns_packet_append_uint32(p, rr->loc.altitude, NULL);
     970           6 :                 break;
     971             : 
     972           0 :         case DNS_TYPE_DS:
     973           0 :                 r = dns_packet_append_uint16(p, rr->ds.key_tag, NULL);
     974           0 :                 if (r < 0)
     975           0 :                         goto fail;
     976             : 
     977           0 :                 r = dns_packet_append_uint8(p, rr->ds.algorithm, NULL);
     978           0 :                 if (r < 0)
     979           0 :                         goto fail;
     980             : 
     981           0 :                 r = dns_packet_append_uint8(p, rr->ds.digest_type, NULL);
     982           0 :                 if (r < 0)
     983           0 :                         goto fail;
     984             : 
     985           0 :                 r = dns_packet_append_blob(p, rr->ds.digest, rr->ds.digest_size, NULL);
     986           0 :                 break;
     987             : 
     988          12 :         case DNS_TYPE_SSHFP:
     989          12 :                 r = dns_packet_append_uint8(p, rr->sshfp.algorithm, NULL);
     990          12 :                 if (r < 0)
     991           0 :                         goto fail;
     992             : 
     993          12 :                 r = dns_packet_append_uint8(p, rr->sshfp.fptype, NULL);
     994          12 :                 if (r < 0)
     995           0 :                         goto fail;
     996             : 
     997          12 :                 r = dns_packet_append_blob(p, rr->sshfp.fingerprint, rr->sshfp.fingerprint_size, NULL);
     998          12 :                 break;
     999             : 
    1000          16 :         case DNS_TYPE_DNSKEY:
    1001          16 :                 r = dns_packet_append_uint16(p, rr->dnskey.flags, NULL);
    1002          16 :                 if (r < 0)
    1003           0 :                         goto fail;
    1004             : 
    1005          16 :                 r = dns_packet_append_uint8(p, rr->dnskey.protocol, NULL);
    1006          16 :                 if (r < 0)
    1007           0 :                         goto fail;
    1008             : 
    1009          16 :                 r = dns_packet_append_uint8(p, rr->dnskey.algorithm, NULL);
    1010          16 :                 if (r < 0)
    1011           0 :                         goto fail;
    1012             : 
    1013          16 :                 r = dns_packet_append_blob(p, rr->dnskey.key, rr->dnskey.key_size, NULL);
    1014          16 :                 break;
    1015             : 
    1016           0 :         case DNS_TYPE_RRSIG:
    1017           0 :                 r = dns_packet_append_uint16(p, rr->rrsig.type_covered, NULL);
    1018           0 :                 if (r < 0)
    1019           0 :                         goto fail;
    1020             : 
    1021           0 :                 r = dns_packet_append_uint8(p, rr->rrsig.algorithm, NULL);
    1022           0 :                 if (r < 0)
    1023           0 :                         goto fail;
    1024             : 
    1025           0 :                 r = dns_packet_append_uint8(p, rr->rrsig.labels, NULL);
    1026           0 :                 if (r < 0)
    1027           0 :                         goto fail;
    1028             : 
    1029           0 :                 r = dns_packet_append_uint32(p, rr->rrsig.original_ttl, NULL);
    1030           0 :                 if (r < 0)
    1031           0 :                         goto fail;
    1032             : 
    1033           0 :                 r = dns_packet_append_uint32(p, rr->rrsig.expiration, NULL);
    1034           0 :                 if (r < 0)
    1035           0 :                         goto fail;
    1036             : 
    1037           0 :                 r = dns_packet_append_uint32(p, rr->rrsig.inception, NULL);
    1038           0 :                 if (r < 0)
    1039           0 :                         goto fail;
    1040             : 
    1041           0 :                 r = dns_packet_append_uint16(p, rr->rrsig.key_tag, NULL);
    1042           0 :                 if (r < 0)
    1043           0 :                         goto fail;
    1044             : 
    1045           0 :                 r = dns_packet_append_name(p, rr->rrsig.signer, false, true, NULL);
    1046           0 :                 if (r < 0)
    1047           0 :                         goto fail;
    1048             : 
    1049           0 :                 r = dns_packet_append_blob(p, rr->rrsig.signature, rr->rrsig.signature_size, NULL);
    1050           0 :                 break;
    1051             : 
    1052          13 :         case DNS_TYPE_NSEC:
    1053          13 :                 r = dns_packet_append_name(p, rr->nsec.next_domain_name, false, false, NULL);
    1054          13 :                 if (r < 0)
    1055           0 :                         goto fail;
    1056             : 
    1057          13 :                 r = dns_packet_append_types(p, rr->nsec.types, NULL);
    1058          13 :                 if (r < 0)
    1059           0 :                         goto fail;
    1060             : 
    1061          13 :                 break;
    1062             : 
    1063           0 :         case DNS_TYPE_NSEC3:
    1064           0 :                 r = dns_packet_append_uint8(p, rr->nsec3.algorithm, NULL);
    1065           0 :                 if (r < 0)
    1066           0 :                         goto fail;
    1067             : 
    1068           0 :                 r = dns_packet_append_uint8(p, rr->nsec3.flags, NULL);
    1069           0 :                 if (r < 0)
    1070           0 :                         goto fail;
    1071             : 
    1072           0 :                 r = dns_packet_append_uint16(p, rr->nsec3.iterations, NULL);
    1073           0 :                 if (r < 0)
    1074           0 :                         goto fail;
    1075             : 
    1076           0 :                 r = dns_packet_append_uint8(p, rr->nsec3.salt_size, NULL);
    1077           0 :                 if (r < 0)
    1078           0 :                         goto fail;
    1079             : 
    1080           0 :                 r = dns_packet_append_blob(p, rr->nsec3.salt, rr->nsec3.salt_size, NULL);
    1081           0 :                 if (r < 0)
    1082           0 :                         goto fail;
    1083             : 
    1084           0 :                 r = dns_packet_append_uint8(p, rr->nsec3.next_hashed_name_size, NULL);
    1085           0 :                 if (r < 0)
    1086           0 :                         goto fail;
    1087             : 
    1088           0 :                 r = dns_packet_append_blob(p, rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, NULL);
    1089           0 :                 if (r < 0)
    1090           0 :                         goto fail;
    1091             : 
    1092           0 :                 r = dns_packet_append_types(p, rr->nsec3.types, NULL);
    1093           0 :                 if (r < 0)
    1094           0 :                         goto fail;
    1095             : 
    1096           0 :                 break;
    1097             : 
    1098           2 :         case DNS_TYPE_TLSA:
    1099           2 :                 r = dns_packet_append_uint8(p, rr->tlsa.cert_usage, NULL);
    1100           2 :                 if (r < 0)
    1101           0 :                         goto fail;
    1102             : 
    1103           2 :                 r = dns_packet_append_uint8(p, rr->tlsa.selector, NULL);
    1104           2 :                 if (r < 0)
    1105           0 :                         goto fail;
    1106             : 
    1107           2 :                 r = dns_packet_append_uint8(p, rr->tlsa.matching_type, NULL);
    1108           2 :                 if (r < 0)
    1109           0 :                         goto fail;
    1110             : 
    1111           2 :                 r = dns_packet_append_blob(p, rr->tlsa.data, rr->tlsa.data_size, NULL);
    1112           2 :                 break;
    1113             : 
    1114          10 :         case DNS_TYPE_CAA:
    1115          10 :                 r = dns_packet_append_uint8(p, rr->caa.flags, NULL);
    1116          10 :                 if (r < 0)
    1117           0 :                         goto fail;
    1118             : 
    1119          10 :                 r = dns_packet_append_string(p, rr->caa.tag, NULL);
    1120          10 :                 if (r < 0)
    1121           0 :                         goto fail;
    1122             : 
    1123          10 :                 r = dns_packet_append_blob(p, rr->caa.value, rr->caa.value_size, NULL);
    1124          10 :                 break;
    1125             : 
    1126           2 :         case DNS_TYPE_OPT:
    1127             :         case DNS_TYPE_OPENPGPKEY:
    1128             :         case _DNS_TYPE_INVALID: /* unparseable */
    1129             :         default:
    1130             : 
    1131           2 :                 r = dns_packet_append_blob(p, rr->generic.data, rr->generic.data_size, NULL);
    1132           2 :                 break;
    1133             :         }
    1134         242 :         if (r < 0)
    1135           0 :                 goto fail;
    1136             : 
    1137             :         /* Let's calculate the actual data size and update the field */
    1138         242 :         rdlength = p->size - rdlength_offset - sizeof(uint16_t);
    1139         242 :         if (rdlength > 0xFFFF) {
    1140           0 :                 r = -ENOSPC;
    1141           0 :                 goto fail;
    1142             :         }
    1143             : 
    1144         242 :         end = p->size;
    1145         242 :         p->size = rdlength_offset;
    1146         242 :         r = dns_packet_append_uint16(p, rdlength, NULL);
    1147         242 :         if (r < 0)
    1148           0 :                 goto fail;
    1149         242 :         p->size = end;
    1150             : 
    1151         242 :         if (start)
    1152         242 :                 *start = saved_size;
    1153             : 
    1154         242 :         if (rdata_start)
    1155         242 :                 *rdata_start = rds;
    1156             : 
    1157         242 :         return 0;
    1158             : 
    1159           0 : fail:
    1160           0 :         dns_packet_truncate(p, saved_size);
    1161           0 :         return r;
    1162             : }
    1163             : 
    1164           0 : int dns_packet_append_question(DnsPacket *p, DnsQuestion *q) {
    1165             :         DnsResourceKey *key;
    1166             :         int r;
    1167             : 
    1168           0 :         assert(p);
    1169             : 
    1170           0 :         DNS_QUESTION_FOREACH(key, q) {
    1171           0 :                 r = dns_packet_append_key(p, key, 0, NULL);
    1172           0 :                 if (r < 0)
    1173           0 :                         return r;
    1174             :         }
    1175             : 
    1176           0 :         return 0;
    1177             : }
    1178             : 
    1179           0 : int dns_packet_append_answer(DnsPacket *p, DnsAnswer *a) {
    1180             :         DnsResourceRecord *rr;
    1181             :         DnsAnswerFlags flags;
    1182             :         int r;
    1183             : 
    1184           0 :         assert(p);
    1185             : 
    1186           0 :         DNS_ANSWER_FOREACH_FLAGS(rr, flags, a) {
    1187           0 :                 r = dns_packet_append_rr(p, rr, flags, NULL, NULL);
    1188           0 :                 if (r < 0)
    1189           0 :                         return r;
    1190             :         }
    1191             : 
    1192           0 :         return 0;
    1193             : }
    1194             : 
    1195        7180 : int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) {
    1196        7180 :         assert(p);
    1197             : 
    1198        7180 :         if (p->rindex + sz > p->size)
    1199           0 :                 return -EMSGSIZE;
    1200             : 
    1201        7180 :         if (ret)
    1202        7180 :                 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->rindex;
    1203             : 
    1204        7180 :         if (start)
    1205          96 :                 *start = p->rindex;
    1206             : 
    1207        7180 :         p->rindex += sz;
    1208        7180 :         return 0;
    1209             : }
    1210             : 
    1211           0 : void dns_packet_rewind(DnsPacket *p, size_t idx) {
    1212           0 :         assert(p);
    1213           0 :         assert(idx <= p->size);
    1214           0 :         assert(idx >= DNS_PACKET_HEADER_SIZE);
    1215             : 
    1216           0 :         p->rindex = idx;
    1217           0 : }
    1218             : 
    1219          84 : int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start) {
    1220             :         const void *q;
    1221             :         int r;
    1222             : 
    1223          84 :         assert(p);
    1224          84 :         assert(d);
    1225             : 
    1226          84 :         r = dns_packet_read(p, sz, &q, start);
    1227          84 :         if (r < 0)
    1228           0 :                 return r;
    1229             : 
    1230          84 :         memcpy(d, q, sz);
    1231          84 :         return 0;
    1232             : }
    1233             : 
    1234          84 : static int dns_packet_read_memdup(
    1235             :                 DnsPacket *p, size_t size,
    1236             :                 void **ret, size_t *ret_size,
    1237             :                 size_t *ret_start) {
    1238             : 
    1239             :         const void *src;
    1240             :         size_t start;
    1241             :         int r;
    1242             : 
    1243          84 :         assert(p);
    1244          84 :         assert(ret);
    1245             : 
    1246          84 :         r = dns_packet_read(p, size, &src, &start);
    1247          84 :         if (r < 0)
    1248           0 :                 return r;
    1249             : 
    1250          84 :         if (size <= 0)
    1251           0 :                 *ret = NULL;
    1252             :         else {
    1253             :                 void *copy;
    1254             : 
    1255          84 :                 copy = memdup(src, size);
    1256          84 :                 if (!copy)
    1257           0 :                         return -ENOMEM;
    1258             : 
    1259          84 :                 *ret = copy;
    1260             :         }
    1261             : 
    1262          84 :         if (ret_size)
    1263          84 :                 *ret_size = size;
    1264          84 :         if (ret_start)
    1265           0 :                 *ret_start = start;
    1266             : 
    1267          84 :         return 0;
    1268             : }
    1269             : 
    1270        2912 : int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) {
    1271             :         const void *d;
    1272             :         int r;
    1273             : 
    1274        2912 :         assert(p);
    1275             : 
    1276        2912 :         r = dns_packet_read(p, sizeof(uint8_t), &d, start);
    1277        2912 :         if (r < 0)
    1278           0 :                 return r;
    1279             : 
    1280        2912 :         *ret = ((uint8_t*) d)[0];
    1281        2912 :         return 0;
    1282             : }
    1283             : 
    1284        1516 : int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start) {
    1285             :         const void *d;
    1286             :         int r;
    1287             : 
    1288        1516 :         assert(p);
    1289             : 
    1290        1516 :         r = dns_packet_read(p, sizeof(uint16_t), &d, start);
    1291        1516 :         if (r < 0)
    1292           0 :                 return r;
    1293             : 
    1294        1516 :         *ret = unaligned_read_be16(d);
    1295             : 
    1296        1516 :         return 0;
    1297             : }
    1298             : 
    1299         652 : int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start) {
    1300             :         const void *d;
    1301             :         int r;
    1302             : 
    1303         652 :         assert(p);
    1304             : 
    1305         652 :         r = dns_packet_read(p, sizeof(uint32_t), &d, start);
    1306         652 :         if (r < 0)
    1307           0 :                 return r;
    1308             : 
    1309         652 :         *ret = unaligned_read_be32(d);
    1310             : 
    1311         652 :         return 0;
    1312             : }
    1313             : 
    1314          20 : int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start) {
    1315          20 :         _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
    1316             :         const void *d;
    1317             :         char *t;
    1318             :         uint8_t c;
    1319             :         int r;
    1320             : 
    1321          20 :         assert(p);
    1322          20 :         INIT_REWINDER(rewinder, p);
    1323             : 
    1324          20 :         r = dns_packet_read_uint8(p, &c, NULL);
    1325          20 :         if (r < 0)
    1326           0 :                 return r;
    1327             : 
    1328          20 :         r = dns_packet_read(p, c, &d, NULL);
    1329          20 :         if (r < 0)
    1330           0 :                 return r;
    1331             : 
    1332          20 :         if (memchr(d, 0, c))
    1333           0 :                 return -EBADMSG;
    1334             : 
    1335          20 :         t = strndup(d, c);
    1336          20 :         if (!t)
    1337           0 :                 return -ENOMEM;
    1338             : 
    1339          20 :         if (!utf8_is_valid(t)) {
    1340           0 :                 free(t);
    1341           0 :                 return -EBADMSG;
    1342             :         }
    1343             : 
    1344          20 :         *ret = t;
    1345             : 
    1346          20 :         if (start)
    1347           0 :                 *start = rewinder.saved_rindex;
    1348          20 :         CANCEL_REWINDER(rewinder);
    1349             : 
    1350          20 :         return 0;
    1351             : }
    1352             : 
    1353          36 : int dns_packet_read_raw_string(DnsPacket *p, const void **ret, size_t *size, size_t *start) {
    1354          36 :         _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
    1355             :         uint8_t c;
    1356             :         int r;
    1357             : 
    1358          36 :         assert(p);
    1359          36 :         INIT_REWINDER(rewinder, p);
    1360             : 
    1361          36 :         r = dns_packet_read_uint8(p, &c, NULL);
    1362          36 :         if (r < 0)
    1363           0 :                 return r;
    1364             : 
    1365          36 :         r = dns_packet_read(p, c, ret, NULL);
    1366          36 :         if (r < 0)
    1367           0 :                 return r;
    1368             : 
    1369          36 :         if (size)
    1370          36 :                 *size = c;
    1371          36 :         if (start)
    1372           0 :                 *start = rewinder.saved_rindex;
    1373          36 :         CANCEL_REWINDER(rewinder);
    1374             : 
    1375          36 :         return 0;
    1376             : }
    1377             : 
    1378         764 : int dns_packet_read_name(
    1379             :                 DnsPacket *p,
    1380             :                 char **_ret,
    1381             :                 bool allow_compression,
    1382             :                 size_t *start) {
    1383             : 
    1384         764 :         _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
    1385         764 :         size_t after_rindex = 0, jump_barrier;
    1386         764 :         _cleanup_free_ char *ret = NULL;
    1387         764 :         size_t n = 0, allocated = 0;
    1388         764 :         bool first = true;
    1389             :         int r;
    1390             : 
    1391         764 :         assert(p);
    1392         764 :         assert(_ret);
    1393         764 :         INIT_REWINDER(rewinder, p);
    1394         764 :         jump_barrier = p->rindex;
    1395             : 
    1396         764 :         if (p->refuse_compression)
    1397           0 :                 allow_compression = false;
    1398             : 
    1399        1852 :         for (;;) {
    1400             :                 uint8_t c, d;
    1401             : 
    1402        2616 :                 r = dns_packet_read_uint8(p, &c, NULL);
    1403        2616 :                 if (r < 0)
    1404           0 :                         return r;
    1405             : 
    1406        2616 :                 if (c == 0)
    1407             :                         /* End of name */
    1408         764 :                         break;
    1409        1852 :                 else if (c <= 63) {
    1410             :                         const char *label;
    1411             : 
    1412             :                         /* Literal label */
    1413        1852 :                         r = dns_packet_read(p, c, (const void**) &label, NULL);
    1414        1852 :                         if (r < 0)
    1415           0 :                                 return r;
    1416             : 
    1417        1852 :                         if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX))
    1418           0 :                                 return -ENOMEM;
    1419             : 
    1420        1852 :                         if (first)
    1421         696 :                                 first = false;
    1422             :                         else
    1423        1156 :                                 ret[n++] = '.';
    1424             : 
    1425        1852 :                         r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX);
    1426        1852 :                         if (r < 0)
    1427           0 :                                 return r;
    1428             : 
    1429        1852 :                         n += r;
    1430        1852 :                         continue;
    1431           0 :                 } else if (allow_compression && (c & 0xc0) == 0xc0) {
    1432             :                         uint16_t ptr;
    1433             : 
    1434             :                         /* Pointer */
    1435           0 :                         r = dns_packet_read_uint8(p, &d, NULL);
    1436           0 :                         if (r < 0)
    1437           0 :                                 return r;
    1438             : 
    1439           0 :                         ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
    1440           0 :                         if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= jump_barrier)
    1441           0 :                                 return -EBADMSG;
    1442             : 
    1443           0 :                         if (after_rindex == 0)
    1444           0 :                                 after_rindex = p->rindex;
    1445             : 
    1446             :                         /* Jumps are limited to a "prior occurrence" (RFC-1035 4.1.4) */
    1447           0 :                         jump_barrier = ptr;
    1448           0 :                         p->rindex = ptr;
    1449             :                 } else
    1450           0 :                         return -EBADMSG;
    1451             :         }
    1452             : 
    1453         764 :         if (!GREEDY_REALLOC(ret, allocated, n + 1))
    1454           0 :                 return -ENOMEM;
    1455             : 
    1456         764 :         ret[n] = 0;
    1457             : 
    1458         764 :         if (after_rindex != 0)
    1459           0 :                 p->rindex= after_rindex;
    1460             : 
    1461         764 :         *_ret = TAKE_PTR(ret);
    1462             : 
    1463         764 :         if (start)
    1464           0 :                 *start = rewinder.saved_rindex;
    1465         764 :         CANCEL_REWINDER(rewinder);
    1466             : 
    1467         764 :         return 0;
    1468             : }
    1469             : 
    1470          24 : static int dns_packet_read_type_window(DnsPacket *p, Bitmap **types, size_t *start) {
    1471             :         uint8_t window;
    1472             :         uint8_t length;
    1473             :         const uint8_t *bitmap;
    1474          24 :         uint8_t bit = 0;
    1475             :         unsigned i;
    1476          24 :         bool found = false;
    1477          24 :         _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
    1478             :         int r;
    1479             : 
    1480          24 :         assert(p);
    1481          24 :         assert(types);
    1482          24 :         INIT_REWINDER(rewinder, p);
    1483             : 
    1484          24 :         r = bitmap_ensure_allocated(types);
    1485          24 :         if (r < 0)
    1486           0 :                 return r;
    1487             : 
    1488          24 :         r = dns_packet_read_uint8(p, &window, NULL);
    1489          24 :         if (r < 0)
    1490           0 :                 return r;
    1491             : 
    1492          24 :         r = dns_packet_read_uint8(p, &length, NULL);
    1493          24 :         if (r < 0)
    1494           0 :                 return r;
    1495             : 
    1496          24 :         if (length == 0 || length > 32)
    1497           0 :                 return -EBADMSG;
    1498             : 
    1499          24 :         r = dns_packet_read(p, length, (const void **)&bitmap, NULL);
    1500          24 :         if (r < 0)
    1501           0 :                 return r;
    1502             : 
    1503         220 :         for (i = 0; i < length; i++) {
    1504         196 :                 uint8_t bitmask = 1 << 7;
    1505             : 
    1506         196 :                 if (!bitmap[i]) {
    1507         108 :                         found = false;
    1508         108 :                         bit += 8;
    1509         108 :                         continue;
    1510             :                 }
    1511             : 
    1512          88 :                 found = true;
    1513             : 
    1514         792 :                 for (; bitmask; bit++, bitmask >>= 1)
    1515         704 :                         if (bitmap[i] & bitmask) {
    1516             :                                 uint16_t n;
    1517             : 
    1518         140 :                                 n = (uint16_t) window << 8 | (uint16_t) bit;
    1519             : 
    1520             :                                 /* Ignore pseudo-types. see RFC4034 section 4.1.2 */
    1521         140 :                                 if (dns_type_is_pseudo(n))
    1522           0 :                                         continue;
    1523             : 
    1524         140 :                                 r = bitmap_set(*types, n);
    1525         140 :                                 if (r < 0)
    1526           0 :                                         return r;
    1527             :                         }
    1528             :         }
    1529             : 
    1530          24 :         if (!found)
    1531           0 :                 return -EBADMSG;
    1532             : 
    1533          24 :         if (start)
    1534           0 :                 *start = rewinder.saved_rindex;
    1535          24 :         CANCEL_REWINDER(rewinder);
    1536             : 
    1537          24 :         return 0;
    1538             : }
    1539             : 
    1540          24 : static int dns_packet_read_type_windows(DnsPacket *p, Bitmap **types, size_t size, size_t *start) {
    1541          24 :         _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
    1542             :         int r;
    1543             : 
    1544          24 :         INIT_REWINDER(rewinder, p);
    1545             : 
    1546          48 :         while (p->rindex < rewinder.saved_rindex + size) {
    1547          24 :                 r = dns_packet_read_type_window(p, types, NULL);
    1548          24 :                 if (r < 0)
    1549           0 :                         return r;
    1550             : 
    1551             :                 /* don't read past end of current RR */
    1552          24 :                 if (p->rindex > rewinder.saved_rindex + size)
    1553           0 :                         return -EBADMSG;
    1554             :         }
    1555             : 
    1556          24 :         if (p->rindex != rewinder.saved_rindex + size)
    1557           0 :                 return -EBADMSG;
    1558             : 
    1559          24 :         if (start)
    1560           0 :                 *start = rewinder.saved_rindex;
    1561          24 :         CANCEL_REWINDER(rewinder);
    1562             : 
    1563          24 :         return 0;
    1564             : }
    1565             : 
    1566         476 : int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, bool *ret_cache_flush, size_t *start) {
    1567         476 :         _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
    1568         476 :         _cleanup_free_ char *name = NULL;
    1569         476 :         bool cache_flush = false;
    1570             :         uint16_t class, type;
    1571             :         DnsResourceKey *key;
    1572             :         int r;
    1573             : 
    1574         476 :         assert(p);
    1575         476 :         assert(ret);
    1576         476 :         INIT_REWINDER(rewinder, p);
    1577             : 
    1578         476 :         r = dns_packet_read_name(p, &name, true, NULL);
    1579         476 :         if (r < 0)
    1580           0 :                 return r;
    1581             : 
    1582         476 :         r = dns_packet_read_uint16(p, &type, NULL);
    1583         476 :         if (r < 0)
    1584           0 :                 return r;
    1585             : 
    1586         476 :         r = dns_packet_read_uint16(p, &class, NULL);
    1587         476 :         if (r < 0)
    1588           0 :                 return r;
    1589             : 
    1590         476 :         if (p->protocol == DNS_PROTOCOL_MDNS) {
    1591             :                 /* See RFC6762, Section 10.2 */
    1592             : 
    1593           0 :                 if (type != DNS_TYPE_OPT && (class & MDNS_RR_CACHE_FLUSH)) {
    1594           0 :                         class &= ~MDNS_RR_CACHE_FLUSH;
    1595           0 :                         cache_flush = true;
    1596             :                 }
    1597             :         }
    1598             : 
    1599         476 :         key = dns_resource_key_new_consume(class, type, name);
    1600         476 :         if (!key)
    1601           0 :                 return -ENOMEM;
    1602             : 
    1603         476 :         name = NULL;
    1604         476 :         *ret = key;
    1605             : 
    1606         476 :         if (ret_cache_flush)
    1607         476 :                 *ret_cache_flush = cache_flush;
    1608         476 :         if (start)
    1609           0 :                 *start = rewinder.saved_rindex;
    1610         476 :         CANCEL_REWINDER(rewinder);
    1611             : 
    1612         476 :         return 0;
    1613             : }
    1614             : 
    1615          36 : static bool loc_size_ok(uint8_t size) {
    1616          36 :         uint8_t m = size >> 4, e = size & 0xF;
    1617             : 
    1618          36 :         return m <= 9 && e <= 9 && (m > 0 || e == 0);
    1619             : }
    1620             : 
    1621         476 : int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, bool *ret_cache_flush, size_t *start) {
    1622         476 :         _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
    1623         476 :         _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
    1624         476 :         _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
    1625             :         size_t offset;
    1626             :         uint16_t rdlength;
    1627             :         bool cache_flush;
    1628             :         int r;
    1629             : 
    1630         476 :         assert(p);
    1631         476 :         assert(ret);
    1632             : 
    1633         476 :         INIT_REWINDER(rewinder, p);
    1634             : 
    1635         476 :         r = dns_packet_read_key(p, &key, &cache_flush, NULL);
    1636         476 :         if (r < 0)
    1637           0 :                 return r;
    1638             : 
    1639         476 :         if (!dns_class_is_valid_rr(key->class) || !dns_type_is_valid_rr(key->type))
    1640           0 :                 return -EBADMSG;
    1641             : 
    1642         476 :         rr = dns_resource_record_new(key);
    1643         476 :         if (!rr)
    1644           0 :                 return -ENOMEM;
    1645             : 
    1646         476 :         r = dns_packet_read_uint32(p, &rr->ttl, NULL);
    1647         476 :         if (r < 0)
    1648           0 :                 return r;
    1649             : 
    1650             :         /* RFC 2181, Section 8, suggests to
    1651             :          * treat a TTL with the MSB set as a zero TTL. */
    1652         476 :         if (rr->ttl & UINT32_C(0x80000000))
    1653           0 :                 rr->ttl = 0;
    1654             : 
    1655         476 :         r = dns_packet_read_uint16(p, &rdlength, NULL);
    1656         476 :         if (r < 0)
    1657           0 :                 return r;
    1658             : 
    1659         476 :         if (p->rindex + rdlength > p->size)
    1660           0 :                 return -EBADMSG;
    1661             : 
    1662         476 :         offset = p->rindex;
    1663             : 
    1664         476 :         switch (rr->key->type) {
    1665             : 
    1666           0 :         case DNS_TYPE_SRV:
    1667           0 :                 r = dns_packet_read_uint16(p, &rr->srv.priority, NULL);
    1668           0 :                 if (r < 0)
    1669           0 :                         return r;
    1670           0 :                 r = dns_packet_read_uint16(p, &rr->srv.weight, NULL);
    1671           0 :                 if (r < 0)
    1672           0 :                         return r;
    1673           0 :                 r = dns_packet_read_uint16(p, &rr->srv.port, NULL);
    1674           0 :                 if (r < 0)
    1675           0 :                         return r;
    1676           0 :                 r = dns_packet_read_name(p, &rr->srv.name, true, NULL);
    1677           0 :                 break;
    1678             : 
    1679         152 :         case DNS_TYPE_PTR:
    1680             :         case DNS_TYPE_NS:
    1681             :         case DNS_TYPE_CNAME:
    1682             :         case DNS_TYPE_DNAME:
    1683         152 :                 r = dns_packet_read_name(p, &rr->ptr.name, true, NULL);
    1684         152 :                 break;
    1685             : 
    1686           0 :         case DNS_TYPE_HINFO:
    1687           0 :                 r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL);
    1688           0 :                 if (r < 0)
    1689           0 :                         return r;
    1690             : 
    1691           0 :                 r = dns_packet_read_string(p, &rr->hinfo.os, NULL);
    1692           0 :                 break;
    1693             : 
    1694          36 :         case DNS_TYPE_SPF: /* exactly the same as TXT */
    1695             :         case DNS_TYPE_TXT:
    1696          36 :                 if (rdlength <= 0) {
    1697           0 :                         r = dns_txt_item_new_empty(&rr->txt.items);
    1698           0 :                         if (r < 0)
    1699           0 :                                 return r;
    1700          36 :                 } else {
    1701          36 :                         DnsTxtItem *last = NULL;
    1702             : 
    1703          72 :                         while (p->rindex < offset + rdlength) {
    1704             :                                 DnsTxtItem *i;
    1705             :                                 const void *data;
    1706             :                                 size_t sz;
    1707             : 
    1708          36 :                                 r = dns_packet_read_raw_string(p, &data, &sz, NULL);
    1709          36 :                                 if (r < 0)
    1710           0 :                                         return r;
    1711             : 
    1712          36 :                                 i = malloc0(offsetof(DnsTxtItem, data) + sz + 1); /* extra NUL byte at the end */
    1713          36 :                                 if (!i)
    1714           0 :                                         return -ENOMEM;
    1715             : 
    1716          36 :                                 memcpy(i->data, data, sz);
    1717          36 :                                 i->length = sz;
    1718             : 
    1719          36 :                                 LIST_INSERT_AFTER(items, rr->txt.items, last, i);
    1720          36 :                                 last = i;
    1721             :                         }
    1722             :                 }
    1723             : 
    1724          36 :                 r = 0;
    1725          36 :                 break;
    1726             : 
    1727          56 :         case DNS_TYPE_A:
    1728          56 :                 r = dns_packet_read_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
    1729          56 :                 break;
    1730             : 
    1731          28 :         case DNS_TYPE_AAAA:
    1732          28 :                 r = dns_packet_read_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
    1733          28 :                 break;
    1734             : 
    1735          28 :         case DNS_TYPE_SOA:
    1736          28 :                 r = dns_packet_read_name(p, &rr->soa.mname, true, NULL);
    1737          28 :                 if (r < 0)
    1738           0 :                         return r;
    1739             : 
    1740          28 :                 r = dns_packet_read_name(p, &rr->soa.rname, true, NULL);
    1741          28 :                 if (r < 0)
    1742           0 :                         return r;
    1743             : 
    1744          28 :                 r = dns_packet_read_uint32(p, &rr->soa.serial, NULL);
    1745          28 :                 if (r < 0)
    1746           0 :                         return r;
    1747             : 
    1748          28 :                 r = dns_packet_read_uint32(p, &rr->soa.refresh, NULL);
    1749          28 :                 if (r < 0)
    1750           0 :                         return r;
    1751             : 
    1752          28 :                 r = dns_packet_read_uint32(p, &rr->soa.retry, NULL);
    1753          28 :                 if (r < 0)
    1754           0 :                         return r;
    1755             : 
    1756          28 :                 r = dns_packet_read_uint32(p, &rr->soa.expire, NULL);
    1757          28 :                 if (r < 0)
    1758           0 :                         return r;
    1759             : 
    1760          28 :                 r = dns_packet_read_uint32(p, &rr->soa.minimum, NULL);
    1761          28 :                 break;
    1762             : 
    1763          56 :         case DNS_TYPE_MX:
    1764          56 :                 r = dns_packet_read_uint16(p, &rr->mx.priority, NULL);
    1765          56 :                 if (r < 0)
    1766           0 :                         return r;
    1767             : 
    1768          56 :                 r = dns_packet_read_name(p, &rr->mx.exchange, true, NULL);
    1769          56 :                 break;
    1770             : 
    1771          12 :         case DNS_TYPE_LOC: {
    1772             :                 uint8_t t;
    1773             :                 size_t pos;
    1774             : 
    1775          12 :                 r = dns_packet_read_uint8(p, &t, &pos);
    1776          12 :                 if (r < 0)
    1777           0 :                         return r;
    1778             : 
    1779          12 :                 if (t == 0) {
    1780          12 :                         rr->loc.version = t;
    1781             : 
    1782          12 :                         r = dns_packet_read_uint8(p, &rr->loc.size, NULL);
    1783          12 :                         if (r < 0)
    1784           0 :                                 return r;
    1785             : 
    1786          12 :                         if (!loc_size_ok(rr->loc.size))
    1787           0 :                                 return -EBADMSG;
    1788             : 
    1789          12 :                         r = dns_packet_read_uint8(p, &rr->loc.horiz_pre, NULL);
    1790          12 :                         if (r < 0)
    1791           0 :                                 return r;
    1792             : 
    1793          12 :                         if (!loc_size_ok(rr->loc.horiz_pre))
    1794           0 :                                 return -EBADMSG;
    1795             : 
    1796          12 :                         r = dns_packet_read_uint8(p, &rr->loc.vert_pre, NULL);
    1797          12 :                         if (r < 0)
    1798           0 :                                 return r;
    1799             : 
    1800          12 :                         if (!loc_size_ok(rr->loc.vert_pre))
    1801           0 :                                 return -EBADMSG;
    1802             : 
    1803          12 :                         r = dns_packet_read_uint32(p, &rr->loc.latitude, NULL);
    1804          12 :                         if (r < 0)
    1805           0 :                                 return r;
    1806             : 
    1807          12 :                         r = dns_packet_read_uint32(p, &rr->loc.longitude, NULL);
    1808          12 :                         if (r < 0)
    1809           0 :                                 return r;
    1810             : 
    1811          12 :                         r = dns_packet_read_uint32(p, &rr->loc.altitude, NULL);
    1812          12 :                         if (r < 0)
    1813           0 :                                 return r;
    1814             : 
    1815          12 :                         break;
    1816             :                 } else {
    1817           0 :                         dns_packet_rewind(p, pos);
    1818           0 :                         rr->unparseable = true;
    1819           0 :                         goto unparseable;
    1820             :                 }
    1821             :         }
    1822             : 
    1823           0 :         case DNS_TYPE_DS:
    1824           0 :                 r = dns_packet_read_uint16(p, &rr->ds.key_tag, NULL);
    1825           0 :                 if (r < 0)
    1826           0 :                         return r;
    1827             : 
    1828           0 :                 r = dns_packet_read_uint8(p, &rr->ds.algorithm, NULL);
    1829           0 :                 if (r < 0)
    1830           0 :                         return r;
    1831             : 
    1832           0 :                 r = dns_packet_read_uint8(p, &rr->ds.digest_type, NULL);
    1833           0 :                 if (r < 0)
    1834           0 :                         return r;
    1835             : 
    1836           0 :                 if (rdlength < 4)
    1837           0 :                         return -EBADMSG;
    1838             : 
    1839           0 :                 r = dns_packet_read_memdup(p, rdlength - 4,
    1840           0 :                                            &rr->ds.digest, &rr->ds.digest_size,
    1841             :                                            NULL);
    1842           0 :                 if (r < 0)
    1843           0 :                         return r;
    1844             : 
    1845           0 :                 if (rr->ds.digest_size <= 0)
    1846             :                         /* the accepted size depends on the algorithm, but for now
    1847             :                            just ensure that the value is greater than zero */
    1848           0 :                         return -EBADMSG;
    1849             : 
    1850           0 :                 break;
    1851             : 
    1852          24 :         case DNS_TYPE_SSHFP:
    1853          24 :                 r = dns_packet_read_uint8(p, &rr->sshfp.algorithm, NULL);
    1854          24 :                 if (r < 0)
    1855           0 :                         return r;
    1856             : 
    1857          24 :                 r = dns_packet_read_uint8(p, &rr->sshfp.fptype, NULL);
    1858          24 :                 if (r < 0)
    1859           0 :                         return r;
    1860             : 
    1861          24 :                 if (rdlength < 2)
    1862           0 :                         return -EBADMSG;
    1863             : 
    1864          48 :                 r = dns_packet_read_memdup(p, rdlength - 2,
    1865          24 :                                            &rr->sshfp.fingerprint, &rr->sshfp.fingerprint_size,
    1866             :                                            NULL);
    1867             : 
    1868          24 :                 if (rr->sshfp.fingerprint_size <= 0)
    1869             :                         /* the accepted size depends on the algorithm, but for now
    1870             :                            just ensure that the value is greater than zero */
    1871           0 :                         return -EBADMSG;
    1872             : 
    1873          24 :                 break;
    1874             : 
    1875          32 :         case DNS_TYPE_DNSKEY:
    1876          32 :                 r = dns_packet_read_uint16(p, &rr->dnskey.flags, NULL);
    1877          32 :                 if (r < 0)
    1878           0 :                         return r;
    1879             : 
    1880          32 :                 r = dns_packet_read_uint8(p, &rr->dnskey.protocol, NULL);
    1881          32 :                 if (r < 0)
    1882           0 :                         return r;
    1883             : 
    1884          32 :                 r = dns_packet_read_uint8(p, &rr->dnskey.algorithm, NULL);
    1885          32 :                 if (r < 0)
    1886           0 :                         return r;
    1887             : 
    1888          32 :                 if (rdlength < 4)
    1889           0 :                         return -EBADMSG;
    1890             : 
    1891          64 :                 r = dns_packet_read_memdup(p, rdlength - 4,
    1892          32 :                                            &rr->dnskey.key, &rr->dnskey.key_size,
    1893             :                                            NULL);
    1894             : 
    1895          32 :                 if (rr->dnskey.key_size <= 0)
    1896             :                         /* the accepted size depends on the algorithm, but for now
    1897             :                            just ensure that the value is greater than zero */
    1898           0 :                         return -EBADMSG;
    1899             : 
    1900          32 :                 break;
    1901             : 
    1902           0 :         case DNS_TYPE_RRSIG:
    1903           0 :                 r = dns_packet_read_uint16(p, &rr->rrsig.type_covered, NULL);
    1904           0 :                 if (r < 0)
    1905           0 :                         return r;
    1906             : 
    1907           0 :                 r = dns_packet_read_uint8(p, &rr->rrsig.algorithm, NULL);
    1908           0 :                 if (r < 0)
    1909           0 :                         return r;
    1910             : 
    1911           0 :                 r = dns_packet_read_uint8(p, &rr->rrsig.labels, NULL);
    1912           0 :                 if (r < 0)
    1913           0 :                         return r;
    1914             : 
    1915           0 :                 r = dns_packet_read_uint32(p, &rr->rrsig.original_ttl, NULL);
    1916           0 :                 if (r < 0)
    1917           0 :                         return r;
    1918             : 
    1919           0 :                 r = dns_packet_read_uint32(p, &rr->rrsig.expiration, NULL);
    1920           0 :                 if (r < 0)
    1921           0 :                         return r;
    1922             : 
    1923           0 :                 r = dns_packet_read_uint32(p, &rr->rrsig.inception, NULL);
    1924           0 :                 if (r < 0)
    1925           0 :                         return r;
    1926             : 
    1927           0 :                 r = dns_packet_read_uint16(p, &rr->rrsig.key_tag, NULL);
    1928           0 :                 if (r < 0)
    1929           0 :                         return r;
    1930             : 
    1931           0 :                 r = dns_packet_read_name(p, &rr->rrsig.signer, false, NULL);
    1932           0 :                 if (r < 0)
    1933           0 :                         return r;
    1934             : 
    1935           0 :                 if (rdlength + offset < p->rindex)
    1936           0 :                         return -EBADMSG;
    1937             : 
    1938           0 :                 r = dns_packet_read_memdup(p, offset + rdlength - p->rindex,
    1939           0 :                                            &rr->rrsig.signature, &rr->rrsig.signature_size,
    1940             :                                            NULL);
    1941             : 
    1942           0 :                 if (rr->rrsig.signature_size <= 0)
    1943             :                         /* the accepted size depends on the algorithm, but for now
    1944             :                            just ensure that the value is greater than zero */
    1945           0 :                         return -EBADMSG;
    1946             : 
    1947           0 :                 break;
    1948             : 
    1949          24 :         case DNS_TYPE_NSEC: {
    1950             : 
    1951             :                 /*
    1952             :                  * RFC6762, section 18.14 explicitly states mDNS should use name compression.
    1953             :                  * This contradicts RFC3845, section 2.1.1
    1954             :                  */
    1955             : 
    1956          24 :                 bool allow_compressed = p->protocol == DNS_PROTOCOL_MDNS;
    1957             : 
    1958          24 :                 r = dns_packet_read_name(p, &rr->nsec.next_domain_name, allow_compressed, NULL);
    1959          24 :                 if (r < 0)
    1960           0 :                         return r;
    1961             : 
    1962          24 :                 r = dns_packet_read_type_windows(p, &rr->nsec.types, offset + rdlength - p->rindex, NULL);
    1963             : 
    1964             :                 /* We accept empty NSEC bitmaps. The bit indicating the presence of the NSEC record itself
    1965             :                  * is redundant and in e.g., RFC4956 this fact is used to define a use for NSEC records
    1966             :                  * without the NSEC bit set. */
    1967             : 
    1968          24 :                 break;
    1969             :         }
    1970           0 :         case DNS_TYPE_NSEC3: {
    1971             :                 uint8_t size;
    1972             : 
    1973           0 :                 r = dns_packet_read_uint8(p, &rr->nsec3.algorithm, NULL);
    1974           0 :                 if (r < 0)
    1975           0 :                         return r;
    1976             : 
    1977           0 :                 r = dns_packet_read_uint8(p, &rr->nsec3.flags, NULL);
    1978           0 :                 if (r < 0)
    1979           0 :                         return r;
    1980             : 
    1981           0 :                 r = dns_packet_read_uint16(p, &rr->nsec3.iterations, NULL);
    1982           0 :                 if (r < 0)
    1983           0 :                         return r;
    1984             : 
    1985             :                 /* this may be zero */
    1986           0 :                 r = dns_packet_read_uint8(p, &size, NULL);
    1987           0 :                 if (r < 0)
    1988           0 :                         return r;
    1989             : 
    1990           0 :                 r = dns_packet_read_memdup(p, size, &rr->nsec3.salt, &rr->nsec3.salt_size, NULL);
    1991           0 :                 if (r < 0)
    1992           0 :                         return r;
    1993             : 
    1994           0 :                 r = dns_packet_read_uint8(p, &size, NULL);
    1995           0 :                 if (r < 0)
    1996           0 :                         return r;
    1997             : 
    1998           0 :                 if (size <= 0)
    1999           0 :                         return -EBADMSG;
    2000             : 
    2001           0 :                 r = dns_packet_read_memdup(p, size,
    2002           0 :                                            &rr->nsec3.next_hashed_name, &rr->nsec3.next_hashed_name_size,
    2003             :                                            NULL);
    2004           0 :                 if (r < 0)
    2005           0 :                         return r;
    2006             : 
    2007           0 :                 r = dns_packet_read_type_windows(p, &rr->nsec3.types, offset + rdlength - p->rindex, NULL);
    2008             : 
    2009             :                 /* empty non-terminals can have NSEC3 records, so empty bitmaps are allowed */
    2010             : 
    2011           0 :                 break;
    2012             :         }
    2013             : 
    2014           4 :         case DNS_TYPE_TLSA:
    2015           4 :                 r = dns_packet_read_uint8(p, &rr->tlsa.cert_usage, NULL);
    2016           4 :                 if (r < 0)
    2017           0 :                         return r;
    2018             : 
    2019           4 :                 r = dns_packet_read_uint8(p, &rr->tlsa.selector, NULL);
    2020           4 :                 if (r < 0)
    2021           0 :                         return r;
    2022             : 
    2023           4 :                 r = dns_packet_read_uint8(p, &rr->tlsa.matching_type, NULL);
    2024           4 :                 if (r < 0)
    2025           0 :                         return r;
    2026             : 
    2027           4 :                 if (rdlength < 3)
    2028           0 :                         return -EBADMSG;
    2029             : 
    2030           8 :                 r = dns_packet_read_memdup(p, rdlength - 3,
    2031           4 :                                            &rr->tlsa.data, &rr->tlsa.data_size,
    2032             :                                            NULL);
    2033             : 
    2034           4 :                 if (rr->tlsa.data_size <= 0)
    2035             :                         /* the accepted size depends on the algorithm, but for now
    2036             :                            just ensure that the value is greater than zero */
    2037           0 :                         return -EBADMSG;
    2038             : 
    2039           4 :                 break;
    2040             : 
    2041          20 :         case DNS_TYPE_CAA:
    2042          20 :                 r = dns_packet_read_uint8(p, &rr->caa.flags, NULL);
    2043          20 :                 if (r < 0)
    2044           0 :                         return r;
    2045             : 
    2046          20 :                 r = dns_packet_read_string(p, &rr->caa.tag, NULL);
    2047          20 :                 if (r < 0)
    2048           0 :                         return r;
    2049             : 
    2050          20 :                 if (rdlength + offset < p->rindex)
    2051           0 :                         return -EBADMSG;
    2052             : 
    2053          60 :                 r = dns_packet_read_memdup(p,
    2054          20 :                                            rdlength + offset - p->rindex,
    2055          20 :                                            &rr->caa.value, &rr->caa.value_size, NULL);
    2056             : 
    2057          20 :                 break;
    2058             : 
    2059             :         case DNS_TYPE_OPT: /* we only care about the header of OPT for now. */
    2060             :         case DNS_TYPE_OPENPGPKEY:
    2061             :         default:
    2062           4 :         unparseable:
    2063           4 :                 r = dns_packet_read_memdup(p, rdlength, &rr->generic.data, &rr->generic.data_size, NULL);
    2064             : 
    2065           4 :                 break;
    2066             :         }
    2067         476 :         if (r < 0)
    2068           0 :                 return r;
    2069         476 :         if (p->rindex != offset + rdlength)
    2070           0 :                 return -EBADMSG;
    2071             : 
    2072         476 :         *ret = TAKE_PTR(rr);
    2073             : 
    2074         476 :         if (ret_cache_flush)
    2075           0 :                 *ret_cache_flush = cache_flush;
    2076         476 :         if (start)
    2077           0 :                 *start = rewinder.saved_rindex;
    2078         476 :         CANCEL_REWINDER(rewinder);
    2079             : 
    2080         476 :         return 0;
    2081             : }
    2082             : 
    2083           0 : static bool opt_is_good(DnsResourceRecord *rr, bool *rfc6975) {
    2084             :         const uint8_t* p;
    2085           0 :         bool found_dau_dhu_n3u = false;
    2086             :         size_t l;
    2087             : 
    2088             :         /* Checks whether the specified OPT RR is well-formed and whether it contains RFC6975 data (which is not OK in
    2089             :          * a reply). */
    2090             : 
    2091           0 :         assert(rr);
    2092           0 :         assert(rr->key->type == DNS_TYPE_OPT);
    2093             : 
    2094             :         /* Check that the version is 0 */
    2095           0 :         if (((rr->ttl >> 16) & UINT32_C(0xFF)) != 0) {
    2096           0 :                 *rfc6975 = false;
    2097           0 :                 return true; /* if it's not version 0, it's OK, but we will ignore the OPT field contents */
    2098             :         }
    2099             : 
    2100           0 :         p = rr->opt.data;
    2101           0 :         l = rr->opt.data_size;
    2102           0 :         while (l > 0) {
    2103             :                 uint16_t option_code, option_length;
    2104             : 
    2105             :                 /* At least four bytes for OPTION-CODE and OPTION-LENGTH are required */
    2106           0 :                 if (l < 4U)
    2107           0 :                         return false;
    2108             : 
    2109           0 :                 option_code = unaligned_read_be16(p);
    2110           0 :                 option_length = unaligned_read_be16(p + 2);
    2111             : 
    2112           0 :                 if (l < option_length + 4U)
    2113           0 :                         return false;
    2114             : 
    2115             :                 /* RFC 6975 DAU, DHU or N3U fields found. */
    2116           0 :                 if (IN_SET(option_code, 5, 6, 7))
    2117           0 :                         found_dau_dhu_n3u = true;
    2118             : 
    2119           0 :                 p += option_length + 4U;
    2120           0 :                 l -= option_length + 4U;
    2121             :         }
    2122             : 
    2123           0 :         *rfc6975 = found_dau_dhu_n3u;
    2124           0 :         return true;
    2125             : }
    2126             : 
    2127           0 : static int dns_packet_extract_question(DnsPacket *p, DnsQuestion **ret_question) {
    2128           0 :         _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
    2129             :         unsigned n, i;
    2130             :         int r;
    2131             : 
    2132           0 :         n = DNS_PACKET_QDCOUNT(p);
    2133           0 :         if (n > 0) {
    2134           0 :                 question = dns_question_new(n);
    2135           0 :                 if (!question)
    2136           0 :                         return -ENOMEM;
    2137             : 
    2138           0 :                 _cleanup_set_free_ Set *keys = NULL; /* references to keys are kept by Question */
    2139             : 
    2140           0 :                 keys = set_new(&dns_resource_key_hash_ops);
    2141           0 :                 if (!keys)
    2142           0 :                         return log_oom();
    2143             : 
    2144           0 :                 r = set_reserve(keys, n * 2); /* Higher multipliers give slightly higher efficiency through
    2145             :                                                * hash collisions, but the gains quickly drop of after 2. */
    2146           0 :                 if (r < 0)
    2147           0 :                         return r;
    2148             : 
    2149           0 :                 for (i = 0; i < n; i++) {
    2150           0 :                         _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
    2151             :                         bool cache_flush;
    2152             : 
    2153           0 :                         r = dns_packet_read_key(p, &key, &cache_flush, NULL);
    2154           0 :                         if (r < 0)
    2155           0 :                                 return r;
    2156             : 
    2157           0 :                         if (cache_flush)
    2158           0 :                                 return -EBADMSG;
    2159             : 
    2160           0 :                         if (!dns_type_is_valid_query(key->type))
    2161           0 :                                 return -EBADMSG;
    2162             : 
    2163           0 :                         r = set_put(keys, key);
    2164           0 :                         if (r < 0)
    2165           0 :                                 return r;
    2166           0 :                         if (r == 0)
    2167             :                                 /* Already in the Question, let's skip */
    2168           0 :                                 continue;
    2169             : 
    2170           0 :                         r = dns_question_add_raw(question, key);
    2171           0 :                         if (r < 0)
    2172           0 :                                 return r;
    2173             :                 }
    2174             :         }
    2175             : 
    2176           0 :         *ret_question = TAKE_PTR(question);
    2177             : 
    2178           0 :         return 0;
    2179             : }
    2180             : 
    2181           0 : static int dns_packet_extract_answer(DnsPacket *p, DnsAnswer **ret_answer) {
    2182           0 :         _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
    2183             :         unsigned n, i;
    2184           0 :         _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *previous = NULL;
    2185           0 :         bool bad_opt = false;
    2186             :         int r;
    2187             : 
    2188           0 :         n = DNS_PACKET_RRCOUNT(p);
    2189           0 :         if (n == 0)
    2190           0 :                 return 0;
    2191             : 
    2192           0 :         answer = dns_answer_new(n);
    2193           0 :         if (!answer)
    2194           0 :                 return -ENOMEM;
    2195             : 
    2196           0 :         for (i = 0; i < n; i++) {
    2197           0 :                 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
    2198           0 :                 bool cache_flush = false;
    2199             : 
    2200           0 :                 r = dns_packet_read_rr(p, &rr, &cache_flush, NULL);
    2201           0 :                 if (r < 0)
    2202           0 :                         return r;
    2203             : 
    2204             :                 /* Try to reduce memory usage a bit */
    2205           0 :                 if (previous)
    2206           0 :                         dns_resource_key_reduce(&rr->key, &previous->key);
    2207             : 
    2208           0 :                 if (rr->key->type == DNS_TYPE_OPT) {
    2209             :                         bool has_rfc6975;
    2210             : 
    2211           0 :                         if (p->opt || bad_opt) {
    2212             :                                 /* Multiple OPT RRs? if so, let's ignore all, because there's
    2213             :                                  * something wrong with the server, and if one is valid we wouldn't
    2214             :                                  * know which one. */
    2215           0 :                                 log_debug("Multiple OPT RRs detected, ignoring all.");
    2216           0 :                                 bad_opt = true;
    2217           0 :                                 continue;
    2218             :                         }
    2219             : 
    2220           0 :                         if (!dns_name_is_root(dns_resource_key_name(rr->key))) {
    2221             :                                 /* If the OPT RR is not owned by the root domain, then it is bad,
    2222             :                                  * let's ignore it. */
    2223           0 :                                 log_debug("OPT RR is not owned by root domain, ignoring.");
    2224           0 :                                 bad_opt = true;
    2225           0 :                                 continue;
    2226             :                         }
    2227             : 
    2228           0 :                         if (i < DNS_PACKET_ANCOUNT(p) + DNS_PACKET_NSCOUNT(p)) {
    2229             :                                 /* OPT RR is in the wrong section? Some Belkin routers do this. This
    2230             :                                  * is a hint the EDNS implementation is borked, like the Belkin one
    2231             :                                  * is, hence ignore it. */
    2232           0 :                                 log_debug("OPT RR in wrong section, ignoring.");
    2233           0 :                                 bad_opt = true;
    2234           0 :                                 continue;
    2235             :                         }
    2236             : 
    2237           0 :                         if (!opt_is_good(rr, &has_rfc6975)) {
    2238           0 :                                 log_debug("Malformed OPT RR, ignoring.");
    2239           0 :                                 bad_opt = true;
    2240           0 :                                 continue;
    2241             :                         }
    2242             : 
    2243           0 :                         if (DNS_PACKET_QR(p)) {
    2244             :                                 /* Additional checks for responses */
    2245             : 
    2246           0 :                                 if (!DNS_RESOURCE_RECORD_OPT_VERSION_SUPPORTED(rr)) {
    2247             :                                         /* If this is a reply and we don't know the EDNS version
    2248             :                                          * then something is weird... */
    2249           0 :                                         log_debug("EDNS version newer that our request, bad server.");
    2250           0 :                                         return -EBADMSG;
    2251             :                                 }
    2252             : 
    2253           0 :                                 if (has_rfc6975) {
    2254             :                                         /* If the OPT RR contains RFC6975 algorithm data, then this
    2255             :                                          * is indication that the server just copied the OPT it got
    2256             :                                          * from us (which contained that data) back into the reply.
    2257             :                                          * If so, then it doesn't properly support EDNS, as RFC6975
    2258             :                                          * makes it very clear that the algorithm data should only
    2259             :                                          * be contained in questions, never in replies. Crappy
    2260             :                                          * Belkin routers copy the OPT data for example, hence let's
    2261             :                                          * detect this so that we downgrade early. */
    2262           0 :                                         log_debug("OPT RR contains RFC6975 data, ignoring.");
    2263           0 :                                         bad_opt = true;
    2264           0 :                                         continue;
    2265             :                                 }
    2266             :                         }
    2267             : 
    2268           0 :                         p->opt = dns_resource_record_ref(rr);
    2269             :                 } else {
    2270             :                         /* According to RFC 4795, section 2.9. only the RRs from the Answer section
    2271             :                          * shall be cached. Hence mark only those RRs as cacheable by default, but
    2272             :                          * not the ones from the Additional or Authority sections. */
    2273           0 :                         DnsAnswerFlags flags =
    2274           0 :                                 (i < DNS_PACKET_ANCOUNT(p) ? DNS_ANSWER_CACHEABLE : 0) |
    2275           0 :                                 (p->protocol == DNS_PROTOCOL_MDNS && !cache_flush ? DNS_ANSWER_SHARED_OWNER : 0);
    2276             : 
    2277           0 :                         r = dns_answer_add(answer, rr, p->ifindex, flags);
    2278           0 :                         if (r < 0)
    2279           0 :                                 return r;
    2280             :                 }
    2281             : 
    2282             :                 /* Remember this RR, so that we potentically can merge it's ->key object with the
    2283             :                  * next RR. Note that we only do this if we actually decided to keep the RR around.
    2284             :                  */
    2285           0 :                 dns_resource_record_unref(previous);
    2286           0 :                 previous = dns_resource_record_ref(rr);
    2287             :         }
    2288             : 
    2289           0 :         if (bad_opt)
    2290           0 :                 p->opt = dns_resource_record_unref(p->opt);
    2291             : 
    2292           0 :         *ret_answer = TAKE_PTR(answer);
    2293             : 
    2294           0 :         return 0;
    2295             : }
    2296             : 
    2297           0 : int dns_packet_extract(DnsPacket *p) {
    2298           0 :         _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
    2299           0 :         _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
    2300           0 :         _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder = {};
    2301             :         int r;
    2302             : 
    2303           0 :         if (p->extracted)
    2304           0 :                 return 0;
    2305             : 
    2306           0 :         INIT_REWINDER(rewinder, p);
    2307           0 :         dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
    2308             : 
    2309           0 :         r = dns_packet_extract_question(p, &question);
    2310           0 :         if (r < 0)
    2311           0 :                 return r;
    2312             : 
    2313           0 :         r = dns_packet_extract_answer(p, &answer);
    2314           0 :         if (r < 0)
    2315           0 :                 return r;
    2316             : 
    2317           0 :         p->question = TAKE_PTR(question);
    2318           0 :         p->answer = TAKE_PTR(answer);
    2319             : 
    2320           0 :         p->extracted = true;
    2321             : 
    2322             :         /* no CANCEL, always rewind */
    2323           0 :         return 0;
    2324             : }
    2325             : 
    2326           0 : int dns_packet_is_reply_for(DnsPacket *p, const DnsResourceKey *key) {
    2327             :         int r;
    2328             : 
    2329           0 :         assert(p);
    2330           0 :         assert(key);
    2331             : 
    2332             :         /* Checks if the specified packet is a reply for the specified
    2333             :          * key and the specified key is the only one in the question
    2334             :          * section. */
    2335             : 
    2336           0 :         if (DNS_PACKET_QR(p) != 1)
    2337           0 :                 return 0;
    2338             : 
    2339             :         /* Let's unpack the packet, if that hasn't happened yet. */
    2340           0 :         r = dns_packet_extract(p);
    2341           0 :         if (r < 0)
    2342           0 :                 return r;
    2343             : 
    2344           0 :         if (!p->question)
    2345           0 :                 return 0;
    2346             : 
    2347           0 :         if (p->question->n_keys != 1)
    2348           0 :                 return 0;
    2349             : 
    2350           0 :         return dns_resource_key_equal(p->question->keys[0], key);
    2351             : }
    2352             : 
    2353           0 : static void dns_packet_hash_func(const DnsPacket *s, struct siphash *state) {
    2354           0 :         assert(s);
    2355             : 
    2356           0 :         siphash24_compress(&s->size, sizeof(s->size), state);
    2357           0 :         siphash24_compress(DNS_PACKET_DATA((DnsPacket*) s), s->size, state);
    2358           0 : }
    2359             : 
    2360           0 : static int dns_packet_compare_func(const DnsPacket *x, const DnsPacket *y) {
    2361             :         int r;
    2362             : 
    2363           0 :         r = CMP(x->size, y->size);
    2364           0 :         if (r != 0)
    2365           0 :                 return r;
    2366             : 
    2367           0 :         return memcmp(DNS_PACKET_DATA((DnsPacket*) x), DNS_PACKET_DATA((DnsPacket*) y), x->size);
    2368             : }
    2369             : 
    2370             : DEFINE_HASH_OPS(dns_packet_hash_ops, DnsPacket, dns_packet_hash_func, dns_packet_compare_func);
    2371             : 
    2372             : static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
    2373             :         [DNS_RCODE_SUCCESS] = "SUCCESS",
    2374             :         [DNS_RCODE_FORMERR] = "FORMERR",
    2375             :         [DNS_RCODE_SERVFAIL] = "SERVFAIL",
    2376             :         [DNS_RCODE_NXDOMAIN] = "NXDOMAIN",
    2377             :         [DNS_RCODE_NOTIMP] = "NOTIMP",
    2378             :         [DNS_RCODE_REFUSED] = "REFUSED",
    2379             :         [DNS_RCODE_YXDOMAIN] = "YXDOMAIN",
    2380             :         [DNS_RCODE_YXRRSET] = "YRRSET",
    2381             :         [DNS_RCODE_NXRRSET] = "NXRRSET",
    2382             :         [DNS_RCODE_NOTAUTH] = "NOTAUTH",
    2383             :         [DNS_RCODE_NOTZONE] = "NOTZONE",
    2384             :         [DNS_RCODE_BADVERS] = "BADVERS",
    2385             :         [DNS_RCODE_BADKEY] = "BADKEY",
    2386             :         [DNS_RCODE_BADTIME] = "BADTIME",
    2387             :         [DNS_RCODE_BADMODE] = "BADMODE",
    2388             :         [DNS_RCODE_BADNAME] = "BADNAME",
    2389             :         [DNS_RCODE_BADALG] = "BADALG",
    2390             :         [DNS_RCODE_BADTRUNC] = "BADTRUNC",
    2391             :         [DNS_RCODE_BADCOOKIE] = "BADCOOKIE",
    2392             : };
    2393        8194 : DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int);
    2394             : 
    2395             : static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = {
    2396             :         [DNS_PROTOCOL_DNS] = "dns",
    2397             :         [DNS_PROTOCOL_MDNS] = "mdns",
    2398             :         [DNS_PROTOCOL_LLMNR] = "llmnr",
    2399             : };
    2400          10 : DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);

Generated by: LCOV version 1.14