LCOV - code coverage report
Current view: top level - resolve - resolved-dns-rr.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 599 1099 54.5 %
Date: 2019-08-23 13:36:53 Functions: 27 49 55.1 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 279 791 35.3 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <math.h>
       4                 :            : 
       5                 :            : #include "alloc-util.h"
       6                 :            : #include "dns-domain.h"
       7                 :            : #include "dns-type.h"
       8                 :            : #include "escape.h"
       9                 :            : #include "hexdecoct.h"
      10                 :            : #include "memory-util.h"
      11                 :            : #include "resolved-dns-dnssec.h"
      12                 :            : #include "resolved-dns-packet.h"
      13                 :            : #include "resolved-dns-rr.h"
      14                 :            : #include "string-table.h"
      15                 :            : #include "string-util.h"
      16                 :            : #include "strv.h"
      17                 :            : #include "terminal-util.h"
      18                 :            : 
      19                 :         72 : DnsResourceKey* dns_resource_key_new(uint16_t class, uint16_t type, const char *name) {
      20                 :            :         DnsResourceKey *k;
      21                 :            :         size_t l;
      22                 :            : 
      23         [ -  + ]:         72 :         assert(name);
      24                 :            : 
      25                 :         72 :         l = strlen(name);
      26                 :         72 :         k = malloc0(sizeof(DnsResourceKey) + l + 1);
      27         [ -  + ]:         72 :         if (!k)
      28                 :          0 :                 return NULL;
      29                 :            : 
      30                 :         72 :         k->n_ref = 1;
      31                 :         72 :         k->class = class;
      32                 :         72 :         k->type = type;
      33                 :            : 
      34                 :         72 :         strcpy((char*) k + sizeof(DnsResourceKey), name);
      35                 :            : 
      36                 :         72 :         return k;
      37                 :            : }
      38                 :            : 
      39                 :          0 : DnsResourceKey* dns_resource_key_new_redirect(const DnsResourceKey *key, const DnsResourceRecord *cname) {
      40                 :            :         int r;
      41                 :            : 
      42         [ #  # ]:          0 :         assert(key);
      43         [ #  # ]:          0 :         assert(cname);
      44                 :            : 
      45   [ #  #  #  # ]:          0 :         assert(IN_SET(cname->key->type, DNS_TYPE_CNAME, DNS_TYPE_DNAME));
      46                 :            : 
      47         [ #  # ]:          0 :         if (cname->key->type == DNS_TYPE_CNAME)
      48                 :          0 :                 return dns_resource_key_new(key->class, key->type, cname->cname.name);
      49                 :            :         else {
      50                 :            :                 DnsResourceKey *k;
      51                 :          0 :                 char *destination = NULL;
      52                 :            : 
      53                 :          0 :                 r = dns_name_change_suffix(dns_resource_key_name(key), dns_resource_key_name(cname->key), cname->dname.name, &destination);
      54         [ #  # ]:          0 :                 if (r < 0)
      55                 :          0 :                         return NULL;
      56         [ #  # ]:          0 :                 if (r == 0)
      57                 :          0 :                         return dns_resource_key_ref((DnsResourceKey*) key);
      58                 :            : 
      59                 :          0 :                 k = dns_resource_key_new_consume(key->class, key->type, destination);
      60         [ #  # ]:          0 :                 if (!k)
      61                 :          0 :                         return mfree(destination);
      62                 :            : 
      63                 :          0 :                 return k;
      64                 :            :         }
      65                 :            : }
      66                 :            : 
      67                 :          0 : int dns_resource_key_new_append_suffix(DnsResourceKey **ret, DnsResourceKey *key, char *name) {
      68                 :            :         DnsResourceKey *new_key;
      69                 :            :         char *joined;
      70                 :            :         int r;
      71                 :            : 
      72         [ #  # ]:          0 :         assert(ret);
      73         [ #  # ]:          0 :         assert(key);
      74         [ #  # ]:          0 :         assert(name);
      75                 :            : 
      76         [ #  # ]:          0 :         if (dns_name_is_root(name)) {
      77                 :          0 :                 *ret = dns_resource_key_ref(key);
      78                 :          0 :                 return 0;
      79                 :            :         }
      80                 :            : 
      81                 :          0 :         r = dns_name_concat(dns_resource_key_name(key), name, 0, &joined);
      82         [ #  # ]:          0 :         if (r < 0)
      83                 :          0 :                 return r;
      84                 :            : 
      85                 :          0 :         new_key = dns_resource_key_new_consume(key->class, key->type, joined);
      86         [ #  # ]:          0 :         if (!new_key) {
      87                 :          0 :                 free(joined);
      88                 :          0 :                 return -ENOMEM;
      89                 :            :         }
      90                 :            : 
      91                 :          0 :         *ret = new_key;
      92                 :          0 :         return 0;
      93                 :            : }
      94                 :            : 
      95                 :       1904 : DnsResourceKey* dns_resource_key_new_consume(uint16_t class, uint16_t type, char *name) {
      96                 :            :         DnsResourceKey *k;
      97                 :            : 
      98         [ -  + ]:       1904 :         assert(name);
      99                 :            : 
     100                 :       1904 :         k = new0(DnsResourceKey, 1);
     101         [ -  + ]:       1904 :         if (!k)
     102                 :          0 :                 return NULL;
     103                 :            : 
     104                 :       1904 :         k->n_ref = 1;
     105                 :       1904 :         k->class = class;
     106                 :       1904 :         k->type = type;
     107                 :       1904 :         k->_name = name;
     108                 :            : 
     109                 :       1904 :         return k;
     110                 :            : }
     111                 :            : 
     112                 :       3880 : DnsResourceKey* dns_resource_key_ref(DnsResourceKey *k) {
     113                 :            : 
     114         [ -  + ]:       3880 :         if (!k)
     115                 :          0 :                 return NULL;
     116                 :            : 
     117                 :            :         /* Static/const keys created with DNS_RESOURCE_KEY_CONST will
     118                 :            :          * set this to -1, they should not be reffed/unreffed */
     119         [ -  + ]:       3880 :         assert(k->n_ref != (unsigned) -1);
     120                 :            : 
     121         [ -  + ]:       3880 :         assert(k->n_ref > 0);
     122                 :       3880 :         k->n_ref++;
     123                 :            : 
     124                 :       3880 :         return k;
     125                 :            : }
     126                 :            : 
     127                 :       5856 : DnsResourceKey* dns_resource_key_unref(DnsResourceKey *k) {
     128         [ -  + ]:       5856 :         if (!k)
     129                 :          0 :                 return NULL;
     130                 :            : 
     131         [ -  + ]:       5856 :         assert(k->n_ref != (unsigned) -1);
     132         [ -  + ]:       5856 :         assert(k->n_ref > 0);
     133                 :            : 
     134         [ +  + ]:       5856 :         if (k->n_ref == 1) {
     135                 :       1976 :                 free(k->_name);
     136                 :       1976 :                 free(k);
     137                 :            :         } else
     138                 :       3880 :                 k->n_ref--;
     139                 :            : 
     140                 :       5856 :         return NULL;
     141                 :            : }
     142                 :            : 
     143                 :       5888 : const char* dns_resource_key_name(const DnsResourceKey *key) {
     144                 :            :         const char *name;
     145                 :            : 
     146         [ -  + ]:       5888 :         if (!key)
     147                 :          0 :                 return NULL;
     148                 :            : 
     149         [ +  + ]:       5888 :         if (key->_name)
     150                 :       5712 :                 name = key->_name;
     151                 :            :         else
     152                 :        176 :                 name = (char*) key + sizeof(DnsResourceKey);
     153                 :            : 
     154         [ +  + ]:       5888 :         if (dns_name_is_root(name))
     155                 :        816 :                 return ".";
     156                 :            :         else
     157                 :       5072 :                 return name;
     158                 :            : }
     159                 :            : 
     160                 :          0 : bool dns_resource_key_is_address(const DnsResourceKey *key) {
     161         [ #  # ]:          0 :         assert(key);
     162                 :            : 
     163                 :            :         /* Check if this is an A or AAAA resource key */
     164                 :            : 
     165   [ #  #  #  #  :          0 :         return key->class == DNS_CLASS_IN && IN_SET(key->type, DNS_TYPE_A, DNS_TYPE_AAAA);
                   #  # ]
     166                 :            : }
     167                 :            : 
     168                 :          0 : bool dns_resource_key_is_dnssd_ptr(const DnsResourceKey *key) {
     169         [ #  # ]:          0 :         assert(key);
     170                 :            : 
     171                 :            :         /* Check if this is a PTR resource key used in
     172                 :            :            Service Instance Enumeration as described in RFC6763 p4.1. */
     173                 :            : 
     174         [ #  # ]:          0 :         if (key->type != DNS_TYPE_PTR)
     175                 :          0 :                 return false;
     176                 :            : 
     177   [ #  #  #  # ]:          0 :         return dns_name_endswith(dns_resource_key_name(key), "_tcp.local") ||
     178                 :          0 :                 dns_name_endswith(dns_resource_key_name(key), "_udp.local");
     179                 :            : }
     180                 :            : 
     181                 :       1920 : int dns_resource_key_equal(const DnsResourceKey *a, const DnsResourceKey *b) {
     182                 :            :         int r;
     183                 :            : 
     184         [ +  - ]:       1920 :         if (a == b)
     185                 :       1920 :                 return 1;
     186                 :            : 
     187                 :          0 :         r = dns_name_equal(dns_resource_key_name(a), dns_resource_key_name(b));
     188         [ #  # ]:          0 :         if (r <= 0)
     189                 :          0 :                 return r;
     190                 :            : 
     191         [ #  # ]:          0 :         if (a->class != b->class)
     192                 :          0 :                 return 0;
     193                 :            : 
     194         [ #  # ]:          0 :         if (a->type != b->type)
     195                 :          0 :                 return 0;
     196                 :            : 
     197                 :          0 :         return 1;
     198                 :            : }
     199                 :            : 
     200                 :          0 : int dns_resource_key_match_rr(const DnsResourceKey *key, DnsResourceRecord *rr, const char *search_domain) {
     201                 :            :         int r;
     202                 :            : 
     203         [ #  # ]:          0 :         assert(key);
     204         [ #  # ]:          0 :         assert(rr);
     205                 :            : 
     206         [ #  # ]:          0 :         if (key == rr->key)
     207                 :          0 :                 return 1;
     208                 :            : 
     209                 :            :         /* Checks if an rr matches the specified key. If a search
     210                 :            :          * domain is specified, it will also be checked if the key
     211                 :            :          * with the search domain suffixed might match the RR. */
     212                 :            : 
     213   [ #  #  #  # ]:          0 :         if (rr->key->class != key->class && key->class != DNS_CLASS_ANY)
     214                 :          0 :                 return 0;
     215                 :            : 
     216   [ #  #  #  # ]:          0 :         if (rr->key->type != key->type && key->type != DNS_TYPE_ANY)
     217                 :          0 :                 return 0;
     218                 :            : 
     219                 :          0 :         r = dns_name_equal(dns_resource_key_name(rr->key), dns_resource_key_name(key));
     220         [ #  # ]:          0 :         if (r != 0)
     221                 :          0 :                 return r;
     222                 :            : 
     223         [ #  # ]:          0 :         if (search_domain) {
     224                 :          0 :                 _cleanup_free_ char *joined = NULL;
     225                 :            : 
     226                 :          0 :                 r = dns_name_concat(dns_resource_key_name(key), search_domain, 0, &joined);
     227         [ #  # ]:          0 :                 if (r < 0)
     228                 :          0 :                         return r;
     229                 :            : 
     230                 :          0 :                 return dns_name_equal(dns_resource_key_name(rr->key), joined);
     231                 :            :         }
     232                 :            : 
     233                 :          0 :         return 0;
     234                 :            : }
     235                 :            : 
     236                 :          0 : int dns_resource_key_match_cname_or_dname(const DnsResourceKey *key, const DnsResourceKey *cname, const char *search_domain) {
     237                 :            :         int r;
     238                 :            : 
     239         [ #  # ]:          0 :         assert(key);
     240         [ #  # ]:          0 :         assert(cname);
     241                 :            : 
     242   [ #  #  #  # ]:          0 :         if (cname->class != key->class && key->class != DNS_CLASS_ANY)
     243                 :          0 :                 return 0;
     244                 :            : 
     245         [ #  # ]:          0 :         if (cname->type == DNS_TYPE_CNAME)
     246                 :          0 :                 r = dns_name_equal(dns_resource_key_name(key), dns_resource_key_name(cname));
     247         [ #  # ]:          0 :         else if (cname->type == DNS_TYPE_DNAME)
     248                 :          0 :                 r = dns_name_endswith(dns_resource_key_name(key), dns_resource_key_name(cname));
     249                 :            :         else
     250                 :          0 :                 return 0;
     251                 :            : 
     252         [ #  # ]:          0 :         if (r != 0)
     253                 :          0 :                 return r;
     254                 :            : 
     255         [ #  # ]:          0 :         if (search_domain) {
     256         [ #  # ]:          0 :                 _cleanup_free_ char *joined = NULL;
     257                 :            : 
     258                 :          0 :                 r = dns_name_concat(dns_resource_key_name(key), search_domain, 0, &joined);
     259         [ #  # ]:          0 :                 if (r < 0)
     260                 :          0 :                         return r;
     261                 :            : 
     262         [ #  # ]:          0 :                 if (cname->type == DNS_TYPE_CNAME)
     263                 :          0 :                         return dns_name_equal(joined, dns_resource_key_name(cname));
     264         [ #  # ]:          0 :                 else if (cname->type == DNS_TYPE_DNAME)
     265                 :          0 :                         return dns_name_endswith(joined, dns_resource_key_name(cname));
     266                 :            :         }
     267                 :            : 
     268                 :          0 :         return 0;
     269                 :            : }
     270                 :            : 
     271                 :          0 : int dns_resource_key_match_soa(const DnsResourceKey *key, const DnsResourceKey *soa) {
     272         [ #  # ]:          0 :         assert(soa);
     273         [ #  # ]:          0 :         assert(key);
     274                 :            : 
     275                 :            :         /* Checks whether 'soa' is a SOA record for the specified key. */
     276                 :            : 
     277         [ #  # ]:          0 :         if (soa->class != key->class)
     278                 :          0 :                 return 0;
     279                 :            : 
     280         [ #  # ]:          0 :         if (soa->type != DNS_TYPE_SOA)
     281                 :          0 :                 return 0;
     282                 :            : 
     283                 :          0 :         return dns_name_endswith(dns_resource_key_name(key), dns_resource_key_name(soa));
     284                 :            : }
     285                 :            : 
     286                 :       1904 : static void dns_resource_key_hash_func(const DnsResourceKey *k, struct siphash *state) {
     287         [ -  + ]:       1904 :         assert(k);
     288                 :            : 
     289                 :       1904 :         dns_name_hash_func(dns_resource_key_name(k), state);
     290                 :       1904 :         siphash24_compress(&k->class, sizeof(k->class), state);
     291                 :       1904 :         siphash24_compress(&k->type, sizeof(k->type), state);
     292                 :       1904 : }
     293                 :            : 
     294                 :          0 : static int dns_resource_key_compare_func(const DnsResourceKey *x, const DnsResourceKey *y) {
     295                 :            :         int ret;
     296                 :            : 
     297                 :          0 :         ret = dns_name_compare_func(dns_resource_key_name(x), dns_resource_key_name(y));
     298         [ #  # ]:          0 :         if (ret != 0)
     299                 :          0 :                 return ret;
     300                 :            : 
     301         [ #  # ]:          0 :         ret = CMP(x->type, y->type);
     302         [ #  # ]:          0 :         if (ret != 0)
     303                 :          0 :                 return ret;
     304                 :            : 
     305         [ #  # ]:          0 :         ret = CMP(x->class, y->class);
     306         [ #  # ]:          0 :         if (ret != 0)
     307                 :          0 :                 return ret;
     308                 :            : 
     309                 :          0 :         return 0;
     310                 :            : }
     311                 :            : 
     312                 :            : DEFINE_HASH_OPS(dns_resource_key_hash_ops, DnsResourceKey, dns_resource_key_hash_func, dns_resource_key_compare_func);
     313                 :            : 
     314                 :       2928 : char* dns_resource_key_to_string(const DnsResourceKey *key, char *buf, size_t buf_size) {
     315                 :            :         const char *c, *t;
     316                 :       2928 :         char *ans = buf;
     317                 :            : 
     318                 :            :         /* If we cannot convert the CLASS/TYPE into a known string,
     319                 :            :            use the format recommended by RFC 3597, Section 5. */
     320                 :            : 
     321                 :       2928 :         c = dns_class_to_string(key->class);
     322                 :       2928 :         t = dns_type_to_string(key->type);
     323                 :            : 
     324   [ -  +  +  -  :       2928 :         snprintf(buf, buf_size, "%s %s%s%.0u %s%s%.0u",
             -  +  +  - ]
     325                 :            :                  dns_resource_key_name(key),
     326                 :          0 :                  strempty(c), c ? "" : "CLASS", c ? 0 : key->class,
     327                 :          0 :                  strempty(t), t ? "" : "TYPE", t ? 0 : key->type);
     328                 :            : 
     329                 :       2928 :         return ans;
     330                 :            : }
     331                 :            : 
     332                 :          0 : bool dns_resource_key_reduce(DnsResourceKey **a, DnsResourceKey **b) {
     333         [ #  # ]:          0 :         assert(a);
     334         [ #  # ]:          0 :         assert(b);
     335                 :            : 
     336                 :            :         /* Try to replace one RR key by another if they are identical, thus saving a bit of memory. Note that we do
     337                 :            :          * this only for RR keys, not for RRs themselves, as they carry a lot of additional metadata (where they come
     338                 :            :          * from, validity data, and suchlike), and cannot be replaced so easily by other RRs that have the same
     339                 :            :          * superficial data. */
     340                 :            : 
     341         [ #  # ]:          0 :         if (!*a)
     342                 :          0 :                 return false;
     343         [ #  # ]:          0 :         if (!*b)
     344                 :          0 :                 return false;
     345                 :            : 
     346                 :            :         /* We refuse merging const keys */
     347         [ #  # ]:          0 :         if ((*a)->n_ref == (unsigned) -1)
     348                 :          0 :                 return false;
     349         [ #  # ]:          0 :         if ((*b)->n_ref == (unsigned) -1)
     350                 :          0 :                 return false;
     351                 :            : 
     352                 :            :         /* Already the same? */
     353         [ #  # ]:          0 :         if (*a == *b)
     354                 :          0 :                 return true;
     355                 :            : 
     356                 :            :         /* Are they really identical? */
     357         [ #  # ]:          0 :         if (dns_resource_key_equal(*a, *b) <= 0)
     358                 :          0 :                 return false;
     359                 :            : 
     360                 :            :         /* Keep the one which already has more references. */
     361         [ #  # ]:          0 :         if ((*a)->n_ref > (*b)->n_ref) {
     362                 :          0 :                 dns_resource_key_unref(*b);
     363                 :          0 :                 *b = dns_resource_key_ref(*a);
     364                 :            :         } else {
     365                 :          0 :                 dns_resource_key_unref(*a);
     366                 :          0 :                 *a = dns_resource_key_ref(*b);
     367                 :            :         }
     368                 :            : 
     369                 :          0 :         return true;
     370                 :            : }
     371                 :            : 
     372                 :       3880 : DnsResourceRecord* dns_resource_record_new(DnsResourceKey *key) {
     373                 :            :         DnsResourceRecord *rr;
     374                 :            : 
     375                 :       3880 :         rr = new0(DnsResourceRecord, 1);
     376         [ -  + ]:       3880 :         if (!rr)
     377                 :          0 :                 return NULL;
     378                 :            : 
     379                 :       3880 :         rr->n_ref = 1;
     380                 :       3880 :         rr->key = dns_resource_key_ref(key);
     381                 :       3880 :         rr->expiry = USEC_INFINITY;
     382                 :       3880 :         rr->n_skip_labels_signer = rr->n_skip_labels_source = (unsigned) -1;
     383                 :            : 
     384                 :       3880 :         return rr;
     385                 :            : }
     386                 :            : 
     387                 :         72 : DnsResourceRecord* dns_resource_record_new_full(uint16_t class, uint16_t type, const char *name) {
     388                 :         72 :         _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
     389                 :            : 
     390                 :         72 :         key = dns_resource_key_new(class, type, name);
     391         [ -  + ]:         72 :         if (!key)
     392                 :          0 :                 return NULL;
     393                 :            : 
     394                 :         72 :         return dns_resource_record_new(key);
     395                 :            : }
     396                 :            : 
     397                 :       3880 : static DnsResourceRecord* dns_resource_record_free(DnsResourceRecord *rr) {
     398         [ -  + ]:       3880 :         assert(rr);
     399                 :            : 
     400         [ +  - ]:       3880 :         if (rr->key) {
     401   [ -  +  -  +  :       3880 :                 switch(rr->key->type) {
          +  +  +  +  +  
          +  +  +  +  +  
                   +  + ]
     402                 :            : 
     403                 :          0 :                 case DNS_TYPE_SRV:
     404                 :          0 :                         free(rr->srv.name);
     405                 :          0 :                         break;
     406                 :            : 
     407                 :       1216 :                 case DNS_TYPE_PTR:
     408                 :            :                 case DNS_TYPE_NS:
     409                 :            :                 case DNS_TYPE_CNAME:
     410                 :            :                 case DNS_TYPE_DNAME:
     411                 :       1216 :                         free(rr->ptr.name);
     412                 :       1216 :                         break;
     413                 :            : 
     414                 :          0 :                 case DNS_TYPE_HINFO:
     415                 :          0 :                         free(rr->hinfo.cpu);
     416                 :          0 :                         free(rr->hinfo.os);
     417                 :          0 :                         break;
     418                 :            : 
     419                 :        288 :                 case DNS_TYPE_TXT:
     420                 :            :                 case DNS_TYPE_SPF:
     421                 :        288 :                         dns_txt_item_free_all(rr->txt.items);
     422                 :        288 :                         break;
     423                 :            : 
     424                 :        224 :                 case DNS_TYPE_SOA:
     425                 :        224 :                         free(rr->soa.mname);
     426                 :        224 :                         free(rr->soa.rname);
     427                 :        224 :                         break;
     428                 :            : 
     429                 :        456 :                 case DNS_TYPE_MX:
     430                 :        456 :                         free(rr->mx.exchange);
     431                 :        456 :                         break;
     432                 :            : 
     433                 :         16 :                 case DNS_TYPE_DS:
     434                 :         16 :                         free(rr->ds.digest);
     435                 :         16 :                         break;
     436                 :            : 
     437                 :        192 :                 case DNS_TYPE_SSHFP:
     438                 :        192 :                         free(rr->sshfp.fingerprint);
     439                 :        192 :                         break;
     440                 :            : 
     441                 :        276 :                 case DNS_TYPE_DNSKEY:
     442                 :        276 :                         free(rr->dnskey.key);
     443                 :        276 :                         break;
     444                 :            : 
     445                 :         16 :                 case DNS_TYPE_RRSIG:
     446                 :         16 :                         free(rr->rrsig.signer);
     447                 :         16 :                         free(rr->rrsig.signature);
     448                 :         16 :                         break;
     449                 :            : 
     450                 :        196 :                 case DNS_TYPE_NSEC:
     451                 :        196 :                         free(rr->nsec.next_domain_name);
     452                 :        196 :                         bitmap_free(rr->nsec.types);
     453                 :        196 :                         break;
     454                 :            : 
     455                 :          4 :                 case DNS_TYPE_NSEC3:
     456                 :          4 :                         free(rr->nsec3.next_hashed_name);
     457                 :          4 :                         free(rr->nsec3.salt);
     458                 :          4 :                         bitmap_free(rr->nsec3.types);
     459                 :          4 :                         break;
     460                 :            : 
     461                 :        772 :                 case DNS_TYPE_LOC:
     462                 :            :                 case DNS_TYPE_A:
     463                 :            :                 case DNS_TYPE_AAAA:
     464                 :        772 :                         break;
     465                 :            : 
     466                 :         32 :                 case DNS_TYPE_TLSA:
     467                 :         32 :                         free(rr->tlsa.data);
     468                 :         32 :                         break;
     469                 :            : 
     470                 :        160 :                 case DNS_TYPE_CAA:
     471                 :        160 :                         free(rr->caa.tag);
     472                 :        160 :                         free(rr->caa.value);
     473                 :        160 :                         break;
     474                 :            : 
     475                 :         32 :                 case DNS_TYPE_OPENPGPKEY:
     476                 :            :                 default:
     477         [ +  - ]:         32 :                         if (!rr->unparseable)
     478                 :         32 :                                 free(rr->generic.data);
     479                 :            :                 }
     480                 :            : 
     481         [ -  + ]:       3880 :                 if (rr->unparseable)
     482                 :          0 :                         free(rr->generic.data);
     483                 :            : 
     484                 :       3880 :                 free(rr->wire_format);
     485                 :       3880 :                 dns_resource_key_unref(rr->key);
     486                 :            :         }
     487                 :            : 
     488                 :       3880 :         free(rr->to_string);
     489                 :       3880 :         return mfree(rr);
     490                 :            : }
     491                 :            : 
     492   [ +  +  -  +  :       8944 : DEFINE_TRIVIAL_REF_UNREF_FUNC(DnsResourceRecord, dns_resource_record, dns_resource_record_free);
                   +  + ]
     493                 :            : 
     494                 :          0 : int dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *hostname) {
     495                 :          0 :         _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
     496                 :          0 :         _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
     497                 :          0 :         _cleanup_free_ char *ptr = NULL;
     498                 :            :         int r;
     499                 :            : 
     500         [ #  # ]:          0 :         assert(ret);
     501         [ #  # ]:          0 :         assert(address);
     502         [ #  # ]:          0 :         assert(hostname);
     503                 :            : 
     504                 :          0 :         r = dns_name_reverse(family, address, &ptr);
     505         [ #  # ]:          0 :         if (r < 0)
     506                 :          0 :                 return r;
     507                 :            : 
     508                 :          0 :         key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, ptr);
     509         [ #  # ]:          0 :         if (!key)
     510                 :          0 :                 return -ENOMEM;
     511                 :            : 
     512                 :          0 :         ptr = NULL;
     513                 :            : 
     514                 :          0 :         rr = dns_resource_record_new(key);
     515         [ #  # ]:          0 :         if (!rr)
     516                 :          0 :                 return -ENOMEM;
     517                 :            : 
     518                 :          0 :         rr->ptr.name = strdup(hostname);
     519         [ #  # ]:          0 :         if (!rr->ptr.name)
     520                 :          0 :                 return -ENOMEM;
     521                 :            : 
     522                 :          0 :         *ret = TAKE_PTR(rr);
     523                 :            : 
     524                 :          0 :         return 0;
     525                 :            : }
     526                 :            : 
     527                 :          0 : int dns_resource_record_new_address(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *name) {
     528                 :            :         DnsResourceRecord *rr;
     529                 :            : 
     530         [ #  # ]:          0 :         assert(ret);
     531         [ #  # ]:          0 :         assert(address);
     532         [ #  # ]:          0 :         assert(family);
     533                 :            : 
     534         [ #  # ]:          0 :         if (family == AF_INET) {
     535                 :            : 
     536                 :          0 :                 rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, name);
     537         [ #  # ]:          0 :                 if (!rr)
     538                 :          0 :                         return -ENOMEM;
     539                 :            : 
     540                 :          0 :                 rr->a.in_addr = address->in;
     541                 :            : 
     542         [ #  # ]:          0 :         } else if (family == AF_INET6) {
     543                 :            : 
     544                 :          0 :                 rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_AAAA, name);
     545         [ #  # ]:          0 :                 if (!rr)
     546                 :          0 :                         return -ENOMEM;
     547                 :            : 
     548                 :          0 :                 rr->aaaa.in6_addr = address->in6;
     549                 :            :         } else
     550                 :          0 :                 return -EAFNOSUPPORT;
     551                 :            : 
     552                 :          0 :         *ret = rr;
     553                 :            : 
     554                 :          0 :         return 0;
     555                 :            : }
     556                 :            : 
     557                 :            : #define FIELD_EQUAL(a, b, field) \
     558                 :            :         ((a).field ## _size == (b).field ## _size &&  \
     559                 :            :          memcmp_safe((a).field, (b).field, (a).field ## _size) == 0)
     560                 :            : 
     561                 :       1904 : int dns_resource_record_payload_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
     562                 :            :         int r;
     563                 :            : 
     564                 :            :         /* Check if a and b are the same, but don't look at their keys */
     565                 :            : 
     566         [ -  + ]:       1904 :         if (a->unparseable != b->unparseable)
     567                 :          0 :                 return 0;
     568                 :            : 
     569   [ +  -  -  +  :       1904 :         switch (a->unparseable ? _DNS_TYPE_INVALID : a->key->type) {
          -  +  +  +  +  
          +  +  -  +  +  
          -  +  -  +  +  
                      + ]
     570                 :            : 
     571                 :          0 :         case DNS_TYPE_SRV:
     572                 :          0 :                 r = dns_name_equal(a->srv.name, b->srv.name);
     573         [ #  # ]:          0 :                 if (r <= 0)
     574                 :          0 :                         return r;
     575                 :            : 
     576                 :          0 :                 return a->srv.priority == b->srv.priority &&
     577   [ #  #  #  # ]:          0 :                        a->srv.weight == b->srv.weight &&
     578         [ #  # ]:          0 :                        a->srv.port == b->srv.port;
     579                 :            : 
     580                 :        608 :         case DNS_TYPE_PTR:
     581                 :            :         case DNS_TYPE_NS:
     582                 :            :         case DNS_TYPE_CNAME:
     583                 :            :         case DNS_TYPE_DNAME:
     584                 :        608 :                 return dns_name_equal(a->ptr.name, b->ptr.name);
     585                 :            : 
     586                 :          0 :         case DNS_TYPE_HINFO:
     587         [ #  # ]:          0 :                 return strcaseeq(a->hinfo.cpu, b->hinfo.cpu) &&
     588         [ #  # ]:          0 :                        strcaseeq(a->hinfo.os, b->hinfo.os);
     589                 :            : 
     590                 :        144 :         case DNS_TYPE_SPF: /* exactly the same as TXT */
     591                 :            :         case DNS_TYPE_TXT:
     592                 :        144 :                 return dns_txt_item_equal(a->txt.items, b->txt.items);
     593                 :            : 
     594                 :        224 :         case DNS_TYPE_A:
     595                 :        224 :                 return memcmp(&a->a.in_addr, &b->a.in_addr, sizeof(struct in_addr)) == 0;
     596                 :            : 
     597                 :        112 :         case DNS_TYPE_AAAA:
     598                 :        112 :                 return memcmp(&a->aaaa.in6_addr, &b->aaaa.in6_addr, sizeof(struct in6_addr)) == 0;
     599                 :            : 
     600                 :        112 :         case DNS_TYPE_SOA:
     601                 :        112 :                 r = dns_name_equal(a->soa.mname, b->soa.mname);
     602         [ -  + ]:        112 :                 if (r <= 0)
     603                 :          0 :                         return r;
     604                 :        112 :                 r = dns_name_equal(a->soa.rname, b->soa.rname);
     605         [ -  + ]:        112 :                 if (r <= 0)
     606                 :          0 :                         return r;
     607                 :            : 
     608                 :        224 :                 return a->soa.serial  == b->soa.serial &&
     609         [ +  - ]:        112 :                        a->soa.refresh == b->soa.refresh &&
     610         [ +  - ]:        112 :                        a->soa.retry   == b->soa.retry &&
     611   [ +  -  +  - ]:        336 :                        a->soa.expire  == b->soa.expire &&
     612         [ +  - ]:        112 :                        a->soa.minimum == b->soa.minimum;
     613                 :            : 
     614                 :        224 :         case DNS_TYPE_MX:
     615         [ -  + ]:        224 :                 if (a->mx.priority != b->mx.priority)
     616                 :          0 :                         return 0;
     617                 :            : 
     618                 :        224 :                 return dns_name_equal(a->mx.exchange, b->mx.exchange);
     619                 :            : 
     620                 :         48 :         case DNS_TYPE_LOC:
     621         [ -  + ]:         48 :                 assert(a->loc.version == b->loc.version);
     622                 :            : 
     623                 :         96 :                 return a->loc.size == b->loc.size &&
     624         [ +  - ]:         48 :                        a->loc.horiz_pre == b->loc.horiz_pre &&
     625         [ +  - ]:         48 :                        a->loc.vert_pre == b->loc.vert_pre &&
     626         [ +  - ]:         48 :                        a->loc.latitude == b->loc.latitude &&
     627   [ +  -  +  - ]:        144 :                        a->loc.longitude == b->loc.longitude &&
     628         [ +  - ]:         48 :                        a->loc.altitude == b->loc.altitude;
     629                 :            : 
     630                 :          0 :         case DNS_TYPE_DS:
     631                 :          0 :                 return a->ds.key_tag == b->ds.key_tag &&
     632         [ #  # ]:          0 :                        a->ds.algorithm == b->ds.algorithm &&
     633   [ #  #  #  # ]:          0 :                        a->ds.digest_type == b->ds.digest_type &&
     634   [ #  #  #  # ]:          0 :                        FIELD_EQUAL(a->ds, b->ds, digest);
     635                 :            : 
     636                 :         96 :         case DNS_TYPE_SSHFP:
     637                 :        192 :                 return a->sshfp.algorithm == b->sshfp.algorithm &&
     638   [ +  -  +  - ]:        192 :                        a->sshfp.fptype == b->sshfp.fptype &&
     639   [ +  -  +  - ]:         96 :                        FIELD_EQUAL(a->sshfp, b->sshfp, fingerprint);
     640                 :            : 
     641                 :        128 :         case DNS_TYPE_DNSKEY:
     642                 :        256 :                 return a->dnskey.flags == b->dnskey.flags &&
     643         [ +  - ]:        128 :                        a->dnskey.protocol == b->dnskey.protocol &&
     644   [ +  -  +  - ]:        384 :                        a->dnskey.algorithm == b->dnskey.algorithm &&
     645   [ +  -  +  - ]:        128 :                        FIELD_EQUAL(a->dnskey, b->dnskey, key);
     646                 :            : 
     647                 :          0 :         case DNS_TYPE_RRSIG:
     648                 :            :                 /* do the fast comparisons first */
     649                 :          0 :                 return a->rrsig.type_covered == b->rrsig.type_covered &&
     650         [ #  # ]:          0 :                        a->rrsig.algorithm == b->rrsig.algorithm &&
     651         [ #  # ]:          0 :                        a->rrsig.labels == b->rrsig.labels &&
     652         [ #  # ]:          0 :                        a->rrsig.original_ttl == b->rrsig.original_ttl &&
     653         [ #  # ]:          0 :                        a->rrsig.expiration == b->rrsig.expiration &&
     654         [ #  # ]:          0 :                        a->rrsig.inception == b->rrsig.inception &&
     655         [ #  # ]:          0 :                        a->rrsig.key_tag == b->rrsig.key_tag &&
     656   [ #  #  #  #  :          0 :                        FIELD_EQUAL(a->rrsig, b->rrsig, signature) &&
             #  #  #  # ]
     657                 :          0 :                        dns_name_equal(a->rrsig.signer, b->rrsig.signer);
     658                 :            : 
     659                 :         96 :         case DNS_TYPE_NSEC:
     660   [ +  -  +  - ]:        192 :                 return dns_name_equal(a->nsec.next_domain_name, b->nsec.next_domain_name) &&
     661                 :         96 :                        bitmap_equal(a->nsec.types, b->nsec.types);
     662                 :            : 
     663                 :          0 :         case DNS_TYPE_NSEC3:
     664                 :          0 :                 return a->nsec3.algorithm == b->nsec3.algorithm &&
     665         [ #  # ]:          0 :                        a->nsec3.flags == b->nsec3.flags &&
     666         [ #  # ]:          0 :                        a->nsec3.iterations == b->nsec3.iterations &&
     667   [ #  #  #  # ]:          0 :                        FIELD_EQUAL(a->nsec3, b->nsec3, salt) &&
     668   [ #  #  #  #  :          0 :                        FIELD_EQUAL(a->nsec3, b->nsec3, next_hashed_name) &&
             #  #  #  # ]
     669                 :          0 :                        bitmap_equal(a->nsec3.types, b->nsec3.types);
     670                 :            : 
     671                 :         16 :         case DNS_TYPE_TLSA:
     672                 :         32 :                 return a->tlsa.cert_usage == b->tlsa.cert_usage &&
     673         [ +  - ]:         16 :                        a->tlsa.selector == b->tlsa.selector &&
     674   [ +  -  +  - ]:         48 :                        a->tlsa.matching_type == b->tlsa.matching_type &&
     675   [ +  -  +  - ]:         16 :                        FIELD_EQUAL(a->tlsa, b->tlsa, data);
     676                 :            : 
     677                 :         80 :         case DNS_TYPE_CAA:
     678                 :        160 :                 return a->caa.flags == b->caa.flags &&
     679   [ +  -  +  - ]:        160 :                        streq(a->caa.tag, b->caa.tag) &&
     680   [ +  -  +  - ]:         80 :                        FIELD_EQUAL(a->caa, b->caa, value);
     681                 :            : 
     682                 :         16 :         case DNS_TYPE_OPENPGPKEY:
     683                 :            :         default:
     684   [ +  -  +  - ]:         16 :                 return FIELD_EQUAL(a->generic, b->generic, data);
     685                 :            :         }
     686                 :            : }
     687                 :            : 
     688                 :       1904 : int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
     689                 :            :         int r;
     690                 :            : 
     691         [ -  + ]:       1904 :         assert(a);
     692         [ -  + ]:       1904 :         assert(b);
     693                 :            : 
     694         [ -  + ]:       1904 :         if (a == b)
     695                 :          0 :                 return 1;
     696                 :            : 
     697                 :       1904 :         r = dns_resource_key_equal(a->key, b->key);
     698         [ -  + ]:       1904 :         if (r <= 0)
     699                 :          0 :                 return r;
     700                 :            : 
     701                 :       1904 :         return dns_resource_record_payload_equal(a, b);
     702                 :            : }
     703                 :            : 
     704                 :         72 : static char* format_location(uint32_t latitude, uint32_t longitude, uint32_t altitude,
     705                 :            :                              uint8_t size, uint8_t horiz_pre, uint8_t vert_pre) {
     706                 :            :         char *s;
     707         [ +  - ]:         72 :         char NS = latitude >= 1U<<31 ? 'N' : 'S';
     708         [ -  + ]:         72 :         char EW = longitude >= 1U<<31 ? 'E' : 'W';
     709                 :            : 
     710         [ +  - ]:         72 :         int lat = latitude >= 1U<<31 ? (int) (latitude - (1U<<31)) : (int) ((1U<<31) - latitude);
     711         [ -  + ]:         72 :         int lon = longitude >= 1U<<31 ? (int) (longitude - (1U<<31)) : (int) ((1U<<31) - longitude);
     712         [ +  - ]:         72 :         double alt = altitude >= 10000000u ? altitude - 10000000u : -(double)(10000000u - altitude);
     713                 :         72 :         double siz = (size >> 4) * exp10((double) (size & 0xF));
     714                 :         72 :         double hor = (horiz_pre >> 4) * exp10((double) (horiz_pre & 0xF));
     715                 :         72 :         double ver = (vert_pre >> 4) * exp10((double) (vert_pre & 0xF));
     716                 :            : 
     717         [ -  + ]:         72 :         if (asprintf(&s, "%d %d %.3f %c %d %d %.3f %c %.2fm %.2fm %.2fm %.2fm",
     718                 :            :                      (lat / 60000 / 60),
     719                 :         72 :                      (lat / 60000) % 60,
     720                 :         72 :                      (lat % 60000) / 1000.,
     721                 :            :                      NS,
     722                 :            :                      (lon / 60000 / 60),
     723                 :         72 :                      (lon / 60000) % 60,
     724                 :         72 :                      (lon % 60000) / 1000.,
     725                 :            :                      EW,
     726                 :            :                      alt / 100.,
     727                 :            :                      siz / 100.,
     728                 :            :                      hor / 100.,
     729                 :            :                      ver / 100.) < 0)
     730                 :          0 :                 return NULL;
     731                 :            : 
     732                 :         72 :         return s;
     733                 :            : }
     734                 :            : 
     735                 :         32 : static int format_timestamp_dns(char *buf, size_t l, time_t sec) {
     736                 :            :         struct tm tm;
     737                 :            : 
     738         [ -  + ]:         32 :         assert(buf);
     739         [ -  + ]:         32 :         assert(l > STRLEN("YYYYMMDDHHmmSS"));
     740                 :            : 
     741         [ -  + ]:         32 :         if (!gmtime_r(&sec, &tm))
     742                 :          0 :                 return -EINVAL;
     743                 :            : 
     744         [ -  + ]:         32 :         if (strftime(buf, l, "%Y%m%d%H%M%S", &tm) <= 0)
     745                 :          0 :                 return -EINVAL;
     746                 :            : 
     747                 :         32 :         return 0;
     748                 :            : }
     749                 :            : 
     750                 :        152 : static char *format_types(Bitmap *types) {
     751                 :        152 :         _cleanup_strv_free_ char **strv = NULL;
     752                 :        152 :         _cleanup_free_ char *str = NULL;
     753                 :            :         Iterator i;
     754                 :            :         unsigned type;
     755                 :            :         int r;
     756                 :            : 
     757         [ +  + ]:       1028 :         BITMAP_FOREACH(type, types, i) {
     758         [ +  + ]:        876 :                 if (dns_type_to_string(type)) {
     759                 :        872 :                         r = strv_extend(&strv, dns_type_to_string(type));
     760         [ -  + ]:        872 :                         if (r < 0)
     761                 :          0 :                                 return NULL;
     762                 :            :                 } else {
     763                 :            :                         char *t;
     764                 :            : 
     765                 :          4 :                         r = asprintf(&t, "TYPE%u", type);
     766         [ -  + ]:          4 :                         if (r < 0)
     767                 :          0 :                                 return NULL;
     768                 :            : 
     769                 :          4 :                         r = strv_consume(&strv, t);
     770         [ -  + ]:          4 :                         if (r < 0)
     771                 :          0 :                                 return NULL;
     772                 :            :                 }
     773                 :            :         }
     774                 :            : 
     775                 :        152 :         str = strv_join(strv, " ");
     776         [ -  + ]:        152 :         if (!str)
     777                 :          0 :                 return NULL;
     778                 :            : 
     779                 :        152 :         return strjoin("( ", str, " )");
     780                 :            : }
     781                 :            : 
     782                 :        216 : static char *format_txt(DnsTxtItem *first) {
     783                 :            :         DnsTxtItem *i;
     784                 :        216 :         size_t c = 1;
     785                 :            :         char *p, *s;
     786                 :            : 
     787         [ +  + ]:        432 :         LIST_FOREACH(items, i, first)
     788                 :        216 :                 c += i->length * 4 + 3;
     789                 :            : 
     790                 :        216 :         p = s = new(char, c);
     791         [ -  + ]:        216 :         if (!s)
     792                 :          0 :                 return NULL;
     793                 :            : 
     794         [ +  + ]:        432 :         LIST_FOREACH(items, i, first) {
     795                 :            :                 size_t j;
     796                 :            : 
     797         [ -  + ]:        216 :                 if (i != first)
     798                 :          0 :                         *(p++) = ' ';
     799                 :            : 
     800                 :        216 :                 *(p++) = '"';
     801                 :            : 
     802         [ +  + ]:      26448 :                 for (j = 0; j < i->length; j++) {
     803   [ +  -  +  -  :      26232 :                         if (i->data[j] < ' ' || i->data[j] == '"' || i->data[j] >= 127) {
                   -  + ]
     804                 :          0 :                                 *(p++) = '\\';
     805                 :          0 :                                 *(p++) = '0' + (i->data[j] / 100);
     806                 :          0 :                                 *(p++) = '0' + ((i->data[j] / 10) % 10);
     807                 :          0 :                                 *(p++) = '0' + (i->data[j] % 10);
     808                 :            :                         } else
     809                 :      26232 :                                 *(p++) = i->data[j];
     810                 :            :                 }
     811                 :            : 
     812                 :        216 :                 *(p++) = '"';
     813                 :            :         }
     814                 :            : 
     815                 :        216 :         *p = 0;
     816                 :        216 :         return s;
     817                 :            : }
     818                 :            : 
     819                 :       5784 : const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
     820                 :       5784 :         _cleanup_free_ char *t = NULL;
     821                 :            :         char *s, k[DNS_RESOURCE_KEY_STRING_MAX];
     822                 :            :         int r;
     823                 :            : 
     824         [ -  + ]:       5784 :         assert(rr);
     825                 :            : 
     826         [ +  + ]:       5784 :         if (rr->to_string)
     827                 :       2856 :                 return rr->to_string;
     828                 :            : 
     829                 :       2928 :         dns_resource_key_to_string(rr->key, k, sizeof(k));
     830                 :            : 
     831   [ +  -  -  +  :       2928 :         switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
          -  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
                   +  - ]
     832                 :            : 
     833                 :          0 :         case DNS_TYPE_SRV:
     834                 :          0 :                 r = asprintf(&s, "%s %u %u %u %s",
     835                 :            :                              k,
     836                 :          0 :                              rr->srv.priority,
     837                 :          0 :                              rr->srv.weight,
     838                 :          0 :                              rr->srv.port,
     839                 :          0 :                              strna(rr->srv.name));
     840         [ #  # ]:          0 :                 if (r < 0)
     841                 :          0 :                         return NULL;
     842                 :          0 :                 break;
     843                 :            : 
     844                 :        912 :         case DNS_TYPE_PTR:
     845                 :            :         case DNS_TYPE_NS:
     846                 :            :         case DNS_TYPE_CNAME:
     847                 :            :         case DNS_TYPE_DNAME:
     848                 :        912 :                 s = strjoin(k, " ", rr->ptr.name);
     849         [ -  + ]:        912 :                 if (!s)
     850                 :          0 :                         return NULL;
     851                 :            : 
     852                 :        912 :                 break;
     853                 :            : 
     854                 :          0 :         case DNS_TYPE_HINFO:
     855                 :          0 :                 s = strjoin(k, " ", rr->hinfo.cpu, " ", rr->hinfo.os);
     856         [ #  # ]:          0 :                 if (!s)
     857                 :          0 :                         return NULL;
     858                 :          0 :                 break;
     859                 :            : 
     860                 :        216 :         case DNS_TYPE_SPF: /* exactly the same as TXT */
     861                 :            :         case DNS_TYPE_TXT:
     862                 :        216 :                 t = format_txt(rr->txt.items);
     863         [ -  + ]:        216 :                 if (!t)
     864                 :          0 :                         return NULL;
     865                 :            : 
     866                 :        216 :                 s = strjoin(k, " ", t);
     867         [ -  + ]:        216 :                 if (!s)
     868                 :          0 :                         return NULL;
     869                 :        216 :                 break;
     870                 :            : 
     871                 :        340 :         case DNS_TYPE_A: {
     872         [ -  + ]:        340 :                 _cleanup_free_ char *x = NULL;
     873                 :            : 
     874                 :        340 :                 r = in_addr_to_string(AF_INET, (const union in_addr_union*) &rr->a.in_addr, &x);
     875         [ -  + ]:        340 :                 if (r < 0)
     876                 :          0 :                         return NULL;
     877                 :            : 
     878                 :        340 :                 s = strjoin(k, " ", x);
     879         [ -  + ]:        340 :                 if (!s)
     880                 :          0 :                         return NULL;
     881                 :        340 :                 break;
     882                 :            :         }
     883                 :            : 
     884                 :        168 :         case DNS_TYPE_AAAA:
     885                 :        168 :                 r = in_addr_to_string(AF_INET6, (const union in_addr_union*) &rr->aaaa.in6_addr, &t);
     886         [ -  + ]:        168 :                 if (r < 0)
     887                 :          0 :                         return NULL;
     888                 :            : 
     889                 :        168 :                 s = strjoin(k, " ", t);
     890         [ -  + ]:        168 :                 if (!s)
     891                 :          0 :                         return NULL;
     892                 :        168 :                 break;
     893                 :            : 
     894                 :        168 :         case DNS_TYPE_SOA:
     895                 :        168 :                 r = asprintf(&s, "%s %s %s %u %u %u %u %u",
     896                 :            :                              k,
     897                 :        168 :                              strna(rr->soa.mname),
     898                 :        168 :                              strna(rr->soa.rname),
     899                 :            :                              rr->soa.serial,
     900                 :            :                              rr->soa.refresh,
     901                 :            :                              rr->soa.retry,
     902                 :            :                              rr->soa.expire,
     903                 :            :                              rr->soa.minimum);
     904         [ -  + ]:        168 :                 if (r < 0)
     905                 :          0 :                         return NULL;
     906                 :        168 :                 break;
     907                 :            : 
     908                 :        344 :         case DNS_TYPE_MX:
     909                 :        688 :                 r = asprintf(&s, "%s %u %s",
     910                 :            :                              k,
     911                 :        344 :                              rr->mx.priority,
     912                 :            :                              rr->mx.exchange);
     913         [ -  + ]:        344 :                 if (r < 0)
     914                 :          0 :                         return NULL;
     915                 :        344 :                 break;
     916                 :            : 
     917                 :         72 :         case DNS_TYPE_LOC:
     918         [ -  + ]:         72 :                 assert(rr->loc.version == 0);
     919                 :            : 
     920                 :        288 :                 t = format_location(rr->loc.latitude,
     921                 :            :                                     rr->loc.longitude,
     922                 :            :                                     rr->loc.altitude,
     923                 :         72 :                                     rr->loc.size,
     924                 :         72 :                                     rr->loc.horiz_pre,
     925                 :         72 :                                     rr->loc.vert_pre);
     926         [ -  + ]:         72 :                 if (!t)
     927                 :          0 :                         return NULL;
     928                 :            : 
     929                 :         72 :                 s = strjoin(k, " ", t);
     930         [ -  + ]:         72 :                 if (!s)
     931                 :          0 :                         return NULL;
     932                 :         72 :                 break;
     933                 :            : 
     934                 :         16 :         case DNS_TYPE_DS:
     935                 :         16 :                 t = hexmem(rr->ds.digest, rr->ds.digest_size);
     936         [ -  + ]:         16 :                 if (!t)
     937                 :          0 :                         return NULL;
     938                 :            : 
     939                 :         64 :                 r = asprintf(&s, "%s %u %u %u %s",
     940                 :            :                              k,
     941                 :         16 :                              rr->ds.key_tag,
     942                 :         16 :                              rr->ds.algorithm,
     943                 :         16 :                              rr->ds.digest_type,
     944                 :            :                              t);
     945         [ -  + ]:         16 :                 if (r < 0)
     946                 :          0 :                         return NULL;
     947                 :         16 :                 break;
     948                 :            : 
     949                 :        144 :         case DNS_TYPE_SSHFP:
     950                 :        144 :                 t = hexmem(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size);
     951         [ -  + ]:        144 :                 if (!t)
     952                 :          0 :                         return NULL;
     953                 :            : 
     954                 :        432 :                 r = asprintf(&s, "%s %u %u %s",
     955                 :            :                              k,
     956                 :        144 :                              rr->sshfp.algorithm,
     957                 :        144 :                              rr->sshfp.fptype,
     958                 :            :                              t);
     959         [ -  + ]:        144 :                 if (r < 0)
     960                 :          0 :                         return NULL;
     961                 :        144 :                 break;
     962                 :            : 
     963                 :        212 :         case DNS_TYPE_DNSKEY: {
     964         [ -  + ]:        212 :                 _cleanup_free_ char *alg = NULL;
     965                 :            :                 char *ss;
     966                 :            :                 uint16_t key_tag;
     967                 :            : 
     968                 :        212 :                 key_tag = dnssec_keytag(rr, true);
     969                 :            : 
     970                 :        212 :                 r = dnssec_algorithm_to_string_alloc(rr->dnskey.algorithm, &alg);
     971         [ -  + ]:        212 :                 if (r < 0)
     972                 :          0 :                         return NULL;
     973                 :            : 
     974                 :        636 :                 r = asprintf(&s, "%s %u %u %s",
     975                 :            :                              k,
     976                 :        212 :                              rr->dnskey.flags,
     977                 :        212 :                              rr->dnskey.protocol,
     978                 :            :                              alg);
     979         [ -  + ]:        212 :                 if (r < 0)
     980                 :          0 :                         return NULL;
     981                 :            : 
     982                 :        424 :                 r = base64_append(&s, r,
     983                 :        212 :                                   rr->dnskey.key, rr->dnskey.key_size,
     984                 :        212 :                                   8, columns());
     985         [ -  + ]:        212 :                 if (r < 0)
     986                 :          0 :                         return NULL;
     987                 :            : 
     988                 :        636 :                 r = asprintf(&ss, "%s\n"
     989                 :            :                              "        -- Flags:%s%s%s\n"
     990                 :            :                              "        -- Key tag: %u",
     991                 :            :                              s,
     992         [ +  + ]:        212 :                              rr->dnskey.flags & DNSKEY_FLAG_SEP ? " SEP" : "",
     993         [ -  + ]:        212 :                              rr->dnskey.flags & DNSKEY_FLAG_REVOKE ? " REVOKE" : "",
     994         [ +  - ]:        212 :                              rr->dnskey.flags & DNSKEY_FLAG_ZONE_KEY ? " ZONE_KEY" : "",
     995                 :            :                              key_tag);
     996         [ -  + ]:        212 :                 if (r < 0)
     997                 :          0 :                         return NULL;
     998                 :        212 :                 free(s);
     999                 :        212 :                 s = ss;
    1000                 :            : 
    1001                 :        212 :                 break;
    1002                 :            :         }
    1003                 :            : 
    1004                 :         16 :         case DNS_TYPE_RRSIG: {
    1005         [ -  + ]:         16 :                 _cleanup_free_ char *alg = NULL;
    1006                 :            :                 char expiration[STRLEN("YYYYMMDDHHmmSS") + 1], inception[STRLEN("YYYYMMDDHHmmSS") + 1];
    1007                 :            :                 const char *type;
    1008                 :            : 
    1009                 :         16 :                 type = dns_type_to_string(rr->rrsig.type_covered);
    1010                 :            : 
    1011                 :         16 :                 r = dnssec_algorithm_to_string_alloc(rr->rrsig.algorithm, &alg);
    1012         [ -  + ]:         16 :                 if (r < 0)
    1013                 :          0 :                         return NULL;
    1014                 :            : 
    1015                 :         16 :                 r = format_timestamp_dns(expiration, sizeof(expiration), rr->rrsig.expiration);
    1016         [ -  + ]:         16 :                 if (r < 0)
    1017                 :          0 :                         return NULL;
    1018                 :            : 
    1019                 :         16 :                 r = format_timestamp_dns(inception, sizeof(inception), rr->rrsig.inception);
    1020         [ -  + ]:         16 :                 if (r < 0)
    1021                 :          0 :                         return NULL;
    1022                 :            : 
    1023                 :            :                 /* TYPE?? follows
    1024                 :            :                  * http://tools.ietf.org/html/rfc3597#section-5 */
    1025                 :            : 
    1026                 :         32 :                 r = asprintf(&s, "%s %s%.*u %s %u %u %s %s %u %s",
    1027                 :            :                              k,
    1028         [ +  - ]:         16 :                              type ?: "TYPE",
    1029                 :          0 :                              type ? 0 : 1, type ? 0u : (unsigned) rr->rrsig.type_covered,
    1030                 :            :                              alg,
    1031                 :         16 :                              rr->rrsig.labels,
    1032                 :            :                              rr->rrsig.original_ttl,
    1033                 :            :                              expiration,
    1034                 :            :                              inception,
    1035         [ -  + ]:         16 :                              rr->rrsig.key_tag,
    1036                 :            :                              rr->rrsig.signer);
    1037         [ -  + ]:         16 :                 if (r < 0)
    1038                 :          0 :                         return NULL;
    1039                 :            : 
    1040                 :         32 :                 r = base64_append(&s, r,
    1041                 :         16 :                                   rr->rrsig.signature, rr->rrsig.signature_size,
    1042                 :         16 :                                   8, columns());
    1043         [ -  + ]:         16 :                 if (r < 0)
    1044                 :          0 :                         return NULL;
    1045                 :            : 
    1046                 :         16 :                 break;
    1047                 :            :         }
    1048                 :            : 
    1049                 :        148 :         case DNS_TYPE_NSEC:
    1050                 :        148 :                 t = format_types(rr->nsec.types);
    1051         [ -  + ]:        148 :                 if (!t)
    1052                 :          0 :                         return NULL;
    1053                 :            : 
    1054                 :        148 :                 r = asprintf(&s, "%s %s %s",
    1055                 :            :                              k,
    1056                 :            :                              rr->nsec.next_domain_name,
    1057                 :            :                              t);
    1058         [ -  + ]:        148 :                 if (r < 0)
    1059                 :          0 :                         return NULL;
    1060                 :        148 :                 break;
    1061                 :            : 
    1062                 :          4 :         case DNS_TYPE_NSEC3: {
    1063   [ -  +  -  + ]:          8 :                 _cleanup_free_ char *salt = NULL, *hash = NULL;
    1064                 :            : 
    1065         [ +  - ]:          4 :                 if (rr->nsec3.salt_size > 0) {
    1066                 :          4 :                         salt = hexmem(rr->nsec3.salt, rr->nsec3.salt_size);
    1067         [ -  + ]:          4 :                         if (!salt)
    1068                 :          0 :                                 return NULL;
    1069                 :            :                 }
    1070                 :            : 
    1071                 :          4 :                 hash = base32hexmem(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, false);
    1072         [ -  + ]:          4 :                 if (!hash)
    1073                 :          0 :                         return NULL;
    1074                 :            : 
    1075                 :          4 :                 t = format_types(rr->nsec3.types);
    1076         [ -  + ]:          4 :                 if (!t)
    1077                 :          0 :                         return NULL;
    1078                 :            : 
    1079                 :          4 :                 r = asprintf(&s, "%s %"PRIu8" %"PRIu8" %"PRIu16" %s %s %s",
    1080                 :            :                              k,
    1081                 :          4 :                              rr->nsec3.algorithm,
    1082                 :          4 :                              rr->nsec3.flags,
    1083                 :          4 :                              rr->nsec3.iterations,
    1084         [ +  - ]:          4 :                              rr->nsec3.salt_size > 0 ? salt : "-",
    1085                 :            :                              hash,
    1086                 :            :                              t);
    1087         [ -  + ]:          4 :                 if (r < 0)
    1088                 :          0 :                         return NULL;
    1089                 :            : 
    1090                 :          4 :                 break;
    1091                 :            :         }
    1092                 :            : 
    1093                 :         24 :         case DNS_TYPE_TLSA: {
    1094                 :            :                 const char *cert_usage, *selector, *matching_type;
    1095                 :            : 
    1096                 :         24 :                 cert_usage = tlsa_cert_usage_to_string(rr->tlsa.cert_usage);
    1097                 :         24 :                 selector = tlsa_selector_to_string(rr->tlsa.selector);
    1098                 :         24 :                 matching_type = tlsa_matching_type_to_string(rr->tlsa.matching_type);
    1099                 :            : 
    1100                 :         24 :                 t = hexmem(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size);
    1101         [ -  + ]:         24 :                 if (!t)
    1102                 :          0 :                         return NULL;
    1103                 :            : 
    1104                 :         96 :                 r = asprintf(&s,
    1105                 :            :                              "%s %u %u %u %s\n"
    1106                 :            :                              "        -- Cert. usage: %s\n"
    1107                 :            :                              "        -- Selector: %s\n"
    1108                 :            :                              "        -- Matching type: %s",
    1109                 :            :                              k,
    1110                 :         24 :                              rr->tlsa.cert_usage,
    1111                 :         24 :                              rr->tlsa.selector,
    1112                 :         24 :                              rr->tlsa.matching_type,
    1113                 :            :                              t,
    1114                 :            :                              cert_usage,
    1115                 :            :                              selector,
    1116                 :            :                              matching_type);
    1117         [ -  + ]:         24 :                 if (r < 0)
    1118                 :          0 :                         return NULL;
    1119                 :            : 
    1120                 :         24 :                 break;
    1121                 :            :         }
    1122                 :            : 
    1123                 :        120 :         case DNS_TYPE_CAA: {
    1124         [ -  + ]:        120 :                 _cleanup_free_ char *value;
    1125                 :            : 
    1126                 :        120 :                 value = octescape(rr->caa.value, rr->caa.value_size);
    1127         [ -  + ]:        120 :                 if (!value)
    1128                 :          0 :                         return NULL;
    1129                 :            : 
    1130                 :        360 :                 r = asprintf(&s, "%s %u %s \"%s\"%s%s%s%.0u",
    1131                 :            :                              k,
    1132                 :        120 :                              rr->caa.flags,
    1133                 :            :                              rr->caa.tag,
    1134                 :            :                              value,
    1135         [ +  + ]:        120 :                              rr->caa.flags ? "\n        -- Flags:" : "",
    1136         [ +  + ]:        120 :                              rr->caa.flags & CAA_FLAG_CRITICAL ? " critical" : "",
    1137                 :        120 :                              rr->caa.flags & ~CAA_FLAG_CRITICAL ? " " : "",
    1138         [ +  + ]:        120 :                              rr->caa.flags & ~CAA_FLAG_CRITICAL);
    1139         [ -  + ]:        120 :                 if (r < 0)
    1140                 :          0 :                         return NULL;
    1141                 :            : 
    1142                 :        120 :                 break;
    1143                 :            :         }
    1144                 :            : 
    1145                 :         24 :         case DNS_TYPE_OPENPGPKEY: {
    1146                 :         24 :                 r = asprintf(&s, "%s", k);
    1147         [ -  + ]:         24 :                 if (r < 0)
    1148                 :          0 :                         return NULL;
    1149                 :            : 
    1150                 :         48 :                 r = base64_append(&s, r,
    1151                 :         24 :                                   rr->generic.data, rr->generic.data_size,
    1152                 :         24 :                                   8, columns());
    1153         [ -  + ]:         24 :                 if (r < 0)
    1154                 :          0 :                         return NULL;
    1155                 :         24 :                 break;
    1156                 :            :         }
    1157                 :            : 
    1158                 :          0 :         default:
    1159                 :          0 :                 t = hexmem(rr->generic.data, rr->generic.data_size);
    1160         [ #  # ]:          0 :                 if (!t)
    1161                 :          0 :                         return NULL;
    1162                 :            : 
    1163                 :            :                 /* Format as documented in RFC 3597, Section 5 */
    1164                 :          0 :                 r = asprintf(&s, "%s \\# %zu %s", k, rr->generic.data_size, t);
    1165         [ #  # ]:          0 :                 if (r < 0)
    1166                 :          0 :                         return NULL;
    1167                 :          0 :                 break;
    1168                 :            :         }
    1169                 :            : 
    1170                 :       2928 :         rr->to_string = s;
    1171                 :       2928 :         return s;
    1172                 :            : }
    1173                 :            : 
    1174                 :          0 : ssize_t dns_resource_record_payload(DnsResourceRecord *rr, void **out) {
    1175         [ #  # ]:          0 :         assert(rr);
    1176         [ #  # ]:          0 :         assert(out);
    1177                 :            : 
    1178   [ #  #  #  #  :          0 :         switch(rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
                   #  # ]
    1179                 :          0 :         case DNS_TYPE_SRV:
    1180                 :            :         case DNS_TYPE_PTR:
    1181                 :            :         case DNS_TYPE_NS:
    1182                 :            :         case DNS_TYPE_CNAME:
    1183                 :            :         case DNS_TYPE_DNAME:
    1184                 :            :         case DNS_TYPE_HINFO:
    1185                 :            :         case DNS_TYPE_SPF:
    1186                 :            :         case DNS_TYPE_TXT:
    1187                 :            :         case DNS_TYPE_A:
    1188                 :            :         case DNS_TYPE_AAAA:
    1189                 :            :         case DNS_TYPE_SOA:
    1190                 :            :         case DNS_TYPE_MX:
    1191                 :            :         case DNS_TYPE_LOC:
    1192                 :            :         case DNS_TYPE_DS:
    1193                 :            :         case DNS_TYPE_DNSKEY:
    1194                 :            :         case DNS_TYPE_RRSIG:
    1195                 :            :         case DNS_TYPE_NSEC:
    1196                 :            :         case DNS_TYPE_NSEC3:
    1197                 :          0 :                 return -EINVAL;
    1198                 :            : 
    1199                 :          0 :         case DNS_TYPE_SSHFP:
    1200                 :          0 :                 *out = rr->sshfp.fingerprint;
    1201                 :          0 :                 return rr->sshfp.fingerprint_size;
    1202                 :            : 
    1203                 :          0 :         case DNS_TYPE_TLSA:
    1204                 :          0 :                 *out = rr->tlsa.data;
    1205                 :          0 :                 return rr->tlsa.data_size;
    1206                 :            : 
    1207                 :          0 :         case DNS_TYPE_OPENPGPKEY:
    1208                 :            :         default:
    1209                 :          0 :                 *out = rr->generic.data;
    1210                 :          0 :                 return rr->generic.data_size;
    1211                 :            :         }
    1212                 :            : }
    1213                 :            : 
    1214                 :        968 : int dns_resource_record_to_wire_format(DnsResourceRecord *rr, bool canonical) {
    1215                 :            : 
    1216                 :        968 :         DnsPacket packet = {
    1217                 :            :                 .n_ref = 1,
    1218                 :            :                 .protocol = DNS_PROTOCOL_DNS,
    1219                 :            :                 .on_stack = true,
    1220                 :            :                 .refuse_compression = true,
    1221                 :            :                 .canonical_form = canonical,
    1222                 :            :         };
    1223                 :            : 
    1224                 :            :         size_t start, rds;
    1225                 :            :         int r;
    1226                 :            : 
    1227         [ -  + ]:        968 :         assert(rr);
    1228                 :            : 
    1229                 :            :         /* Generates the RR in wire-format, optionally in the
    1230                 :            :          * canonical form as discussed in the DNSSEC RFC 4034, Section
    1231                 :            :          * 6.2. We allocate a throw-away DnsPacket object on the stack
    1232                 :            :          * here, because we need some book-keeping for memory
    1233                 :            :          * management, and can reuse the DnsPacket serializer, that
    1234                 :            :          * can generate the canonical form, too, but also knows label
    1235                 :            :          * compression and suchlike. */
    1236                 :            : 
    1237   [ -  +  #  # ]:        968 :         if (rr->wire_format && rr->wire_format_canonical == canonical)
    1238                 :          0 :                 return 0;
    1239                 :            : 
    1240                 :        968 :         r = dns_packet_append_rr(&packet, rr, 0, &start, &rds);
    1241         [ -  + ]:        968 :         if (r < 0)
    1242                 :          0 :                 return r;
    1243                 :            : 
    1244         [ -  + ]:        968 :         assert(start == 0);
    1245         [ -  + ]:        968 :         assert(packet._data);
    1246                 :            : 
    1247                 :        968 :         free(rr->wire_format);
    1248                 :        968 :         rr->wire_format = packet._data;
    1249                 :        968 :         rr->wire_format_size = packet.size;
    1250                 :        968 :         rr->wire_format_rdata_offset = rds;
    1251                 :        968 :         rr->wire_format_canonical = canonical;
    1252                 :            : 
    1253                 :        968 :         packet._data = NULL;
    1254                 :        968 :         dns_packet_unref(&packet);
    1255                 :            : 
    1256                 :        968 :         return 0;
    1257                 :            : }
    1258                 :            : 
    1259                 :          0 : int dns_resource_record_signer(DnsResourceRecord *rr, const char **ret) {
    1260                 :            :         const char *n;
    1261                 :            :         int r;
    1262                 :            : 
    1263         [ #  # ]:          0 :         assert(rr);
    1264         [ #  # ]:          0 :         assert(ret);
    1265                 :            : 
    1266                 :            :         /* Returns the RRset's signer, if it is known. */
    1267                 :            : 
    1268         [ #  # ]:          0 :         if (rr->n_skip_labels_signer == (unsigned) -1)
    1269                 :          0 :                 return -ENODATA;
    1270                 :            : 
    1271                 :          0 :         n = dns_resource_key_name(rr->key);
    1272                 :          0 :         r = dns_name_skip(n, rr->n_skip_labels_signer, &n);
    1273         [ #  # ]:          0 :         if (r < 0)
    1274                 :          0 :                 return r;
    1275         [ #  # ]:          0 :         if (r == 0)
    1276                 :          0 :                 return -EINVAL;
    1277                 :            : 
    1278                 :          0 :         *ret = n;
    1279                 :          0 :         return 0;
    1280                 :            : }
    1281                 :            : 
    1282                 :          0 : int dns_resource_record_source(DnsResourceRecord *rr, const char **ret) {
    1283                 :            :         const char *n;
    1284                 :            :         int r;
    1285                 :            : 
    1286         [ #  # ]:          0 :         assert(rr);
    1287         [ #  # ]:          0 :         assert(ret);
    1288                 :            : 
    1289                 :            :         /* Returns the RRset's synthesizing source, if it is known. */
    1290                 :            : 
    1291         [ #  # ]:          0 :         if (rr->n_skip_labels_source == (unsigned) -1)
    1292                 :          0 :                 return -ENODATA;
    1293                 :            : 
    1294                 :          0 :         n = dns_resource_key_name(rr->key);
    1295                 :          0 :         r = dns_name_skip(n, rr->n_skip_labels_source, &n);
    1296         [ #  # ]:          0 :         if (r < 0)
    1297                 :          0 :                 return r;
    1298         [ #  # ]:          0 :         if (r == 0)
    1299                 :          0 :                 return -EINVAL;
    1300                 :            : 
    1301                 :          0 :         *ret = n;
    1302                 :          0 :         return 0;
    1303                 :            : }
    1304                 :            : 
    1305                 :          0 : int dns_resource_record_is_signer(DnsResourceRecord *rr, const char *zone) {
    1306                 :            :         const char *signer;
    1307                 :            :         int r;
    1308                 :            : 
    1309         [ #  # ]:          0 :         assert(rr);
    1310                 :            : 
    1311                 :          0 :         r = dns_resource_record_signer(rr, &signer);
    1312         [ #  # ]:          0 :         if (r < 0)
    1313                 :          0 :                 return r;
    1314                 :            : 
    1315                 :          0 :         return dns_name_equal(zone, signer);
    1316                 :            : }
    1317                 :            : 
    1318                 :          0 : int dns_resource_record_is_synthetic(DnsResourceRecord *rr) {
    1319                 :            :         int r;
    1320                 :            : 
    1321         [ #  # ]:          0 :         assert(rr);
    1322                 :            : 
    1323                 :            :         /* Returns > 0 if the RR is generated from a wildcard, and is not the asterisk name itself */
    1324                 :            : 
    1325         [ #  # ]:          0 :         if (rr->n_skip_labels_source == (unsigned) -1)
    1326                 :          0 :                 return -ENODATA;
    1327                 :            : 
    1328         [ #  # ]:          0 :         if (rr->n_skip_labels_source == 0)
    1329                 :          0 :                 return 0;
    1330                 :            : 
    1331         [ #  # ]:          0 :         if (rr->n_skip_labels_source > 1)
    1332                 :          0 :                 return 1;
    1333                 :            : 
    1334                 :          0 :         r = dns_name_startswith(dns_resource_key_name(rr->key), "*");
    1335         [ #  # ]:          0 :         if (r < 0)
    1336                 :          0 :                 return r;
    1337                 :            : 
    1338                 :          0 :         return !r;
    1339                 :            : }
    1340                 :            : 
    1341                 :       1904 : void dns_resource_record_hash_func(const DnsResourceRecord *rr, struct siphash *state) {
    1342         [ -  + ]:       1904 :         assert(rr);
    1343                 :            : 
    1344                 :       1904 :         dns_resource_key_hash_func(rr->key, state);
    1345                 :            : 
    1346   [ +  -  -  +  :       1904 :         switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
          -  +  +  +  +  
          +  +  +  +  -  
          +  -  -  +  +  
                      + ]
    1347                 :            : 
    1348                 :          0 :         case DNS_TYPE_SRV:
    1349                 :          0 :                 siphash24_compress(&rr->srv.priority, sizeof(rr->srv.priority), state);
    1350                 :          0 :                 siphash24_compress(&rr->srv.weight, sizeof(rr->srv.weight), state);
    1351                 :          0 :                 siphash24_compress(&rr->srv.port, sizeof(rr->srv.port), state);
    1352                 :          0 :                 dns_name_hash_func(rr->srv.name, state);
    1353                 :          0 :                 break;
    1354                 :            : 
    1355                 :        608 :         case DNS_TYPE_PTR:
    1356                 :            :         case DNS_TYPE_NS:
    1357                 :            :         case DNS_TYPE_CNAME:
    1358                 :            :         case DNS_TYPE_DNAME:
    1359                 :        608 :                 dns_name_hash_func(rr->ptr.name, state);
    1360                 :        608 :                 break;
    1361                 :            : 
    1362                 :          0 :         case DNS_TYPE_HINFO:
    1363                 :          0 :                 string_hash_func(rr->hinfo.cpu, state);
    1364                 :          0 :                 string_hash_func(rr->hinfo.os, state);
    1365                 :          0 :                 break;
    1366                 :            : 
    1367                 :        144 :         case DNS_TYPE_TXT:
    1368                 :            :         case DNS_TYPE_SPF: {
    1369                 :            :                 DnsTxtItem *j;
    1370                 :            : 
    1371         [ +  + ]:        288 :                 LIST_FOREACH(items, j, rr->txt.items) {
    1372                 :        144 :                         siphash24_compress(j->data, j->length, state);
    1373                 :            : 
    1374                 :            :                         /* Add an extra NUL byte, so that "a" followed by "b" doesn't result in the same hash as "ab"
    1375                 :            :                          * followed by "". */
    1376                 :        144 :                         siphash24_compress_byte(0, state);
    1377                 :            :                 }
    1378                 :        144 :                 break;
    1379                 :            :         }
    1380                 :            : 
    1381                 :        224 :         case DNS_TYPE_A:
    1382                 :        224 :                 siphash24_compress(&rr->a.in_addr, sizeof(rr->a.in_addr), state);
    1383                 :        224 :                 break;
    1384                 :            : 
    1385                 :        112 :         case DNS_TYPE_AAAA:
    1386                 :        112 :                 siphash24_compress(&rr->aaaa.in6_addr, sizeof(rr->aaaa.in6_addr), state);
    1387                 :        112 :                 break;
    1388                 :            : 
    1389                 :        112 :         case DNS_TYPE_SOA:
    1390                 :        112 :                 dns_name_hash_func(rr->soa.mname, state);
    1391                 :        112 :                 dns_name_hash_func(rr->soa.rname, state);
    1392                 :        112 :                 siphash24_compress(&rr->soa.serial, sizeof(rr->soa.serial), state);
    1393                 :        112 :                 siphash24_compress(&rr->soa.refresh, sizeof(rr->soa.refresh), state);
    1394                 :        112 :                 siphash24_compress(&rr->soa.retry, sizeof(rr->soa.retry), state);
    1395                 :        112 :                 siphash24_compress(&rr->soa.expire, sizeof(rr->soa.expire), state);
    1396                 :        112 :                 siphash24_compress(&rr->soa.minimum, sizeof(rr->soa.minimum), state);
    1397                 :        112 :                 break;
    1398                 :            : 
    1399                 :        224 :         case DNS_TYPE_MX:
    1400                 :        224 :                 siphash24_compress(&rr->mx.priority, sizeof(rr->mx.priority), state);
    1401                 :        224 :                 dns_name_hash_func(rr->mx.exchange, state);
    1402                 :        224 :                 break;
    1403                 :            : 
    1404                 :         48 :         case DNS_TYPE_LOC:
    1405                 :         48 :                 siphash24_compress(&rr->loc.version, sizeof(rr->loc.version), state);
    1406                 :         48 :                 siphash24_compress(&rr->loc.size, sizeof(rr->loc.size), state);
    1407                 :         48 :                 siphash24_compress(&rr->loc.horiz_pre, sizeof(rr->loc.horiz_pre), state);
    1408                 :         48 :                 siphash24_compress(&rr->loc.vert_pre, sizeof(rr->loc.vert_pre), state);
    1409                 :         48 :                 siphash24_compress(&rr->loc.latitude, sizeof(rr->loc.latitude), state);
    1410                 :         48 :                 siphash24_compress(&rr->loc.longitude, sizeof(rr->loc.longitude), state);
    1411                 :         48 :                 siphash24_compress(&rr->loc.altitude, sizeof(rr->loc.altitude), state);
    1412                 :         48 :                 break;
    1413                 :            : 
    1414                 :         96 :         case DNS_TYPE_SSHFP:
    1415                 :         96 :                 siphash24_compress(&rr->sshfp.algorithm, sizeof(rr->sshfp.algorithm), state);
    1416                 :         96 :                 siphash24_compress(&rr->sshfp.fptype, sizeof(rr->sshfp.fptype), state);
    1417                 :         96 :                 siphash24_compress(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size, state);
    1418                 :         96 :                 break;
    1419                 :            : 
    1420                 :        128 :         case DNS_TYPE_DNSKEY:
    1421                 :        128 :                 siphash24_compress(&rr->dnskey.flags, sizeof(rr->dnskey.flags), state);
    1422                 :        128 :                 siphash24_compress(&rr->dnskey.protocol, sizeof(rr->dnskey.protocol), state);
    1423                 :        128 :                 siphash24_compress(&rr->dnskey.algorithm, sizeof(rr->dnskey.algorithm), state);
    1424                 :        128 :                 siphash24_compress(rr->dnskey.key, rr->dnskey.key_size, state);
    1425                 :        128 :                 break;
    1426                 :            : 
    1427                 :          0 :         case DNS_TYPE_RRSIG:
    1428                 :          0 :                 siphash24_compress(&rr->rrsig.type_covered, sizeof(rr->rrsig.type_covered), state);
    1429                 :          0 :                 siphash24_compress(&rr->rrsig.algorithm, sizeof(rr->rrsig.algorithm), state);
    1430                 :          0 :                 siphash24_compress(&rr->rrsig.labels, sizeof(rr->rrsig.labels), state);
    1431                 :          0 :                 siphash24_compress(&rr->rrsig.original_ttl, sizeof(rr->rrsig.original_ttl), state);
    1432                 :          0 :                 siphash24_compress(&rr->rrsig.expiration, sizeof(rr->rrsig.expiration), state);
    1433                 :          0 :                 siphash24_compress(&rr->rrsig.inception, sizeof(rr->rrsig.inception), state);
    1434                 :          0 :                 siphash24_compress(&rr->rrsig.key_tag, sizeof(rr->rrsig.key_tag), state);
    1435                 :          0 :                 dns_name_hash_func(rr->rrsig.signer, state);
    1436                 :          0 :                 siphash24_compress(rr->rrsig.signature, rr->rrsig.signature_size, state);
    1437                 :          0 :                 break;
    1438                 :            : 
    1439                 :         96 :         case DNS_TYPE_NSEC:
    1440                 :         96 :                 dns_name_hash_func(rr->nsec.next_domain_name, state);
    1441                 :            :                 /* FIXME: we leave out the type bitmap here. Hash
    1442                 :            :                  * would be better if we'd take it into account
    1443                 :            :                  * too. */
    1444                 :         96 :                 break;
    1445                 :            : 
    1446                 :          0 :         case DNS_TYPE_DS:
    1447                 :          0 :                 siphash24_compress(&rr->ds.key_tag, sizeof(rr->ds.key_tag), state);
    1448                 :          0 :                 siphash24_compress(&rr->ds.algorithm, sizeof(rr->ds.algorithm), state);
    1449                 :          0 :                 siphash24_compress(&rr->ds.digest_type, sizeof(rr->ds.digest_type), state);
    1450                 :          0 :                 siphash24_compress(rr->ds.digest, rr->ds.digest_size, state);
    1451                 :          0 :                 break;
    1452                 :            : 
    1453                 :          0 :         case DNS_TYPE_NSEC3:
    1454                 :          0 :                 siphash24_compress(&rr->nsec3.algorithm, sizeof(rr->nsec3.algorithm), state);
    1455                 :          0 :                 siphash24_compress(&rr->nsec3.flags, sizeof(rr->nsec3.flags), state);
    1456                 :          0 :                 siphash24_compress(&rr->nsec3.iterations, sizeof(rr->nsec3.iterations), state);
    1457                 :          0 :                 siphash24_compress(rr->nsec3.salt, rr->nsec3.salt_size, state);
    1458                 :          0 :                 siphash24_compress(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, state);
    1459                 :            :                 /* FIXME: We leave the bitmaps out */
    1460                 :          0 :                 break;
    1461                 :            : 
    1462                 :         16 :         case DNS_TYPE_TLSA:
    1463                 :         16 :                 siphash24_compress(&rr->tlsa.cert_usage, sizeof(rr->tlsa.cert_usage), state);
    1464                 :         16 :                 siphash24_compress(&rr->tlsa.selector, sizeof(rr->tlsa.selector), state);
    1465                 :         16 :                 siphash24_compress(&rr->tlsa.matching_type, sizeof(rr->tlsa.matching_type), state);
    1466                 :         16 :                 siphash24_compress(rr->tlsa.data, rr->tlsa.data_size, state);
    1467                 :         16 :                 break;
    1468                 :            : 
    1469                 :         80 :         case DNS_TYPE_CAA:
    1470                 :         80 :                 siphash24_compress(&rr->caa.flags, sizeof(rr->caa.flags), state);
    1471                 :         80 :                 string_hash_func(rr->caa.tag, state);
    1472                 :         80 :                 siphash24_compress(rr->caa.value, rr->caa.value_size, state);
    1473                 :         80 :                 break;
    1474                 :            : 
    1475                 :         16 :         case DNS_TYPE_OPENPGPKEY:
    1476                 :            :         default:
    1477                 :         16 :                 siphash24_compress(rr->generic.data, rr->generic.data_size, state);
    1478                 :         16 :                 break;
    1479                 :            :         }
    1480                 :       1904 : }
    1481                 :            : 
    1482                 :          0 : static int dns_resource_record_compare_func(const DnsResourceRecord *x, const DnsResourceRecord *y) {
    1483                 :            :         int r;
    1484                 :            : 
    1485                 :          0 :         r = dns_resource_key_compare_func(x->key, y->key);
    1486         [ #  # ]:          0 :         if (r != 0)
    1487                 :          0 :                 return r;
    1488                 :            : 
    1489         [ #  # ]:          0 :         if (dns_resource_record_equal(x, y))
    1490                 :          0 :                 return 0;
    1491                 :            : 
    1492                 :            :         /* We still use CMP() here, even though don't implement proper
    1493                 :            :          * ordering, since the hashtable doesn't need ordering anyway. */
    1494         [ #  # ]:          0 :         return CMP(x, y);
    1495                 :            : }
    1496                 :            : 
    1497                 :            : DEFINE_HASH_OPS(dns_resource_record_hash_ops, DnsResourceRecord, dns_resource_record_hash_func, dns_resource_record_compare_func);
    1498                 :            : 
    1499                 :       1904 : DnsResourceRecord *dns_resource_record_copy(DnsResourceRecord *rr) {
    1500                 :       1904 :         _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *copy = NULL;
    1501                 :            :         DnsResourceRecord *t;
    1502                 :            : 
    1503         [ -  + ]:       1904 :         assert(rr);
    1504                 :            : 
    1505                 :       1904 :         copy = dns_resource_record_new(rr->key);
    1506         [ -  + ]:       1904 :         if (!copy)
    1507                 :          0 :                 return NULL;
    1508                 :            : 
    1509                 :       1904 :         copy->ttl = rr->ttl;
    1510                 :       1904 :         copy->expiry = rr->expiry;
    1511                 :       1904 :         copy->n_skip_labels_signer = rr->n_skip_labels_signer;
    1512                 :       1904 :         copy->n_skip_labels_source = rr->n_skip_labels_source;
    1513                 :       1904 :         copy->unparseable = rr->unparseable;
    1514                 :            : 
    1515   [ +  -  -  +  :       1904 :         switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
          -  +  +  +  +  
          +  +  +  +  -  
          +  -  -  +  +  
                      + ]
    1516                 :            : 
    1517                 :          0 :         case DNS_TYPE_SRV:
    1518                 :          0 :                 copy->srv.priority = rr->srv.priority;
    1519                 :          0 :                 copy->srv.weight = rr->srv.weight;
    1520                 :          0 :                 copy->srv.port = rr->srv.port;
    1521                 :          0 :                 copy->srv.name = strdup(rr->srv.name);
    1522         [ #  # ]:          0 :                 if (!copy->srv.name)
    1523                 :          0 :                         return NULL;
    1524                 :          0 :                 break;
    1525                 :            : 
    1526                 :        608 :         case DNS_TYPE_PTR:
    1527                 :            :         case DNS_TYPE_NS:
    1528                 :            :         case DNS_TYPE_CNAME:
    1529                 :            :         case DNS_TYPE_DNAME:
    1530                 :        608 :                 copy->ptr.name = strdup(rr->ptr.name);
    1531         [ -  + ]:        608 :                 if (!copy->ptr.name)
    1532                 :          0 :                         return NULL;
    1533                 :        608 :                 break;
    1534                 :            : 
    1535                 :          0 :         case DNS_TYPE_HINFO:
    1536                 :          0 :                 copy->hinfo.cpu = strdup(rr->hinfo.cpu);
    1537         [ #  # ]:          0 :                 if (!copy->hinfo.cpu)
    1538                 :          0 :                         return NULL;
    1539                 :            : 
    1540                 :          0 :                 copy->hinfo.os = strdup(rr->hinfo.os);
    1541         [ #  # ]:          0 :                 if (!copy->hinfo.os)
    1542                 :          0 :                         return NULL;
    1543                 :          0 :                 break;
    1544                 :            : 
    1545                 :        144 :         case DNS_TYPE_TXT:
    1546                 :            :         case DNS_TYPE_SPF:
    1547                 :        144 :                 copy->txt.items = dns_txt_item_copy(rr->txt.items);
    1548         [ -  + ]:        144 :                 if (!copy->txt.items)
    1549                 :          0 :                         return NULL;
    1550                 :        144 :                 break;
    1551                 :            : 
    1552                 :        224 :         case DNS_TYPE_A:
    1553                 :        224 :                 copy->a = rr->a;
    1554                 :        224 :                 break;
    1555                 :            : 
    1556                 :        112 :         case DNS_TYPE_AAAA:
    1557                 :        112 :                 copy->aaaa = rr->aaaa;
    1558                 :        112 :                 break;
    1559                 :            : 
    1560                 :        112 :         case DNS_TYPE_SOA:
    1561                 :        112 :                 copy->soa.mname = strdup(rr->soa.mname);
    1562         [ -  + ]:        112 :                 if (!copy->soa.mname)
    1563                 :          0 :                         return NULL;
    1564                 :        112 :                 copy->soa.rname = strdup(rr->soa.rname);
    1565         [ -  + ]:        112 :                 if (!copy->soa.rname)
    1566                 :          0 :                         return NULL;
    1567                 :        112 :                 copy->soa.serial = rr->soa.serial;
    1568                 :        112 :                 copy->soa.refresh = rr->soa.refresh;
    1569                 :        112 :                 copy->soa.retry = rr->soa.retry;
    1570                 :        112 :                 copy->soa.expire = rr->soa.expire;
    1571                 :        112 :                 copy->soa.minimum = rr->soa.minimum;
    1572                 :        112 :                 break;
    1573                 :            : 
    1574                 :        224 :         case DNS_TYPE_MX:
    1575                 :        224 :                 copy->mx.priority = rr->mx.priority;
    1576                 :        224 :                 copy->mx.exchange = strdup(rr->mx.exchange);
    1577         [ -  + ]:        224 :                 if (!copy->mx.exchange)
    1578                 :          0 :                         return NULL;
    1579                 :        224 :                 break;
    1580                 :            : 
    1581                 :         48 :         case DNS_TYPE_LOC:
    1582                 :         48 :                 copy->loc = rr->loc;
    1583                 :         48 :                 break;
    1584                 :            : 
    1585                 :         96 :         case DNS_TYPE_SSHFP:
    1586                 :         96 :                 copy->sshfp.algorithm = rr->sshfp.algorithm;
    1587                 :         96 :                 copy->sshfp.fptype = rr->sshfp.fptype;
    1588                 :         96 :                 copy->sshfp.fingerprint = memdup(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size);
    1589         [ -  + ]:         96 :                 if (!copy->sshfp.fingerprint)
    1590                 :          0 :                         return NULL;
    1591                 :         96 :                 copy->sshfp.fingerprint_size = rr->sshfp.fingerprint_size;
    1592                 :         96 :                 break;
    1593                 :            : 
    1594                 :        128 :         case DNS_TYPE_DNSKEY:
    1595                 :        128 :                 copy->dnskey.flags = rr->dnskey.flags;
    1596                 :        128 :                 copy->dnskey.protocol = rr->dnskey.protocol;
    1597                 :        128 :                 copy->dnskey.algorithm = rr->dnskey.algorithm;
    1598                 :        128 :                 copy->dnskey.key = memdup(rr->dnskey.key, rr->dnskey.key_size);
    1599         [ -  + ]:        128 :                 if (!copy->dnskey.key)
    1600                 :          0 :                         return NULL;
    1601                 :        128 :                 copy->dnskey.key_size = rr->dnskey.key_size;
    1602                 :        128 :                 break;
    1603                 :            : 
    1604                 :          0 :         case DNS_TYPE_RRSIG:
    1605                 :          0 :                 copy->rrsig.type_covered = rr->rrsig.type_covered;
    1606                 :          0 :                 copy->rrsig.algorithm = rr->rrsig.algorithm;
    1607                 :          0 :                 copy->rrsig.labels = rr->rrsig.labels;
    1608                 :          0 :                 copy->rrsig.original_ttl = rr->rrsig.original_ttl;
    1609                 :          0 :                 copy->rrsig.expiration = rr->rrsig.expiration;
    1610                 :          0 :                 copy->rrsig.inception = rr->rrsig.inception;
    1611                 :          0 :                 copy->rrsig.key_tag = rr->rrsig.key_tag;
    1612                 :          0 :                 copy->rrsig.signer = strdup(rr->rrsig.signer);
    1613         [ #  # ]:          0 :                 if (!copy->rrsig.signer)
    1614                 :          0 :                         return NULL;
    1615                 :          0 :                 copy->rrsig.signature = memdup(rr->rrsig.signature, rr->rrsig.signature_size);
    1616         [ #  # ]:          0 :                 if (!copy->rrsig.signature)
    1617                 :          0 :                         return NULL;
    1618                 :          0 :                 copy->rrsig.signature_size = rr->rrsig.signature_size;
    1619                 :          0 :                 break;
    1620                 :            : 
    1621                 :         96 :         case DNS_TYPE_NSEC:
    1622                 :         96 :                 copy->nsec.next_domain_name = strdup(rr->nsec.next_domain_name);
    1623         [ -  + ]:         96 :                 if (!copy->nsec.next_domain_name)
    1624                 :          0 :                         return NULL;
    1625                 :         96 :                 copy->nsec.types = bitmap_copy(rr->nsec.types);
    1626         [ -  + ]:         96 :                 if (!copy->nsec.types)
    1627                 :          0 :                         return NULL;
    1628                 :         96 :                 break;
    1629                 :            : 
    1630                 :          0 :         case DNS_TYPE_DS:
    1631                 :          0 :                 copy->ds.key_tag = rr->ds.key_tag;
    1632                 :          0 :                 copy->ds.algorithm = rr->ds.algorithm;
    1633                 :          0 :                 copy->ds.digest_type = rr->ds.digest_type;
    1634                 :          0 :                 copy->ds.digest = memdup(rr->ds.digest, rr->ds.digest_size);
    1635         [ #  # ]:          0 :                 if (!copy->ds.digest)
    1636                 :          0 :                         return NULL;
    1637                 :          0 :                 copy->ds.digest_size = rr->ds.digest_size;
    1638                 :          0 :                 break;
    1639                 :            : 
    1640                 :          0 :         case DNS_TYPE_NSEC3:
    1641                 :          0 :                 copy->nsec3.algorithm = rr->nsec3.algorithm;
    1642                 :          0 :                 copy->nsec3.flags = rr->nsec3.flags;
    1643                 :          0 :                 copy->nsec3.iterations = rr->nsec3.iterations;
    1644                 :          0 :                 copy->nsec3.salt = memdup(rr->nsec3.salt, rr->nsec3.salt_size);
    1645         [ #  # ]:          0 :                 if (!copy->nsec3.salt)
    1646                 :          0 :                         return NULL;
    1647                 :          0 :                 copy->nsec3.salt_size = rr->nsec3.salt_size;
    1648                 :          0 :                 copy->nsec3.next_hashed_name = memdup(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size);
    1649         [ #  # ]:          0 :                 if (!copy->nsec3.next_hashed_name_size)
    1650                 :          0 :                         return NULL;
    1651                 :          0 :                 copy->nsec3.next_hashed_name_size = rr->nsec3.next_hashed_name_size;
    1652                 :          0 :                 copy->nsec3.types = bitmap_copy(rr->nsec3.types);
    1653         [ #  # ]:          0 :                 if (!copy->nsec3.types)
    1654                 :          0 :                         return NULL;
    1655                 :          0 :                 break;
    1656                 :            : 
    1657                 :         16 :         case DNS_TYPE_TLSA:
    1658                 :         16 :                 copy->tlsa.cert_usage = rr->tlsa.cert_usage;
    1659                 :         16 :                 copy->tlsa.selector = rr->tlsa.selector;
    1660                 :         16 :                 copy->tlsa.matching_type = rr->tlsa.matching_type;
    1661                 :         16 :                 copy->tlsa.data = memdup(rr->tlsa.data, rr->tlsa.data_size);
    1662         [ -  + ]:         16 :                 if (!copy->tlsa.data)
    1663                 :          0 :                         return NULL;
    1664                 :         16 :                 copy->tlsa.data_size = rr->tlsa.data_size;
    1665                 :         16 :                 break;
    1666                 :            : 
    1667                 :         80 :         case DNS_TYPE_CAA:
    1668                 :         80 :                 copy->caa.flags = rr->caa.flags;
    1669                 :         80 :                 copy->caa.tag = strdup(rr->caa.tag);
    1670         [ -  + ]:         80 :                 if (!copy->caa.tag)
    1671                 :          0 :                         return NULL;
    1672                 :         80 :                 copy->caa.value = memdup(rr->caa.value, rr->caa.value_size);
    1673         [ -  + ]:         80 :                 if (!copy->caa.value)
    1674                 :          0 :                         return NULL;
    1675                 :         80 :                 copy->caa.value_size = rr->caa.value_size;
    1676                 :         80 :                 break;
    1677                 :            : 
    1678                 :         16 :         case DNS_TYPE_OPT:
    1679                 :            :         default:
    1680                 :         16 :                 copy->generic.data = memdup(rr->generic.data, rr->generic.data_size);
    1681         [ -  + ]:         16 :                 if (!copy->generic.data)
    1682                 :          0 :                         return NULL;
    1683                 :         16 :                 copy->generic.data_size = rr->generic.data_size;
    1684                 :         16 :                 break;
    1685                 :            :         }
    1686                 :            : 
    1687                 :       1904 :         t = TAKE_PTR(copy);
    1688                 :            : 
    1689                 :       1904 :         return t;
    1690                 :            : }
    1691                 :            : 
    1692                 :          0 : int dns_resource_record_clamp_ttl(DnsResourceRecord **rr, uint32_t max_ttl) {
    1693                 :            :         DnsResourceRecord *old_rr, *new_rr;
    1694                 :            :         uint32_t new_ttl;
    1695                 :            : 
    1696         [ #  # ]:          0 :         assert(rr);
    1697                 :          0 :         old_rr = *rr;
    1698                 :            : 
    1699         [ #  # ]:          0 :         if (old_rr->key->type == DNS_TYPE_OPT)
    1700                 :          0 :                 return -EINVAL;
    1701                 :            : 
    1702                 :          0 :         new_ttl = MIN(old_rr->ttl, max_ttl);
    1703         [ #  # ]:          0 :         if (new_ttl == old_rr->ttl)
    1704                 :          0 :                 return 0;
    1705                 :            : 
    1706         [ #  # ]:          0 :         if (old_rr->n_ref == 1) {
    1707                 :            :                 /* Patch in place */
    1708                 :          0 :                 old_rr->ttl = new_ttl;
    1709                 :          0 :                 return 1;
    1710                 :            :         }
    1711                 :            : 
    1712                 :          0 :         new_rr = dns_resource_record_copy(old_rr);
    1713         [ #  # ]:          0 :         if (!new_rr)
    1714                 :          0 :                 return -ENOMEM;
    1715                 :            : 
    1716                 :          0 :         new_rr->ttl = new_ttl;
    1717                 :            : 
    1718                 :          0 :         dns_resource_record_unref(*rr);
    1719                 :          0 :         *rr = new_rr;
    1720                 :            : 
    1721                 :          0 :         return 1;
    1722                 :            : }
    1723                 :            : 
    1724                 :        576 : DnsTxtItem *dns_txt_item_free_all(DnsTxtItem *i) {
    1725                 :            :         DnsTxtItem *n;
    1726                 :            : 
    1727         [ +  + ]:        576 :         if (!i)
    1728                 :        288 :                 return NULL;
    1729                 :            : 
    1730                 :        288 :         n = i->items_next;
    1731                 :            : 
    1732                 :        288 :         free(i);
    1733                 :        288 :         return dns_txt_item_free_all(n);
    1734                 :            : }
    1735                 :            : 
    1736                 :        288 : bool dns_txt_item_equal(DnsTxtItem *a, DnsTxtItem *b) {
    1737                 :            : 
    1738         [ +  + ]:        288 :         if (a == b)
    1739                 :        144 :                 return true;
    1740                 :            : 
    1741         [ -  + ]:        144 :         if (!a != !b)
    1742                 :          0 :                 return false;
    1743                 :            : 
    1744         [ -  + ]:        144 :         if (!a)
    1745                 :          0 :                 return true;
    1746                 :            : 
    1747         [ -  + ]:        144 :         if (a->length != b->length)
    1748                 :          0 :                 return false;
    1749                 :            : 
    1750         [ -  + ]:        144 :         if (memcmp(a->data, b->data, a->length) != 0)
    1751                 :          0 :                 return false;
    1752                 :            : 
    1753                 :        144 :         return dns_txt_item_equal(a->items_next, b->items_next);
    1754                 :            : }
    1755                 :            : 
    1756                 :        144 : DnsTxtItem *dns_txt_item_copy(DnsTxtItem *first) {
    1757                 :        144 :         DnsTxtItem *i, *copy = NULL, *end = NULL;
    1758                 :            : 
    1759         [ +  + ]:        288 :         LIST_FOREACH(items, i, first) {
    1760                 :            :                 DnsTxtItem *j;
    1761                 :            : 
    1762                 :        144 :                 j = memdup(i, offsetof(DnsTxtItem, data) + i->length + 1);
    1763         [ -  + ]:        144 :                 if (!j) {
    1764                 :          0 :                         dns_txt_item_free_all(copy);
    1765                 :          0 :                         return NULL;
    1766                 :            :                 }
    1767                 :            : 
    1768   [ -  +  +  -  :        144 :                 LIST_INSERT_AFTER(items, copy, end, j);
             -  +  #  # ]
    1769                 :        144 :                 end = j;
    1770                 :            :         }
    1771                 :            : 
    1772                 :        144 :         return copy;
    1773                 :            : }
    1774                 :            : 
    1775                 :          0 : int dns_txt_item_new_empty(DnsTxtItem **ret) {
    1776                 :            :         DnsTxtItem *i;
    1777                 :            : 
    1778                 :            :         /* RFC 6763, section 6.1 suggests to treat
    1779                 :            :          * empty TXT RRs as equivalent to a TXT record
    1780                 :            :          * with a single empty string. */
    1781                 :            : 
    1782                 :          0 :         i = malloc0(offsetof(DnsTxtItem, data) + 1); /* for safety reasons we add an extra NUL byte */
    1783         [ #  # ]:          0 :         if (!i)
    1784                 :          0 :                 return -ENOMEM;
    1785                 :            : 
    1786                 :          0 :         *ret = i;
    1787                 :            : 
    1788                 :          0 :         return 0;
    1789                 :            : }
    1790                 :            : 
    1791                 :            : static const char* const dnssec_algorithm_table[_DNSSEC_ALGORITHM_MAX_DEFINED] = {
    1792                 :            :         /* Mnemonics as listed on https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
    1793                 :            :         [DNSSEC_ALGORITHM_RSAMD5]             = "RSAMD5",
    1794                 :            :         [DNSSEC_ALGORITHM_DH]                 = "DH",
    1795                 :            :         [DNSSEC_ALGORITHM_DSA]                = "DSA",
    1796                 :            :         [DNSSEC_ALGORITHM_ECC]                = "ECC",
    1797                 :            :         [DNSSEC_ALGORITHM_RSASHA1]            = "RSASHA1",
    1798                 :            :         [DNSSEC_ALGORITHM_DSA_NSEC3_SHA1]     = "DSA-NSEC3-SHA1",
    1799                 :            :         [DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1] = "RSASHA1-NSEC3-SHA1",
    1800                 :            :         [DNSSEC_ALGORITHM_RSASHA256]          = "RSASHA256",
    1801                 :            :         [DNSSEC_ALGORITHM_RSASHA512]          = "RSASHA512",
    1802                 :            :         [DNSSEC_ALGORITHM_ECC_GOST]           = "ECC-GOST",
    1803                 :            :         [DNSSEC_ALGORITHM_ECDSAP256SHA256]    = "ECDSAP256SHA256",
    1804                 :            :         [DNSSEC_ALGORITHM_ECDSAP384SHA384]    = "ECDSAP384SHA384",
    1805                 :            :         [DNSSEC_ALGORITHM_ED25519]            = "ED25519",
    1806                 :            :         [DNSSEC_ALGORITHM_ED448]              = "ED448",
    1807                 :            :         [DNSSEC_ALGORITHM_INDIRECT]           = "INDIRECT",
    1808                 :            :         [DNSSEC_ALGORITHM_PRIVATEDNS]         = "PRIVATEDNS",
    1809                 :            :         [DNSSEC_ALGORITHM_PRIVATEOID]         = "PRIVATEOID",
    1810                 :            : };
    1811   [ +  -  -  +  :        228 : DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_algorithm, int, 255);
          +  -  -  +  #  
                      # ]
    1812                 :            : 
    1813                 :            : static const char* const dnssec_digest_table[_DNSSEC_DIGEST_MAX_DEFINED] = {
    1814                 :            :         /* Names as listed on https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
    1815                 :            :         [DNSSEC_DIGEST_SHA1] = "SHA-1",
    1816                 :            :         [DNSSEC_DIGEST_SHA256] = "SHA-256",
    1817                 :            :         [DNSSEC_DIGEST_GOST_R_34_11_94] = "GOST_R_34.11-94",
    1818                 :            :         [DNSSEC_DIGEST_SHA384] = "SHA-384",
    1819                 :            : };
    1820   [ #  #  #  #  :          0 : DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_digest, int, 255);
          #  #  #  #  #  
                      # ]

Generated by: LCOV version 1.14