LCOV - code coverage report
Current view: top level - resolve - resolved-dns-scope.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 0 767 0.0 %
Date: 2019-08-23 13:36:53 Functions: 0 38 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 757 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <netinet/tcp.h>
       4                 :            : 
       5                 :            : #include "af-list.h"
       6                 :            : #include "alloc-util.h"
       7                 :            : #include "dns-domain.h"
       8                 :            : #include "fd-util.h"
       9                 :            : #include "hostname-util.h"
      10                 :            : #include "missing.h"
      11                 :            : #include "random-util.h"
      12                 :            : #include "resolved-dnssd.h"
      13                 :            : #include "resolved-dns-scope.h"
      14                 :            : #include "resolved-dns-zone.h"
      15                 :            : #include "resolved-llmnr.h"
      16                 :            : #include "resolved-mdns.h"
      17                 :            : #include "socket-util.h"
      18                 :            : #include "strv.h"
      19                 :            : 
      20                 :            : #define MULTICAST_RATELIMIT_INTERVAL_USEC (1*USEC_PER_SEC)
      21                 :            : #define MULTICAST_RATELIMIT_BURST 1000
      22                 :            : 
      23                 :            : /* After how much time to repeat LLMNR requests, see RFC 4795 Section 7 */
      24                 :            : #define MULTICAST_RESEND_TIMEOUT_MIN_USEC (100 * USEC_PER_MSEC)
      25                 :            : #define MULTICAST_RESEND_TIMEOUT_MAX_USEC (1 * USEC_PER_SEC)
      26                 :            : 
      27                 :          0 : int dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol protocol, int family) {
      28                 :            :         DnsScope *s;
      29                 :            : 
      30         [ #  # ]:          0 :         assert(m);
      31         [ #  # ]:          0 :         assert(ret);
      32                 :            : 
      33                 :          0 :         s = new(DnsScope, 1);
      34         [ #  # ]:          0 :         if (!s)
      35                 :          0 :                 return -ENOMEM;
      36                 :            : 
      37                 :          0 :         *s = (DnsScope) {
      38                 :            :                 .manager = m,
      39                 :            :                 .link = l,
      40                 :            :                 .protocol = protocol,
      41                 :            :                 .family = family,
      42                 :            :                 .resend_timeout = MULTICAST_RESEND_TIMEOUT_MIN_USEC,
      43                 :            :         };
      44                 :            : 
      45         [ #  # ]:          0 :         if (protocol == DNS_PROTOCOL_DNS) {
      46                 :            :                 /* Copy DNSSEC mode from the link if it is set there,
      47                 :            :                  * otherwise take the manager's DNSSEC mode. Note that
      48                 :            :                  * we copy this only at scope creation time, and do
      49                 :            :                  * not update it from the on, even if the setting
      50                 :            :                  * changes. */
      51                 :            : 
      52         [ #  # ]:          0 :                 if (l) {
      53                 :          0 :                         s->dnssec_mode = link_get_dnssec_mode(l);
      54                 :          0 :                         s->dns_over_tls_mode = link_get_dns_over_tls_mode(l);
      55                 :            :                 } else {
      56                 :          0 :                         s->dnssec_mode = manager_get_dnssec_mode(m);
      57                 :          0 :                         s->dns_over_tls_mode = manager_get_dns_over_tls_mode(m);
      58                 :            :                 }
      59                 :            : 
      60                 :            :         } else {
      61                 :          0 :                 s->dnssec_mode = DNSSEC_NO;
      62                 :          0 :                 s->dns_over_tls_mode = DNS_OVER_TLS_NO;
      63                 :            :         }
      64                 :            : 
      65   [ #  #  #  # ]:          0 :         LIST_PREPEND(scopes, m->dns_scopes, s);
      66                 :            : 
      67                 :          0 :         dns_scope_llmnr_membership(s, true);
      68                 :          0 :         dns_scope_mdns_membership(s, true);
      69                 :            : 
      70   [ #  #  #  #  :          0 :         log_debug("New scope on link %s, protocol %s, family %s", l ? l->ifname : "*", dns_protocol_to_string(protocol), family == AF_UNSPEC ? "*" : af_to_name(family));
                   #  # ]
      71                 :            : 
      72                 :            :         /* Enforce ratelimiting for the multicast protocols */
      73                 :          0 :         RATELIMIT_INIT(s->ratelimit, MULTICAST_RATELIMIT_INTERVAL_USEC, MULTICAST_RATELIMIT_BURST);
      74                 :            : 
      75                 :          0 :         *ret = s;
      76                 :          0 :         return 0;
      77                 :            : }
      78                 :            : 
      79                 :          0 : static void dns_scope_abort_transactions(DnsScope *s) {
      80         [ #  # ]:          0 :         assert(s);
      81                 :            : 
      82         [ #  # ]:          0 :         while (s->transactions) {
      83                 :          0 :                 DnsTransaction *t = s->transactions;
      84                 :            : 
      85                 :            :                 /* Abort the transaction, but make sure it is not
      86                 :            :                  * freed while we still look at it */
      87                 :            : 
      88                 :          0 :                 t->block_gc++;
      89   [ #  #  #  # ]:          0 :                 if (DNS_TRANSACTION_IS_LIVE(t->state))
      90                 :          0 :                         dns_transaction_complete(t, DNS_TRANSACTION_ABORTED);
      91                 :          0 :                 t->block_gc--;
      92                 :            : 
      93                 :          0 :                 dns_transaction_free(t);
      94                 :            :         }
      95                 :          0 : }
      96                 :            : 
      97                 :          0 : DnsScope* dns_scope_free(DnsScope *s) {
      98         [ #  # ]:          0 :         if (!s)
      99                 :          0 :                 return NULL;
     100                 :            : 
     101   [ #  #  #  #  :          0 :         log_debug("Removing scope on link %s, protocol %s, family %s", s->link ? s->link->ifname : "*", dns_protocol_to_string(s->protocol), s->family == AF_UNSPEC ? "*" : af_to_name(s->family));
                   #  # ]
     102                 :            : 
     103                 :          0 :         dns_scope_llmnr_membership(s, false);
     104                 :          0 :         dns_scope_mdns_membership(s, false);
     105                 :          0 :         dns_scope_abort_transactions(s);
     106                 :            : 
     107         [ #  # ]:          0 :         while (s->query_candidates)
     108                 :          0 :                 dns_query_candidate_free(s->query_candidates);
     109                 :            : 
     110                 :          0 :         hashmap_free(s->transactions_by_key);
     111                 :            : 
     112         [ #  # ]:          0 :         ordered_hashmap_free_with_destructor(s->conflict_queue, dns_resource_record_unref);
     113                 :          0 :         sd_event_source_unref(s->conflict_event_source);
     114                 :            : 
     115                 :          0 :         sd_event_source_unref(s->announce_event_source);
     116                 :            : 
     117                 :          0 :         dns_cache_flush(&s->cache);
     118                 :          0 :         dns_zone_flush(&s->zone);
     119                 :            : 
     120   [ #  #  #  #  :          0 :         LIST_REMOVE(scopes, s->manager->dns_scopes, s);
             #  #  #  # ]
     121                 :          0 :         return mfree(s);
     122                 :            : }
     123                 :            : 
     124                 :          0 : DnsServer *dns_scope_get_dns_server(DnsScope *s) {
     125         [ #  # ]:          0 :         assert(s);
     126                 :            : 
     127         [ #  # ]:          0 :         if (s->protocol != DNS_PROTOCOL_DNS)
     128                 :          0 :                 return NULL;
     129                 :            : 
     130         [ #  # ]:          0 :         if (s->link)
     131                 :          0 :                 return link_get_dns_server(s->link);
     132                 :            :         else
     133                 :          0 :                 return manager_get_dns_server(s->manager);
     134                 :            : }
     135                 :            : 
     136                 :          0 : unsigned dns_scope_get_n_dns_servers(DnsScope *s) {
     137                 :          0 :         unsigned n = 0;
     138                 :            :         DnsServer *i;
     139                 :            : 
     140         [ #  # ]:          0 :         assert(s);
     141                 :            : 
     142         [ #  # ]:          0 :         if (s->protocol != DNS_PROTOCOL_DNS)
     143                 :          0 :                 return 0;
     144                 :            : 
     145         [ #  # ]:          0 :         if (s->link)
     146                 :          0 :                 i = s->link->dns_servers;
     147                 :            :         else
     148                 :          0 :                 i = s->manager->dns_servers;
     149                 :            : 
     150         [ #  # ]:          0 :         for (; i; i = i->servers_next)
     151                 :          0 :                 n++;
     152                 :            : 
     153                 :          0 :         return n;
     154                 :            : }
     155                 :            : 
     156                 :          0 : void dns_scope_next_dns_server(DnsScope *s) {
     157         [ #  # ]:          0 :         assert(s);
     158                 :            : 
     159         [ #  # ]:          0 :         if (s->protocol != DNS_PROTOCOL_DNS)
     160                 :          0 :                 return;
     161                 :            : 
     162         [ #  # ]:          0 :         if (s->link)
     163                 :          0 :                 link_next_dns_server(s->link);
     164                 :            :         else
     165                 :          0 :                 manager_next_dns_server(s->manager);
     166                 :            : }
     167                 :            : 
     168                 :          0 : void dns_scope_packet_received(DnsScope *s, usec_t rtt) {
     169         [ #  # ]:          0 :         assert(s);
     170                 :            : 
     171         [ #  # ]:          0 :         if (rtt <= s->max_rtt)
     172                 :          0 :                 return;
     173                 :            : 
     174                 :          0 :         s->max_rtt = rtt;
     175                 :          0 :         s->resend_timeout = MIN(MAX(MULTICAST_RESEND_TIMEOUT_MIN_USEC, s->max_rtt * 2), MULTICAST_RESEND_TIMEOUT_MAX_USEC);
     176                 :            : }
     177                 :            : 
     178                 :          0 : void dns_scope_packet_lost(DnsScope *s, usec_t usec) {
     179         [ #  # ]:          0 :         assert(s);
     180                 :            : 
     181         [ #  # ]:          0 :         if (s->resend_timeout <= usec)
     182                 :          0 :                 s->resend_timeout = MIN(s->resend_timeout * 2, MULTICAST_RESEND_TIMEOUT_MAX_USEC);
     183                 :          0 : }
     184                 :            : 
     185                 :          0 : static int dns_scope_emit_one(DnsScope *s, int fd, DnsPacket *p) {
     186                 :            :         union in_addr_union addr;
     187                 :          0 :         int ifindex = 0, r;
     188                 :            :         int family;
     189                 :            :         uint32_t mtu;
     190                 :            : 
     191         [ #  # ]:          0 :         assert(s);
     192         [ #  # ]:          0 :         assert(p);
     193         [ #  # ]:          0 :         assert(p->protocol == s->protocol);
     194                 :            : 
     195         [ #  # ]:          0 :         if (s->link) {
     196                 :          0 :                 mtu = s->link->mtu;
     197                 :          0 :                 ifindex = s->link->ifindex;
     198                 :            :         } else
     199                 :          0 :                 mtu = manager_find_mtu(s->manager);
     200                 :            : 
     201   [ #  #  #  # ]:          0 :         switch (s->protocol) {
     202                 :            : 
     203                 :          0 :         case DNS_PROTOCOL_DNS:
     204         [ #  # ]:          0 :                 assert(fd >= 0);
     205                 :            : 
     206         [ #  # ]:          0 :                 if (DNS_PACKET_QDCOUNT(p) > 1)
     207                 :          0 :                         return -EOPNOTSUPP;
     208                 :            : 
     209         [ #  # ]:          0 :                 if (p->size > DNS_PACKET_UNICAST_SIZE_MAX)
     210                 :          0 :                         return -EMSGSIZE;
     211                 :            : 
     212         [ #  # ]:          0 :                 if (p->size + UDP_PACKET_HEADER_SIZE > mtu)
     213                 :          0 :                         return -EMSGSIZE;
     214                 :            : 
     215                 :          0 :                 r = manager_write(s->manager, fd, p);
     216         [ #  # ]:          0 :                 if (r < 0)
     217                 :          0 :                         return r;
     218                 :            : 
     219                 :          0 :                 break;
     220                 :            : 
     221                 :          0 :         case DNS_PROTOCOL_LLMNR:
     222         [ #  # ]:          0 :                 assert(fd < 0);
     223                 :            : 
     224         [ #  # ]:          0 :                 if (DNS_PACKET_QDCOUNT(p) > 1)
     225                 :          0 :                         return -EOPNOTSUPP;
     226                 :            : 
     227         [ #  # ]:          0 :                 if (!ratelimit_below(&s->ratelimit))
     228                 :          0 :                         return -EBUSY;
     229                 :            : 
     230                 :          0 :                 family = s->family;
     231                 :            : 
     232         [ #  # ]:          0 :                 if (family == AF_INET) {
     233                 :          0 :                         addr.in = LLMNR_MULTICAST_IPV4_ADDRESS;
     234                 :          0 :                         fd = manager_llmnr_ipv4_udp_fd(s->manager);
     235         [ #  # ]:          0 :                 } else if (family == AF_INET6) {
     236                 :          0 :                         addr.in6 = LLMNR_MULTICAST_IPV6_ADDRESS;
     237                 :          0 :                         fd = manager_llmnr_ipv6_udp_fd(s->manager);
     238                 :            :                 } else
     239                 :          0 :                         return -EAFNOSUPPORT;
     240         [ #  # ]:          0 :                 if (fd < 0)
     241                 :          0 :                         return fd;
     242                 :            : 
     243                 :          0 :                 r = manager_send(s->manager, fd, ifindex, family, &addr, LLMNR_PORT, NULL, p);
     244         [ #  # ]:          0 :                 if (r < 0)
     245                 :          0 :                         return r;
     246                 :            : 
     247                 :          0 :                 break;
     248                 :            : 
     249                 :          0 :         case DNS_PROTOCOL_MDNS:
     250         [ #  # ]:          0 :                 assert(fd < 0);
     251                 :            : 
     252         [ #  # ]:          0 :                 if (!ratelimit_below(&s->ratelimit))
     253                 :          0 :                         return -EBUSY;
     254                 :            : 
     255                 :          0 :                 family = s->family;
     256                 :            : 
     257         [ #  # ]:          0 :                 if (family == AF_INET) {
     258                 :          0 :                         addr.in = MDNS_MULTICAST_IPV4_ADDRESS;
     259                 :          0 :                         fd = manager_mdns_ipv4_fd(s->manager);
     260         [ #  # ]:          0 :                 } else if (family == AF_INET6) {
     261                 :          0 :                         addr.in6 = MDNS_MULTICAST_IPV6_ADDRESS;
     262                 :          0 :                         fd = manager_mdns_ipv6_fd(s->manager);
     263                 :            :                 } else
     264                 :          0 :                         return -EAFNOSUPPORT;
     265         [ #  # ]:          0 :                 if (fd < 0)
     266                 :          0 :                         return fd;
     267                 :            : 
     268                 :          0 :                 r = manager_send(s->manager, fd, ifindex, family, &addr, MDNS_PORT, NULL, p);
     269         [ #  # ]:          0 :                 if (r < 0)
     270                 :          0 :                         return r;
     271                 :            : 
     272                 :          0 :                 break;
     273                 :            : 
     274                 :          0 :         default:
     275                 :          0 :                 return -EAFNOSUPPORT;
     276                 :            :         }
     277                 :            : 
     278                 :          0 :         return 1;
     279                 :            : }
     280                 :            : 
     281                 :          0 : int dns_scope_emit_udp(DnsScope *s, int fd, DnsPacket *p) {
     282                 :            :         int r;
     283                 :            : 
     284         [ #  # ]:          0 :         assert(s);
     285         [ #  # ]:          0 :         assert(p);
     286         [ #  # ]:          0 :         assert(p->protocol == s->protocol);
     287         [ #  # ]:          0 :         assert((s->protocol == DNS_PROTOCOL_DNS) == (fd >= 0));
     288                 :            : 
     289                 :            :         do {
     290                 :            :                 /* If there are multiple linked packets, set the TC bit in all but the last of them */
     291         [ #  # ]:          0 :                 if (p->more) {
     292         [ #  # ]:          0 :                         assert(p->protocol == DNS_PROTOCOL_MDNS);
     293                 :          0 :                         dns_packet_set_flags(p, true, true);
     294                 :            :                 }
     295                 :            : 
     296                 :          0 :                 r = dns_scope_emit_one(s, fd, p);
     297         [ #  # ]:          0 :                 if (r < 0)
     298                 :          0 :                         return r;
     299                 :            : 
     300                 :          0 :                 p = p->more;
     301         [ #  # ]:          0 :         } while (p);
     302                 :            : 
     303                 :          0 :         return 0;
     304                 :            : }
     305                 :            : 
     306                 :          0 : static int dns_scope_socket(
     307                 :            :                 DnsScope *s,
     308                 :            :                 int type,
     309                 :            :                 int family,
     310                 :            :                 const union in_addr_union *address,
     311                 :            :                 DnsServer *server,
     312                 :            :                 uint16_t port,
     313                 :            :                 union sockaddr_union *ret_socket_address) {
     314                 :            : 
     315                 :          0 :         _cleanup_close_ int fd = -1;
     316                 :            :         union sockaddr_union sa;
     317                 :            :         socklen_t salen;
     318                 :            :         int r, ifindex;
     319                 :            : 
     320         [ #  # ]:          0 :         assert(s);
     321                 :            : 
     322         [ #  # ]:          0 :         if (server) {
     323         [ #  # ]:          0 :                 assert(family == AF_UNSPEC);
     324         [ #  # ]:          0 :                 assert(!address);
     325                 :            : 
     326                 :          0 :                 ifindex = dns_server_ifindex(server);
     327                 :            : 
     328      [ #  #  # ]:          0 :                 switch (server->family) {
     329                 :          0 :                 case AF_INET:
     330                 :          0 :                         sa = (union sockaddr_union) {
     331                 :          0 :                                 .in.sin_family = server->family,
     332                 :          0 :                                 .in.sin_port = htobe16(port),
     333                 :          0 :                                 .in.sin_addr = server->address.in,
     334                 :            :                         };
     335                 :          0 :                         salen = sizeof(sa.in);
     336                 :          0 :                         break;
     337                 :          0 :                 case AF_INET6:
     338                 :          0 :                         sa = (union sockaddr_union) {
     339                 :          0 :                                 .in6.sin6_family = server->family,
     340                 :          0 :                                 .in6.sin6_port = htobe16(port),
     341                 :          0 :                                 .in6.sin6_addr = server->address.in6,
     342                 :            :                                 .in6.sin6_scope_id = ifindex,
     343                 :            :                         };
     344                 :          0 :                         salen = sizeof(sa.in6);
     345                 :          0 :                         break;
     346                 :          0 :                 default:
     347                 :          0 :                         return -EAFNOSUPPORT;
     348                 :            :                 }
     349                 :            :         } else {
     350         [ #  # ]:          0 :                 assert(family != AF_UNSPEC);
     351         [ #  # ]:          0 :                 assert(address);
     352                 :            : 
     353         [ #  # ]:          0 :                 ifindex = s->link ? s->link->ifindex : 0;
     354                 :            : 
     355      [ #  #  # ]:          0 :                 switch (family) {
     356                 :          0 :                 case AF_INET:
     357                 :          0 :                         sa = (union sockaddr_union) {
     358                 :            :                                 .in.sin_family = family,
     359                 :          0 :                                 .in.sin_port = htobe16(port),
     360                 :          0 :                                 .in.sin_addr = address->in,
     361                 :            :                         };
     362                 :          0 :                         salen = sizeof(sa.in);
     363                 :          0 :                         break;
     364                 :          0 :                 case AF_INET6:
     365                 :          0 :                         sa = (union sockaddr_union) {
     366                 :            :                                 .in6.sin6_family = family,
     367                 :          0 :                                 .in6.sin6_port = htobe16(port),
     368                 :          0 :                                 .in6.sin6_addr = address->in6,
     369                 :            :                                 .in6.sin6_scope_id = ifindex,
     370                 :            :                         };
     371                 :          0 :                         salen = sizeof(sa.in6);
     372                 :          0 :                         break;
     373                 :          0 :                 default:
     374                 :          0 :                         return -EAFNOSUPPORT;
     375                 :            :                 }
     376                 :            :         }
     377                 :            : 
     378                 :          0 :         fd = socket(sa.sa.sa_family, type|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
     379         [ #  # ]:          0 :         if (fd < 0)
     380                 :          0 :                 return -errno;
     381                 :            : 
     382         [ #  # ]:          0 :         if (type == SOCK_STREAM) {
     383                 :          0 :                 r = setsockopt_int(fd, IPPROTO_TCP, TCP_NODELAY, true);
     384         [ #  # ]:          0 :                 if (r < 0)
     385                 :          0 :                         return r;
     386                 :            :         }
     387                 :            : 
     388         [ #  # ]:          0 :         if (s->link) {
     389                 :          0 :                 be32_t ifindex_be = htobe32(ifindex);
     390                 :            : 
     391         [ #  # ]:          0 :                 if (sa.sa.sa_family == AF_INET) {
     392                 :          0 :                         r = setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex_be, sizeof(ifindex_be));
     393         [ #  # ]:          0 :                         if (r < 0)
     394                 :          0 :                                 return -errno;
     395         [ #  # ]:          0 :                 } else if (sa.sa.sa_family == AF_INET6) {
     396                 :          0 :                         r = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex_be, sizeof(ifindex_be));
     397         [ #  # ]:          0 :                         if (r < 0)
     398                 :          0 :                                 return -errno;
     399                 :            :                 }
     400                 :            :         }
     401                 :            : 
     402         [ #  # ]:          0 :         if (s->protocol == DNS_PROTOCOL_LLMNR) {
     403                 :            :                 /* RFC 4795, section 2.5 requires the TTL to be set to 1 */
     404                 :            : 
     405         [ #  # ]:          0 :                 if (sa.sa.sa_family == AF_INET) {
     406                 :          0 :                         r = setsockopt_int(fd, IPPROTO_IP, IP_TTL, true);
     407         [ #  # ]:          0 :                         if (r < 0)
     408                 :          0 :                                 return r;
     409         [ #  # ]:          0 :                 } else if (sa.sa.sa_family == AF_INET6) {
     410                 :          0 :                         r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, true);
     411         [ #  # ]:          0 :                         if (r < 0)
     412                 :          0 :                                 return r;
     413                 :            :                 }
     414                 :            :         }
     415                 :            : 
     416         [ #  # ]:          0 :         if (type == SOCK_DGRAM) {
     417                 :            :                 /* Set IP_RECVERR or IPV6_RECVERR to get ICMP error feedback. See discussion in #10345. */
     418                 :            : 
     419         [ #  # ]:          0 :                 if (sa.sa.sa_family == AF_INET) {
     420                 :          0 :                         r = setsockopt_int(fd, IPPROTO_IP, IP_RECVERR, true);
     421         [ #  # ]:          0 :                         if (r < 0)
     422                 :          0 :                                 return r;
     423                 :            : 
     424                 :          0 :                         r = setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, true);
     425         [ #  # ]:          0 :                         if (r < 0)
     426                 :          0 :                                 return r;
     427                 :            : 
     428         [ #  # ]:          0 :                 } else if (sa.sa.sa_family == AF_INET6) {
     429                 :          0 :                         r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVERR, true);
     430         [ #  # ]:          0 :                         if (r < 0)
     431                 :          0 :                                 return r;
     432                 :            : 
     433                 :          0 :                         r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, true);
     434         [ #  # ]:          0 :                         if (r < 0)
     435                 :          0 :                                 return r;
     436                 :            :                 }
     437                 :            :         }
     438                 :            : 
     439         [ #  # ]:          0 :         if (ret_socket_address)
     440                 :          0 :                 *ret_socket_address = sa;
     441                 :            :         else {
     442                 :          0 :                 r = connect(fd, &sa.sa, salen);
     443   [ #  #  #  # ]:          0 :                 if (r < 0 && errno != EINPROGRESS)
     444                 :          0 :                         return -errno;
     445                 :            :         }
     446                 :            : 
     447                 :          0 :         return TAKE_FD(fd);
     448                 :            : }
     449                 :            : 
     450                 :          0 : int dns_scope_socket_udp(DnsScope *s, DnsServer *server, uint16_t port) {
     451                 :          0 :         return dns_scope_socket(s, SOCK_DGRAM, AF_UNSPEC, NULL, server, port, NULL);
     452                 :            : }
     453                 :            : 
     454                 :          0 : int dns_scope_socket_tcp(DnsScope *s, int family, const union in_addr_union *address, DnsServer *server, uint16_t port, union sockaddr_union *ret_socket_address) {
     455                 :            :         /* If ret_socket_address is not NULL, the caller is responsible
     456                 :            :          * for calling connect() or sendmsg(). This is required by TCP
     457                 :            :          * Fast Open, to be able to send the initial SYN packet along
     458                 :            :          * with the first data packet. */
     459                 :          0 :         return dns_scope_socket(s, SOCK_STREAM, family, address, server, port, ret_socket_address);
     460                 :            : }
     461                 :            : 
     462                 :          0 : static DnsScopeMatch accept_link_local_reverse_lookups(const char *domain) {
     463         [ #  # ]:          0 :         assert(domain);
     464                 :            : 
     465         [ #  # ]:          0 :         if (dns_name_endswith(domain, "254.169.in-addr.arpa") > 0)
     466                 :          0 :                 return DNS_SCOPE_YES_BASE + 4; /* 4 labels match */
     467                 :            : 
     468   [ #  #  #  # ]:          0 :         if (dns_name_endswith(domain, "8.e.f.ip6.arpa") > 0 ||
     469         [ #  # ]:          0 :             dns_name_endswith(domain, "9.e.f.ip6.arpa") > 0 ||
     470         [ #  # ]:          0 :             dns_name_endswith(domain, "a.e.f.ip6.arpa") > 0 ||
     471                 :          0 :             dns_name_endswith(domain, "b.e.f.ip6.arpa") > 0)
     472                 :          0 :                 return DNS_SCOPE_YES_BASE + 5; /* 5 labels match */
     473                 :            : 
     474                 :          0 :         return _DNS_SCOPE_MATCH_INVALID;
     475                 :            : }
     476                 :            : 
     477                 :          0 : DnsScopeMatch dns_scope_good_domain(
     478                 :            :                 DnsScope *s,
     479                 :            :                 int ifindex,
     480                 :            :                 uint64_t flags,
     481                 :            :                 const char *domain) {
     482                 :            : 
     483                 :            :         DnsSearchDomain *d;
     484                 :            : 
     485                 :            :         /* This returns the following return values:
     486                 :            :          *
     487                 :            :          *    DNS_SCOPE_NO         → This scope is not suitable for lookups of this domain, at all
     488                 :            :          *    DNS_SCOPE_MAYBE      → This scope is suitable, but only if nothing else wants it
     489                 :            :          *    DNS_SCOPE_YES_BASE+n → This scope is suitable, and 'n' suffix labels match
     490                 :            :          *
     491                 :            :          *  (The idea is that the caller will only use the scopes with the longest 'n' returned. If no scopes return
     492                 :            :          *  DNS_SCOPE_YES_BASE+n, then it should use those which returned DNS_SCOPE_MAYBE. It should never use those
     493                 :            :          *  which returned DNS_SCOPE_NO.)
     494                 :            :          */
     495                 :            : 
     496         [ #  # ]:          0 :         assert(s);
     497         [ #  # ]:          0 :         assert(domain);
     498                 :            : 
     499                 :            :         /* Checks if the specified domain is something to look up on
     500                 :            :          * this scope. Note that this accepts non-qualified hostnames,
     501                 :            :          * i.e. those without any search path prefixed yet. */
     502                 :            : 
     503   [ #  #  #  #  :          0 :         if (ifindex != 0 && (!s->link || s->link->ifindex != ifindex))
                   #  # ]
     504                 :          0 :                 return DNS_SCOPE_NO;
     505                 :            : 
     506         [ #  # ]:          0 :         if ((SD_RESOLVED_FLAGS_MAKE(s->protocol, s->family, 0) & flags) == 0)
     507                 :          0 :                 return DNS_SCOPE_NO;
     508                 :            : 
     509                 :            :         /* Never resolve any loopback hostname or IP address via DNS,
     510                 :            :          * LLMNR or mDNS. Instead, always rely on synthesized RRs for
     511                 :            :          * these. */
     512   [ #  #  #  # ]:          0 :         if (is_localhost(domain) ||
     513         [ #  # ]:          0 :             dns_name_endswith(domain, "127.in-addr.arpa") > 0 ||
     514                 :          0 :             dns_name_equal(domain, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa") > 0)
     515                 :          0 :                 return DNS_SCOPE_NO;
     516                 :            : 
     517                 :            :         /* Never respond to some of the domains listed in RFC6303 */
     518   [ #  #  #  # ]:          0 :         if (dns_name_endswith(domain, "0.in-addr.arpa") > 0 ||
     519         [ #  # ]:          0 :             dns_name_equal(domain, "255.255.255.255.in-addr.arpa") > 0 ||
     520                 :          0 :             dns_name_equal(domain, "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa") > 0)
     521                 :          0 :                 return DNS_SCOPE_NO;
     522                 :            : 
     523                 :            :         /* Never respond to some of the domains listed in RFC6761 */
     524         [ #  # ]:          0 :         if (dns_name_endswith(domain, "invalid") > 0)
     525                 :          0 :                 return DNS_SCOPE_NO;
     526                 :            : 
     527   [ #  #  #  # ]:          0 :         switch (s->protocol) {
     528                 :            : 
     529                 :          0 :         case DNS_PROTOCOL_DNS: {
     530                 :          0 :                 bool has_search_domains = false;
     531                 :          0 :                 int n_best = -1;
     532                 :            : 
     533                 :            :                 /* Never route things to scopes that lack DNS servers */
     534         [ #  # ]:          0 :                 if (!dns_scope_get_dns_server(s))
     535                 :          0 :                         return DNS_SCOPE_NO;
     536                 :            : 
     537                 :            :                 /* Always honour search domains for routing queries, except if this scope lacks DNS servers. Note that
     538                 :            :                  * we return DNS_SCOPE_YES here, rather than just DNS_SCOPE_MAYBE, which means other wildcard scopes
     539                 :            :                  * won't be considered anymore. */
     540         [ #  # ]:          0 :                 LIST_FOREACH(domains, d, dns_scope_get_search_domains(s)) {
     541                 :            : 
     542   [ #  #  #  # ]:          0 :                         if (!d->route_only && !dns_name_is_root(d->name))
     543                 :          0 :                                 has_search_domains = true;
     544                 :            : 
     545         [ #  # ]:          0 :                         if (dns_name_endswith(domain, d->name) > 0) {
     546                 :            :                                 int c;
     547                 :            : 
     548                 :          0 :                                 c = dns_name_count_labels(d->name);
     549         [ #  # ]:          0 :                                 if (c < 0)
     550                 :          0 :                                         continue;
     551                 :            : 
     552         [ #  # ]:          0 :                                 if (c > n_best)
     553                 :          0 :                                         n_best = c;
     554                 :            :                         }
     555                 :            :                 }
     556                 :            : 
     557                 :            :                 /* If there's a true search domain defined for this scope, and the query is single-label,
     558                 :            :                  * then let's resolve things here, prefereably. Note that LLMNR considers itself
     559                 :            :                  * authoritative for single-label names too, at the same preference, see below. */
     560   [ #  #  #  # ]:          0 :                 if (has_search_domains && dns_name_is_single_label(domain))
     561                 :          0 :                         return DNS_SCOPE_YES_BASE + 1;
     562                 :            : 
     563                 :            :                 /* Let's return the number of labels in the best matching result */
     564         [ #  # ]:          0 :                 if (n_best >= 0) {
     565         [ #  # ]:          0 :                         assert(n_best <= DNS_SCOPE_YES_END - DNS_SCOPE_YES_BASE);
     566                 :          0 :                         return DNS_SCOPE_YES_BASE + n_best;
     567                 :            :                 }
     568                 :            : 
     569                 :            :                 /* See if this scope is suitable as default route. */
     570         [ #  # ]:          0 :                 if (!dns_scope_is_default_route(s))
     571                 :          0 :                         return DNS_SCOPE_NO;
     572                 :            : 
     573                 :            :                 /* Exclude link-local IP ranges */
     574   [ #  #  #  # ]:          0 :                 if (dns_name_endswith(domain, "254.169.in-addr.arpa") == 0 &&
     575         [ #  # ]:          0 :                     dns_name_endswith(domain, "8.e.f.ip6.arpa") == 0 &&
     576         [ #  # ]:          0 :                     dns_name_endswith(domain, "9.e.f.ip6.arpa") == 0 &&
     577         [ #  # ]:          0 :                     dns_name_endswith(domain, "a.e.f.ip6.arpa") == 0 &&
     578         [ #  # ]:          0 :                     dns_name_endswith(domain, "b.e.f.ip6.arpa") == 0 &&
     579                 :            :                     /* If networks use .local in their private setups, they are supposed to also add .local to their search
     580                 :            :                      * domains, which we already checked above. Otherwise, we consider .local specific to mDNS and won't
     581                 :            :                      * send such queries ordinary DNS servers. */
     582                 :          0 :                     dns_name_endswith(domain, "local") == 0)
     583                 :          0 :                         return DNS_SCOPE_MAYBE;
     584                 :            : 
     585                 :          0 :                 return DNS_SCOPE_NO;
     586                 :            :         }
     587                 :            : 
     588                 :          0 :         case DNS_PROTOCOL_MDNS: {
     589                 :            :                 DnsScopeMatch m;
     590                 :            : 
     591                 :          0 :                 m = accept_link_local_reverse_lookups(domain);
     592         [ #  # ]:          0 :                 if (m >= 0)
     593                 :          0 :                         return m;
     594                 :            : 
     595   [ #  #  #  # ]:          0 :                 if ((s->family == AF_INET && dns_name_endswith(domain, "in-addr.arpa") > 0) ||
     596   [ #  #  #  # ]:          0 :                     (s->family == AF_INET6 && dns_name_endswith(domain, "ip6.arpa") > 0))
     597                 :          0 :                         return DNS_SCOPE_MAYBE;
     598                 :            : 
     599   [ #  #  #  # ]:          0 :                 if ((dns_name_endswith(domain, "local") > 0 && /* only resolve names ending in .local via mDNS */
     600         [ #  # ]:          0 :                      dns_name_equal(domain, "local") == 0 &&   /* but not the single-label "local" name itself */
     601                 :          0 :                      manager_is_own_hostname(s->manager, domain) <= 0)) /* never resolve the local hostname via mDNS */
     602                 :          0 :                         return DNS_SCOPE_YES_BASE + 1; /* Return +1, as the top-level .local domain matches, i.e. one label */
     603                 :            : 
     604                 :          0 :                 return DNS_SCOPE_NO;
     605                 :            :         }
     606                 :            : 
     607                 :          0 :         case DNS_PROTOCOL_LLMNR: {
     608                 :            :                 DnsScopeMatch m;
     609                 :            : 
     610                 :          0 :                 m = accept_link_local_reverse_lookups(domain);
     611         [ #  # ]:          0 :                 if (m >= 0)
     612                 :          0 :                         return m;
     613                 :            : 
     614   [ #  #  #  # ]:          0 :                 if ((s->family == AF_INET && dns_name_endswith(domain, "in-addr.arpa") > 0) ||
     615   [ #  #  #  # ]:          0 :                     (s->family == AF_INET6 && dns_name_endswith(domain, "ip6.arpa") > 0))
     616                 :          0 :                         return DNS_SCOPE_MAYBE;
     617                 :            : 
     618         [ #  # ]:          0 :                 if ((dns_name_is_single_label(domain) && /* only resolve single label names via LLMNR */
     619   [ #  #  #  # ]:          0 :                      !is_gateway_hostname(domain) && /* don't resolve "gateway" with LLMNR, let nss-myhostname handle this */
     620                 :          0 :                      manager_is_own_hostname(s->manager, domain) <= 0))  /* never resolve the local hostname via LLMNR */
     621                 :          0 :                         return DNS_SCOPE_YES_BASE + 1; /* Return +1, as we consider ourselves authoritative
     622                 :            :                                                         * for single-label names, i.e. one label. This is
     623                 :            :                                                         * particular relevant as it means a "." route on some
     624                 :            :                                                         * other scope won't pull all traffic away from
     625                 :            :                                                         * us. (If people actually want to pull traffic away
     626                 :            :                                                         * from us they should turn off LLMNR on the
     627                 :            :                                                         * link). Note that unicast DNS scopes with search
     628                 :            :                                                         * domains also consider themselves authoritative for
     629                 :            :                                                         * single-label domains, at the same preference (see
     630                 :            :                                                         * above). */
     631                 :            : 
     632                 :          0 :                 return DNS_SCOPE_NO;
     633                 :            :         }
     634                 :            : 
     635                 :          0 :         default:
     636                 :          0 :                 assert_not_reached("Unknown scope protocol");
     637                 :            :         }
     638                 :            : }
     639                 :            : 
     640                 :          0 : bool dns_scope_good_key(DnsScope *s, const DnsResourceKey *key) {
     641                 :            :         int key_family;
     642                 :            : 
     643         [ #  # ]:          0 :         assert(s);
     644         [ #  # ]:          0 :         assert(key);
     645                 :            : 
     646                 :            :         /* Check if it makes sense to resolve the specified key on
     647                 :            :          * this scope. Note that this call assumes as fully qualified
     648                 :            :          * name, i.e. the search suffixes already appended. */
     649                 :            : 
     650         [ #  # ]:          0 :         if (key->class != DNS_CLASS_IN)
     651                 :          0 :                 return false;
     652                 :            : 
     653         [ #  # ]:          0 :         if (s->protocol == DNS_PROTOCOL_DNS) {
     654                 :            : 
     655                 :            :                 /* On classic DNS, looking up non-address RRs is always
     656                 :            :                  * fine. (Specifically, we want to permit looking up
     657                 :            :                  * DNSKEY and DS records on the root and top-level
     658                 :            :                  * domains.) */
     659         [ #  # ]:          0 :                 if (!dns_resource_key_is_address(key))
     660                 :          0 :                         return true;
     661                 :            : 
     662                 :            :                 /* However, we refuse to look up A and AAAA RRs on the
     663                 :            :                  * root and single-label domains, under the assumption
     664                 :            :                  * that those should be resolved via LLMNR or search
     665                 :            :                  * path only, and should not be leaked onto the
     666                 :            :                  * internet. */
     667   [ #  #  #  # ]:          0 :                 return !(dns_name_is_single_label(dns_resource_key_name(key)) ||
     668                 :          0 :                          dns_name_is_root(dns_resource_key_name(key)));
     669                 :            :         }
     670                 :            : 
     671                 :            :         /* On mDNS and LLMNR, send A and AAAA queries only on the
     672                 :            :          * respective scopes */
     673                 :            : 
     674                 :          0 :         key_family = dns_type_to_af(key->type);
     675         [ #  # ]:          0 :         if (key_family < 0)
     676                 :          0 :                 return true;
     677                 :            : 
     678                 :          0 :         return key_family == s->family;
     679                 :            : }
     680                 :            : 
     681                 :          0 : static int dns_scope_multicast_membership(DnsScope *s, bool b, struct in_addr in, struct in6_addr in6) {
     682                 :            :         int fd;
     683                 :            : 
     684         [ #  # ]:          0 :         assert(s);
     685         [ #  # ]:          0 :         assert(s->link);
     686                 :            : 
     687         [ #  # ]:          0 :         if (s->family == AF_INET) {
     688                 :          0 :                 struct ip_mreqn mreqn = {
     689                 :            :                         .imr_multiaddr = in,
     690                 :          0 :                         .imr_ifindex = s->link->ifindex,
     691                 :            :                 };
     692                 :            : 
     693         [ #  # ]:          0 :                 if (s->protocol == DNS_PROTOCOL_LLMNR)
     694                 :          0 :                         fd = manager_llmnr_ipv4_udp_fd(s->manager);
     695                 :            :                 else
     696                 :          0 :                         fd = manager_mdns_ipv4_fd(s->manager);
     697                 :            : 
     698         [ #  # ]:          0 :                 if (fd < 0)
     699                 :          0 :                         return fd;
     700                 :            : 
     701                 :            :                 /* Always first try to drop membership before we add
     702                 :            :                  * one. This is necessary on some devices, such as
     703                 :            :                  * veth. */
     704         [ #  # ]:          0 :                 if (b)
     705                 :          0 :                         (void) setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreqn, sizeof(mreqn));
     706                 :            : 
     707   [ #  #  #  # ]:          0 :                 if (setsockopt(fd, IPPROTO_IP, b ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP, &mreqn, sizeof(mreqn)) < 0)
     708                 :          0 :                         return -errno;
     709                 :            : 
     710         [ #  # ]:          0 :         } else if (s->family == AF_INET6) {
     711                 :          0 :                 struct ipv6_mreq mreq = {
     712                 :            :                         .ipv6mr_multiaddr = in6,
     713                 :          0 :                         .ipv6mr_interface = s->link->ifindex,
     714                 :            :                 };
     715                 :            : 
     716         [ #  # ]:          0 :                 if (s->protocol == DNS_PROTOCOL_LLMNR)
     717                 :          0 :                         fd = manager_llmnr_ipv6_udp_fd(s->manager);
     718                 :            :                 else
     719                 :          0 :                         fd = manager_mdns_ipv6_fd(s->manager);
     720                 :            : 
     721         [ #  # ]:          0 :                 if (fd < 0)
     722                 :          0 :                         return fd;
     723                 :            : 
     724         [ #  # ]:          0 :                 if (b)
     725                 :          0 :                         (void) setsockopt(fd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mreq, sizeof(mreq));
     726                 :            : 
     727   [ #  #  #  # ]:          0 :                 if (setsockopt(fd, IPPROTO_IPV6, b ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
     728                 :          0 :                         return -errno;
     729                 :            :         } else
     730                 :          0 :                 return -EAFNOSUPPORT;
     731                 :            : 
     732                 :          0 :         return 0;
     733                 :            : }
     734                 :            : 
     735                 :          0 : int dns_scope_llmnr_membership(DnsScope *s, bool b) {
     736         [ #  # ]:          0 :         assert(s);
     737                 :            : 
     738         [ #  # ]:          0 :         if (s->protocol != DNS_PROTOCOL_LLMNR)
     739                 :          0 :                 return 0;
     740                 :            : 
     741                 :          0 :         return dns_scope_multicast_membership(s, b, LLMNR_MULTICAST_IPV4_ADDRESS, LLMNR_MULTICAST_IPV6_ADDRESS);
     742                 :            : }
     743                 :            : 
     744                 :          0 : int dns_scope_mdns_membership(DnsScope *s, bool b) {
     745         [ #  # ]:          0 :         assert(s);
     746                 :            : 
     747         [ #  # ]:          0 :         if (s->protocol != DNS_PROTOCOL_MDNS)
     748                 :          0 :                 return 0;
     749                 :            : 
     750                 :          0 :         return dns_scope_multicast_membership(s, b, MDNS_MULTICAST_IPV4_ADDRESS, MDNS_MULTICAST_IPV6_ADDRESS);
     751                 :            : }
     752                 :            : 
     753                 :          0 : int dns_scope_make_reply_packet(
     754                 :            :                 DnsScope *s,
     755                 :            :                 uint16_t id,
     756                 :            :                 int rcode,
     757                 :            :                 DnsQuestion *q,
     758                 :            :                 DnsAnswer *answer,
     759                 :            :                 DnsAnswer *soa,
     760                 :            :                 bool tentative,
     761                 :            :                 DnsPacket **ret) {
     762                 :            : 
     763                 :          0 :         _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
     764                 :            :         int r;
     765                 :            : 
     766         [ #  # ]:          0 :         assert(s);
     767         [ #  # ]:          0 :         assert(ret);
     768                 :            : 
     769   [ #  #  #  # ]:          0 :         if (dns_question_isempty(q) &&
     770         [ #  # ]:          0 :             dns_answer_isempty(answer) &&
     771                 :          0 :             dns_answer_isempty(soa))
     772                 :          0 :                 return -EINVAL;
     773                 :            : 
     774                 :          0 :         r = dns_packet_new(&p, s->protocol, 0, DNS_PACKET_SIZE_MAX);
     775         [ #  # ]:          0 :         if (r < 0)
     776                 :          0 :                 return r;
     777                 :            : 
     778                 :          0 :         DNS_PACKET_HEADER(p)->id = id;
     779         [ #  # ]:          0 :         DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS(
     780                 :            :                                                               1 /* qr */,
     781                 :            :                                                               0 /* opcode */,
     782                 :            :                                                               0 /* c */,
     783                 :            :                                                               0 /* tc */,
     784                 :            :                                                               tentative,
     785                 :            :                                                               0 /* (ra) */,
     786                 :            :                                                               0 /* (ad) */,
     787                 :            :                                                               0 /* (cd) */,
     788                 :            :                                                               rcode));
     789                 :            : 
     790                 :          0 :         r = dns_packet_append_question(p, q);
     791         [ #  # ]:          0 :         if (r < 0)
     792                 :          0 :                 return r;
     793                 :          0 :         DNS_PACKET_HEADER(p)->qdcount = htobe16(dns_question_size(q));
     794                 :            : 
     795                 :          0 :         r = dns_packet_append_answer(p, answer);
     796         [ #  # ]:          0 :         if (r < 0)
     797                 :          0 :                 return r;
     798                 :          0 :         DNS_PACKET_HEADER(p)->ancount = htobe16(dns_answer_size(answer));
     799                 :            : 
     800                 :          0 :         r = dns_packet_append_answer(p, soa);
     801         [ #  # ]:          0 :         if (r < 0)
     802                 :          0 :                 return r;
     803                 :          0 :         DNS_PACKET_HEADER(p)->arcount = htobe16(dns_answer_size(soa));
     804                 :            : 
     805                 :          0 :         *ret = TAKE_PTR(p);
     806                 :            : 
     807                 :          0 :         return 0;
     808                 :            : }
     809                 :            : 
     810                 :          0 : static void dns_scope_verify_conflicts(DnsScope *s, DnsPacket *p) {
     811                 :            :         DnsResourceRecord *rr;
     812                 :            :         DnsResourceKey *key;
     813                 :            : 
     814         [ #  # ]:          0 :         assert(s);
     815         [ #  # ]:          0 :         assert(p);
     816                 :            : 
     817   [ #  #  #  #  :          0 :         DNS_QUESTION_FOREACH(key, p->question)
          #  #  #  #  #  
                      # ]
     818                 :          0 :                 dns_zone_verify_conflicts(&s->zone, key);
     819                 :            : 
     820   [ #  #  #  #  :          0 :         DNS_ANSWER_FOREACH(rr, p->answer)
          #  #  #  #  #  
                      # ]
     821                 :          0 :                 dns_zone_verify_conflicts(&s->zone, rr->key);
     822                 :          0 : }
     823                 :            : 
     824                 :          0 : void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
     825   [ #  #  #  # ]:          0 :         _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
     826         [ #  # ]:          0 :         _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;
     827                 :          0 :         DnsResourceKey *key = NULL;
     828                 :          0 :         bool tentative = false;
     829                 :            :         int r;
     830                 :            : 
     831         [ #  # ]:          0 :         assert(s);
     832         [ #  # ]:          0 :         assert(p);
     833                 :            : 
     834         [ #  # ]:          0 :         if (p->protocol != DNS_PROTOCOL_LLMNR)
     835                 :          0 :                 return;
     836                 :            : 
     837         [ #  # ]:          0 :         if (p->ipproto == IPPROTO_UDP) {
     838                 :            :                 /* Don't accept UDP queries directed to anything but
     839                 :            :                  * the LLMNR multicast addresses. See RFC 4795,
     840                 :            :                  * section 2.5. */
     841                 :            : 
     842   [ #  #  #  # ]:          0 :                 if (p->family == AF_INET && !in_addr_equal(AF_INET, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV4_ADDRESS))
     843                 :          0 :                         return;
     844                 :            : 
     845   [ #  #  #  # ]:          0 :                 if (p->family == AF_INET6 && !in_addr_equal(AF_INET6, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV6_ADDRESS))
     846                 :          0 :                         return;
     847                 :            :         }
     848                 :            : 
     849                 :          0 :         r = dns_packet_extract(p);
     850         [ #  # ]:          0 :         if (r < 0) {
     851         [ #  # ]:          0 :                 log_debug_errno(r, "Failed to extract resource records from incoming packet: %m");
     852                 :          0 :                 return;
     853                 :            :         }
     854                 :            : 
     855         [ #  # ]:          0 :         if (DNS_PACKET_LLMNR_C(p)) {
     856                 :            :                 /* Somebody notified us about a possible conflict */
     857                 :          0 :                 dns_scope_verify_conflicts(s, p);
     858                 :          0 :                 return;
     859                 :            :         }
     860                 :            : 
     861         [ #  # ]:          0 :         assert(dns_question_size(p->question) == 1);
     862                 :          0 :         key = p->question->keys[0];
     863                 :            : 
     864                 :          0 :         r = dns_zone_lookup(&s->zone, key, 0, &answer, &soa, &tentative);
     865         [ #  # ]:          0 :         if (r < 0) {
     866         [ #  # ]:          0 :                 log_debug_errno(r, "Failed to lookup key: %m");
     867                 :          0 :                 return;
     868                 :            :         }
     869         [ #  # ]:          0 :         if (r == 0)
     870                 :          0 :                 return;
     871                 :            : 
     872         [ #  # ]:          0 :         if (answer)
     873                 :          0 :                 dns_answer_order_by_scope(answer, in_addr_is_link_local(p->family, &p->sender) > 0);
     874                 :            : 
     875                 :          0 :         r = dns_scope_make_reply_packet(s, DNS_PACKET_ID(p), DNS_RCODE_SUCCESS, p->question, answer, soa, tentative, &reply);
     876         [ #  # ]:          0 :         if (r < 0) {
     877         [ #  # ]:          0 :                 log_debug_errno(r, "Failed to build reply packet: %m");
     878                 :          0 :                 return;
     879                 :            :         }
     880                 :            : 
     881         [ #  # ]:          0 :         if (stream) {
     882                 :          0 :                 r = dns_stream_write_packet(stream, reply);
     883         [ #  # ]:          0 :                 if (r < 0) {
     884         [ #  # ]:          0 :                         log_debug_errno(r, "Failed to enqueue reply packet: %m");
     885                 :          0 :                         return;
     886                 :            :                 }
     887                 :            : 
     888                 :            :                 /* Let's take an extra reference on this stream, so that it stays around after returning. The reference
     889                 :            :                  * will be dangling until the stream is disconnected, and the default completion handler of the stream
     890                 :            :                  * will then unref the stream and destroy it */
     891         [ #  # ]:          0 :                 if (DNS_STREAM_QUEUED(stream))
     892                 :          0 :                         dns_stream_ref(stream);
     893                 :            :         } else {
     894                 :            :                 int fd;
     895                 :            : 
     896         [ #  # ]:          0 :                 if (!ratelimit_below(&s->ratelimit))
     897                 :          0 :                         return;
     898                 :            : 
     899         [ #  # ]:          0 :                 if (p->family == AF_INET)
     900                 :          0 :                         fd = manager_llmnr_ipv4_udp_fd(s->manager);
     901         [ #  # ]:          0 :                 else if (p->family == AF_INET6)
     902                 :          0 :                         fd = manager_llmnr_ipv6_udp_fd(s->manager);
     903                 :            :                 else {
     904         [ #  # ]:          0 :                         log_debug("Unknown protocol");
     905                 :          0 :                         return;
     906                 :            :                 }
     907         [ #  # ]:          0 :                 if (fd < 0) {
     908         [ #  # ]:          0 :                         log_debug_errno(fd, "Failed to get reply socket: %m");
     909                 :          0 :                         return;
     910                 :            :                 }
     911                 :            : 
     912                 :            :                 /* Note that we always immediately reply to all LLMNR
     913                 :            :                  * requests, and do not wait any time, since we
     914                 :            :                  * verified uniqueness for all records. Also see RFC
     915                 :            :                  * 4795, Section 2.7 */
     916                 :            : 
     917                 :          0 :                 r = manager_send(s->manager, fd, p->ifindex, p->family, &p->sender, p->sender_port, NULL, reply);
     918         [ #  # ]:          0 :                 if (r < 0) {
     919         [ #  # ]:          0 :                         log_debug_errno(r, "Failed to send reply packet: %m");
     920                 :          0 :                         return;
     921                 :            :                 }
     922                 :            :         }
     923                 :            : }
     924                 :            : 
     925                 :          0 : DnsTransaction *dns_scope_find_transaction(DnsScope *scope, DnsResourceKey *key, bool cache_ok) {
     926                 :            :         DnsTransaction *t;
     927                 :            : 
     928         [ #  # ]:          0 :         assert(scope);
     929         [ #  # ]:          0 :         assert(key);
     930                 :            : 
     931                 :            :         /* Try to find an ongoing transaction that is a equal to the
     932                 :            :          * specified question */
     933                 :          0 :         t = hashmap_get(scope->transactions_by_key, key);
     934         [ #  # ]:          0 :         if (!t)
     935                 :          0 :                 return NULL;
     936                 :            : 
     937                 :            :         /* Refuse reusing transactions that completed based on cached
     938                 :            :          * data instead of a real packet, if that's requested. */
     939         [ #  # ]:          0 :         if (!cache_ok &&
     940   [ #  #  #  # ]:          0 :             IN_SET(t->state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_RCODE_FAILURE) &&
     941         [ #  # ]:          0 :             t->answer_source != DNS_TRANSACTION_NETWORK)
     942                 :          0 :                 return NULL;
     943                 :            : 
     944                 :          0 :         return t;
     945                 :            : }
     946                 :            : 
     947                 :          0 : static int dns_scope_make_conflict_packet(
     948                 :            :                 DnsScope *s,
     949                 :            :                 DnsResourceRecord *rr,
     950                 :            :                 DnsPacket **ret) {
     951                 :            : 
     952                 :          0 :         _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
     953                 :            :         int r;
     954                 :            : 
     955         [ #  # ]:          0 :         assert(s);
     956         [ #  # ]:          0 :         assert(rr);
     957         [ #  # ]:          0 :         assert(ret);
     958                 :            : 
     959                 :          0 :         r = dns_packet_new(&p, s->protocol, 0, DNS_PACKET_SIZE_MAX);
     960         [ #  # ]:          0 :         if (r < 0)
     961                 :          0 :                 return r;
     962                 :            : 
     963                 :          0 :         DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS(
     964                 :            :                                                               0 /* qr */,
     965                 :            :                                                               0 /* opcode */,
     966                 :            :                                                               1 /* conflict */,
     967                 :            :                                                               0 /* tc */,
     968                 :            :                                                               0 /* t */,
     969                 :            :                                                               0 /* (ra) */,
     970                 :            :                                                               0 /* (ad) */,
     971                 :            :                                                               0 /* (cd) */,
     972                 :            :                                                               0));
     973                 :            : 
     974                 :            :         /* For mDNS, the transaction ID should always be 0 */
     975         [ #  # ]:          0 :         if (s->protocol != DNS_PROTOCOL_MDNS)
     976                 :          0 :                 random_bytes(&DNS_PACKET_HEADER(p)->id, sizeof(uint16_t));
     977                 :            : 
     978                 :          0 :         DNS_PACKET_HEADER(p)->qdcount = htobe16(1);
     979                 :          0 :         DNS_PACKET_HEADER(p)->arcount = htobe16(1);
     980                 :            : 
     981                 :          0 :         r = dns_packet_append_key(p, rr->key, 0, NULL);
     982         [ #  # ]:          0 :         if (r < 0)
     983                 :          0 :                 return r;
     984                 :            : 
     985                 :          0 :         r = dns_packet_append_rr(p, rr, 0, NULL, NULL);
     986         [ #  # ]:          0 :         if (r < 0)
     987                 :          0 :                 return r;
     988                 :            : 
     989                 :          0 :         *ret = TAKE_PTR(p);
     990                 :            : 
     991                 :          0 :         return 0;
     992                 :            : }
     993                 :            : 
     994                 :          0 : static int on_conflict_dispatch(sd_event_source *es, usec_t usec, void *userdata) {
     995                 :          0 :         DnsScope *scope = userdata;
     996                 :            :         int r;
     997                 :            : 
     998         [ #  # ]:          0 :         assert(es);
     999         [ #  # ]:          0 :         assert(scope);
    1000                 :            : 
    1001                 :          0 :         scope->conflict_event_source = sd_event_source_unref(scope->conflict_event_source);
    1002                 :            : 
    1003                 :          0 :         for (;;) {
    1004      [ #  #  # ]:          0 :                 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
    1005      [ #  #  # ]:          0 :                 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
    1006      [ #  #  # ]:          0 :                 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
    1007                 :            : 
    1008                 :          0 :                 key = ordered_hashmap_first_key(scope->conflict_queue);
    1009         [ #  # ]:          0 :                 if (!key)
    1010                 :          0 :                         break;
    1011                 :            : 
    1012                 :          0 :                 rr = ordered_hashmap_remove(scope->conflict_queue, key);
    1013         [ #  # ]:          0 :                 assert(rr);
    1014                 :            : 
    1015                 :          0 :                 r = dns_scope_make_conflict_packet(scope, rr, &p);
    1016         [ #  # ]:          0 :                 if (r < 0) {
    1017         [ #  # ]:          0 :                         log_error_errno(r, "Failed to make conflict packet: %m");
    1018                 :          0 :                         return 0;
    1019                 :            :                 }
    1020                 :            : 
    1021                 :          0 :                 r = dns_scope_emit_udp(scope, -1, p);
    1022         [ #  # ]:          0 :                 if (r < 0)
    1023         [ #  # ]:          0 :                         log_debug_errno(r, "Failed to send conflict packet: %m");
    1024                 :            :         }
    1025                 :            : 
    1026                 :          0 :         return 0;
    1027                 :            : }
    1028                 :            : 
    1029                 :          0 : int dns_scope_notify_conflict(DnsScope *scope, DnsResourceRecord *rr) {
    1030                 :            :         usec_t jitter;
    1031                 :            :         int r;
    1032                 :            : 
    1033         [ #  # ]:          0 :         assert(scope);
    1034         [ #  # ]:          0 :         assert(rr);
    1035                 :            : 
    1036                 :            :         /* We don't send these queries immediately. Instead, we queue
    1037                 :            :          * them, and send them after some jitter delay. */
    1038                 :          0 :         r = ordered_hashmap_ensure_allocated(&scope->conflict_queue, &dns_resource_key_hash_ops);
    1039         [ #  # ]:          0 :         if (r < 0) {
    1040                 :          0 :                 log_oom();
    1041                 :          0 :                 return r;
    1042                 :            :         }
    1043                 :            : 
    1044                 :            :         /* We only place one RR per key in the conflict
    1045                 :            :          * messages, not all of them. That should be enough to
    1046                 :            :          * indicate where there might be a conflict */
    1047                 :          0 :         r = ordered_hashmap_put(scope->conflict_queue, rr->key, rr);
    1048   [ #  #  #  # ]:          0 :         if (IN_SET(r, 0, -EEXIST))
    1049                 :          0 :                 return 0;
    1050         [ #  # ]:          0 :         if (r < 0)
    1051         [ #  # ]:          0 :                 return log_debug_errno(r, "Failed to queue conflicting RR: %m");
    1052                 :            : 
    1053                 :          0 :         dns_resource_key_ref(rr->key);
    1054                 :          0 :         dns_resource_record_ref(rr);
    1055                 :            : 
    1056         [ #  # ]:          0 :         if (scope->conflict_event_source)
    1057                 :          0 :                 return 0;
    1058                 :            : 
    1059                 :          0 :         random_bytes(&jitter, sizeof(jitter));
    1060                 :          0 :         jitter %= LLMNR_JITTER_INTERVAL_USEC;
    1061                 :            : 
    1062                 :          0 :         r = sd_event_add_time(scope->manager->event,
    1063                 :            :                               &scope->conflict_event_source,
    1064                 :            :                               clock_boottime_or_monotonic(),
    1065                 :          0 :                               now(clock_boottime_or_monotonic()) + jitter,
    1066                 :            :                               LLMNR_JITTER_INTERVAL_USEC,
    1067                 :            :                               on_conflict_dispatch, scope);
    1068         [ #  # ]:          0 :         if (r < 0)
    1069         [ #  # ]:          0 :                 return log_debug_errno(r, "Failed to add conflict dispatch event: %m");
    1070                 :            : 
    1071                 :          0 :         (void) sd_event_source_set_description(scope->conflict_event_source, "scope-conflict");
    1072                 :            : 
    1073                 :          0 :         return 0;
    1074                 :            : }
    1075                 :            : 
    1076                 :          0 : void dns_scope_check_conflicts(DnsScope *scope, DnsPacket *p) {
    1077                 :            :         DnsResourceRecord *rr;
    1078                 :            :         int r;
    1079                 :            : 
    1080         [ #  # ]:          0 :         assert(scope);
    1081         [ #  # ]:          0 :         assert(p);
    1082                 :            : 
    1083   [ #  #  #  # ]:          0 :         if (!IN_SET(p->protocol, DNS_PROTOCOL_LLMNR, DNS_PROTOCOL_MDNS))
    1084                 :          0 :                 return;
    1085                 :            : 
    1086         [ #  # ]:          0 :         if (DNS_PACKET_RRCOUNT(p) <= 0)
    1087                 :          0 :                 return;
    1088                 :            : 
    1089         [ #  # ]:          0 :         if (p->protocol == DNS_PROTOCOL_LLMNR) {
    1090         [ #  # ]:          0 :                 if (DNS_PACKET_LLMNR_C(p) != 0)
    1091                 :          0 :                         return;
    1092                 :            : 
    1093         [ #  # ]:          0 :                 if (DNS_PACKET_LLMNR_T(p) != 0)
    1094                 :          0 :                         return;
    1095                 :            :         }
    1096                 :            : 
    1097         [ #  # ]:          0 :         if (manager_our_packet(scope->manager, p))
    1098                 :          0 :                 return;
    1099                 :            : 
    1100                 :          0 :         r = dns_packet_extract(p);
    1101         [ #  # ]:          0 :         if (r < 0) {
    1102         [ #  # ]:          0 :                 log_debug_errno(r, "Failed to extract packet: %m");
    1103                 :          0 :                 return;
    1104                 :            :         }
    1105                 :            : 
    1106         [ #  # ]:          0 :         log_debug("Checking for conflicts...");
    1107                 :            : 
    1108   [ #  #  #  #  :          0 :         DNS_ANSWER_FOREACH(rr, p->answer) {
          #  #  #  #  #  
                      # ]
    1109                 :            :                 /* No conflict if it is DNS-SD RR used for service enumeration. */
    1110         [ #  # ]:          0 :                 if (dns_resource_key_is_dnssd_ptr(rr->key))
    1111                 :          0 :                         continue;
    1112                 :            : 
    1113                 :            :                 /* Check for conflicts against the local zone. If we
    1114                 :            :                  * found one, we won't check any further */
    1115                 :          0 :                 r = dns_zone_check_conflicts(&scope->zone, rr);
    1116         [ #  # ]:          0 :                 if (r != 0)
    1117                 :          0 :                         continue;
    1118                 :            : 
    1119                 :            :                 /* Check for conflicts against the local cache. If so,
    1120                 :            :                  * send out an advisory query, to inform everybody */
    1121                 :          0 :                 r = dns_cache_check_conflicts(&scope->cache, rr, p->family, &p->sender);
    1122         [ #  # ]:          0 :                 if (r <= 0)
    1123                 :          0 :                         continue;
    1124                 :            : 
    1125                 :          0 :                 dns_scope_notify_conflict(scope, rr);
    1126                 :            :         }
    1127                 :            : }
    1128                 :            : 
    1129                 :          0 : void dns_scope_dump(DnsScope *s, FILE *f) {
    1130         [ #  # ]:          0 :         assert(s);
    1131                 :            : 
    1132         [ #  # ]:          0 :         if (!f)
    1133                 :          0 :                 f = stdout;
    1134                 :            : 
    1135                 :          0 :         fputs("[Scope protocol=", f);
    1136                 :          0 :         fputs(dns_protocol_to_string(s->protocol), f);
    1137                 :            : 
    1138         [ #  # ]:          0 :         if (s->link) {
    1139                 :          0 :                 fputs(" interface=", f);
    1140                 :          0 :                 fputs(s->link->ifname, f);
    1141                 :            :         }
    1142                 :            : 
    1143         [ #  # ]:          0 :         if (s->family != AF_UNSPEC) {
    1144                 :          0 :                 fputs(" family=", f);
    1145                 :          0 :                 fputs(af_to_name(s->family), f);
    1146                 :            :         }
    1147                 :            : 
    1148                 :          0 :         fputs("]\n", f);
    1149                 :            : 
    1150         [ #  # ]:          0 :         if (!dns_zone_is_empty(&s->zone)) {
    1151                 :          0 :                 fputs("ZONE:\n", f);
    1152                 :          0 :                 dns_zone_dump(&s->zone, f);
    1153                 :            :         }
    1154                 :            : 
    1155         [ #  # ]:          0 :         if (!dns_cache_is_empty(&s->cache)) {
    1156                 :          0 :                 fputs("CACHE:\n", f);
    1157                 :          0 :                 dns_cache_dump(&s->cache, f);
    1158                 :            :         }
    1159                 :          0 : }
    1160                 :            : 
    1161                 :          0 : DnsSearchDomain *dns_scope_get_search_domains(DnsScope *s) {
    1162         [ #  # ]:          0 :         assert(s);
    1163                 :            : 
    1164         [ #  # ]:          0 :         if (s->protocol != DNS_PROTOCOL_DNS)
    1165                 :          0 :                 return NULL;
    1166                 :            : 
    1167         [ #  # ]:          0 :         if (s->link)
    1168                 :          0 :                 return s->link->search_domains;
    1169                 :            : 
    1170                 :          0 :         return s->manager->search_domains;
    1171                 :            : }
    1172                 :            : 
    1173                 :          0 : bool dns_scope_name_needs_search_domain(DnsScope *s, const char *name) {
    1174         [ #  # ]:          0 :         assert(s);
    1175                 :            : 
    1176         [ #  # ]:          0 :         if (s->protocol != DNS_PROTOCOL_DNS)
    1177                 :          0 :                 return false;
    1178                 :            : 
    1179                 :          0 :         return dns_name_is_single_label(name);
    1180                 :            : }
    1181                 :            : 
    1182                 :          0 : bool dns_scope_network_good(DnsScope *s) {
    1183                 :            :         /* Checks whether the network is in good state for lookups on this scope. For mDNS/LLMNR/Classic DNS scopes
    1184                 :            :          * bound to links this is easy, as they don't even exist if the link isn't in a suitable state. For the global
    1185                 :            :          * DNS scope we check whether there are any links that are up and have an address. */
    1186                 :            : 
    1187         [ #  # ]:          0 :         if (s->link)
    1188                 :          0 :                 return true;
    1189                 :            : 
    1190                 :          0 :         return manager_routable(s->manager, AF_UNSPEC);
    1191                 :            : }
    1192                 :            : 
    1193                 :          0 : int dns_scope_ifindex(DnsScope *s) {
    1194         [ #  # ]:          0 :         assert(s);
    1195                 :            : 
    1196         [ #  # ]:          0 :         if (s->link)
    1197                 :          0 :                 return s->link->ifindex;
    1198                 :            : 
    1199                 :          0 :         return 0;
    1200                 :            : }
    1201                 :            : 
    1202                 :          0 : static int on_announcement_timeout(sd_event_source *s, usec_t usec, void *userdata) {
    1203                 :          0 :         DnsScope *scope = userdata;
    1204                 :            : 
    1205         [ #  # ]:          0 :         assert(s);
    1206                 :            : 
    1207                 :          0 :         scope->announce_event_source = sd_event_source_unref(scope->announce_event_source);
    1208                 :            : 
    1209                 :          0 :         (void) dns_scope_announce(scope, false);
    1210                 :          0 :         return 0;
    1211                 :            : }
    1212                 :            : 
    1213                 :          0 : int dns_scope_announce(DnsScope *scope, bool goodbye) {
    1214                 :          0 :         _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
    1215                 :          0 :         _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
    1216                 :          0 :         _cleanup_set_free_ Set *types = NULL;
    1217                 :            :         DnsTransaction *t;
    1218                 :            :         DnsZoneItem *z, *i;
    1219                 :          0 :         unsigned size = 0;
    1220                 :            :         Iterator iterator;
    1221                 :            :         char *service_type;
    1222                 :            :         int r;
    1223                 :            : 
    1224         [ #  # ]:          0 :         if (!scope)
    1225                 :          0 :                 return 0;
    1226                 :            : 
    1227         [ #  # ]:          0 :         if (scope->protocol != DNS_PROTOCOL_MDNS)
    1228                 :          0 :                 return 0;
    1229                 :            : 
    1230                 :            :         /* Check if we're done with probing. */
    1231         [ #  # ]:          0 :         LIST_FOREACH(transactions_by_scope, t, scope->transactions)
    1232   [ #  #  #  # ]:          0 :                 if (DNS_TRANSACTION_IS_LIVE(t->state))
    1233                 :          0 :                         return 0;
    1234                 :            : 
    1235                 :            :         /* Check if there're services pending conflict resolution. */
    1236         [ #  # ]:          0 :         if (manager_next_dnssd_names(scope->manager))
    1237                 :          0 :                 return 0; /* we reach this point only if changing hostname didn't help */
    1238                 :            : 
    1239                 :            :         /* Calculate answer's size. */
    1240         [ #  # ]:          0 :         HASHMAP_FOREACH(z, scope->zone.by_key, iterator) {
    1241         [ #  # ]:          0 :                 if (z->state != DNS_ZONE_ITEM_ESTABLISHED)
    1242                 :          0 :                         continue;
    1243                 :            : 
    1244         [ #  # ]:          0 :                 if (z->rr->key->type == DNS_TYPE_PTR &&
    1245         [ #  # ]:          0 :                     !dns_zone_contains_name(&scope->zone, z->rr->ptr.name)) {
    1246                 :            :                         char key_str[DNS_RESOURCE_KEY_STRING_MAX];
    1247                 :            : 
    1248         [ #  # ]:          0 :                         log_debug("Skip PTR RR <%s> since its counterparts seem to be withdrawn", dns_resource_key_to_string(z->rr->key, key_str, sizeof key_str));
    1249                 :          0 :                         z->state = DNS_ZONE_ITEM_WITHDRAWN;
    1250                 :          0 :                         continue;
    1251                 :            :                 }
    1252                 :            : 
    1253                 :            :                 /* Collect service types for _services._dns-sd._udp.local RRs in a set */
    1254   [ #  #  #  # ]:          0 :                 if (!scope->announced &&
    1255                 :          0 :                     dns_resource_key_is_dnssd_ptr(z->rr->key)) {
    1256         [ #  # ]:          0 :                         if (!set_contains(types, dns_resource_key_name(z->rr->key))) {
    1257                 :          0 :                                 r = set_ensure_allocated(&types, &dns_name_hash_ops);
    1258         [ #  # ]:          0 :                                 if (r < 0)
    1259         [ #  # ]:          0 :                                         return log_debug_errno(r, "Failed to allocate set: %m");
    1260                 :            : 
    1261                 :          0 :                                 r = set_put(types, dns_resource_key_name(z->rr->key));
    1262         [ #  # ]:          0 :                                 if (r < 0)
    1263         [ #  # ]:          0 :                                         return log_debug_errno(r, "Failed to add item to set: %m");
    1264                 :            :                         }
    1265                 :            :                 }
    1266                 :            : 
    1267         [ #  # ]:          0 :                 LIST_FOREACH(by_key, i, z)
    1268                 :          0 :                         size++;
    1269                 :            :         }
    1270                 :            : 
    1271                 :          0 :         answer = dns_answer_new(size + set_size(types));
    1272         [ #  # ]:          0 :         if (!answer)
    1273                 :          0 :                 return log_oom();
    1274                 :            : 
    1275                 :            :         /* Second iteration, actually add RRs to the answer. */
    1276         [ #  # ]:          0 :         HASHMAP_FOREACH(z, scope->zone.by_key, iterator)
    1277         [ #  # ]:          0 :                 LIST_FOREACH (by_key, i, z) {
    1278                 :            :                         DnsAnswerFlags flags;
    1279                 :            : 
    1280         [ #  # ]:          0 :                         if (i->state != DNS_ZONE_ITEM_ESTABLISHED)
    1281                 :          0 :                                 continue;
    1282                 :            : 
    1283         [ #  # ]:          0 :                         if (dns_resource_key_is_dnssd_ptr(i->rr->key))
    1284         [ #  # ]:          0 :                                 flags = goodbye ? DNS_ANSWER_GOODBYE : 0;
    1285                 :            :                         else
    1286         [ #  # ]:          0 :                                 flags = goodbye ? (DNS_ANSWER_GOODBYE|DNS_ANSWER_CACHE_FLUSH) : DNS_ANSWER_CACHE_FLUSH;
    1287                 :            : 
    1288                 :          0 :                         r = dns_answer_add(answer, i->rr, 0 , flags);
    1289         [ #  # ]:          0 :                         if (r < 0)
    1290         [ #  # ]:          0 :                                 return log_debug_errno(r, "Failed to add RR to announce: %m");
    1291                 :            :                 }
    1292                 :            : 
    1293                 :            :         /* Since all the active services are in the zone make them discoverable now. */
    1294         [ #  # ]:          0 :         SET_FOREACH(service_type, types, iterator) {
    1295         [ #  # ]:          0 :                 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr;
    1296                 :            : 
    1297                 :          0 :                 rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_PTR,
    1298                 :            :                                                   "_services._dns-sd._udp.local");
    1299                 :          0 :                 rr->ptr.name = strdup(service_type);
    1300                 :          0 :                 rr->ttl = MDNS_DEFAULT_TTL;
    1301                 :            : 
    1302                 :          0 :                 r = dns_zone_put(&scope->zone, scope, rr, false);
    1303         [ #  # ]:          0 :                 if (r < 0)
    1304         [ #  # ]:          0 :                         log_warning_errno(r, "Failed to add DNS-SD PTR record to MDNS zone: %m");
    1305                 :            : 
    1306                 :          0 :                 r = dns_answer_add(answer, rr, 0 , 0);
    1307         [ #  # ]:          0 :                 if (r < 0)
    1308         [ #  # ]:          0 :                         return log_debug_errno(r, "Failed to add RR to announce: %m");
    1309                 :            :         }
    1310                 :            : 
    1311         [ #  # ]:          0 :         if (dns_answer_isempty(answer))
    1312                 :          0 :                 return 0;
    1313                 :            : 
    1314                 :          0 :         r = dns_scope_make_reply_packet(scope, 0, DNS_RCODE_SUCCESS, NULL, answer, NULL, false, &p);
    1315         [ #  # ]:          0 :         if (r < 0)
    1316         [ #  # ]:          0 :                 return log_debug_errno(r, "Failed to build reply packet: %m");
    1317                 :            : 
    1318                 :          0 :         r = dns_scope_emit_udp(scope, -1, p);
    1319         [ #  # ]:          0 :         if (r < 0)
    1320         [ #  # ]:          0 :                 return log_debug_errno(r, "Failed to send reply packet: %m");
    1321                 :            : 
    1322                 :            :         /* In section 8.3 of RFC6762: "The Multicast DNS responder MUST send at least two unsolicited
    1323                 :            :          * responses, one second apart." */
    1324         [ #  # ]:          0 :         if (!scope->announced) {
    1325                 :            :                 usec_t ts;
    1326                 :            : 
    1327                 :          0 :                 scope->announced = true;
    1328                 :            : 
    1329         [ #  # ]:          0 :                 assert_se(sd_event_now(scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
    1330                 :          0 :                 ts += MDNS_ANNOUNCE_DELAY;
    1331                 :            : 
    1332                 :          0 :                 r = sd_event_add_time(
    1333                 :          0 :                                 scope->manager->event,
    1334                 :            :                                 &scope->announce_event_source,
    1335                 :            :                                 clock_boottime_or_monotonic(),
    1336                 :            :                                 ts,
    1337                 :            :                                 MDNS_JITTER_RANGE_USEC,
    1338                 :            :                                 on_announcement_timeout, scope);
    1339         [ #  # ]:          0 :                 if (r < 0)
    1340         [ #  # ]:          0 :                         return log_debug_errno(r, "Failed to schedule second announcement: %m");
    1341                 :            : 
    1342                 :          0 :                 (void) sd_event_source_set_description(scope->announce_event_source, "mdns-announce");
    1343                 :            :         }
    1344                 :            : 
    1345                 :          0 :         return 0;
    1346                 :            : }
    1347                 :            : 
    1348                 :          0 : int dns_scope_add_dnssd_services(DnsScope *scope) {
    1349                 :            :         Iterator i;
    1350                 :            :         DnssdService *service;
    1351                 :            :         DnssdTxtData *txt_data;
    1352                 :            :         int r;
    1353                 :            : 
    1354         [ #  # ]:          0 :         assert(scope);
    1355                 :            : 
    1356         [ #  # ]:          0 :         if (hashmap_size(scope->manager->dnssd_services) == 0)
    1357                 :          0 :                 return 0;
    1358                 :            : 
    1359                 :          0 :         scope->announced = false;
    1360                 :            : 
    1361         [ #  # ]:          0 :         HASHMAP_FOREACH(service, scope->manager->dnssd_services, i) {
    1362                 :          0 :                 service->withdrawn = false;
    1363                 :            : 
    1364                 :          0 :                 r = dns_zone_put(&scope->zone, scope, service->ptr_rr, false);
    1365         [ #  # ]:          0 :                 if (r < 0)
    1366         [ #  # ]:          0 :                         log_warning_errno(r, "Failed to add PTR record to MDNS zone: %m");
    1367                 :            : 
    1368                 :          0 :                 r = dns_zone_put(&scope->zone, scope, service->srv_rr, true);
    1369         [ #  # ]:          0 :                 if (r < 0)
    1370         [ #  # ]:          0 :                         log_warning_errno(r, "Failed to add SRV record to MDNS zone: %m");
    1371                 :            : 
    1372         [ #  # ]:          0 :                 LIST_FOREACH(items, txt_data, service->txt_data_items) {
    1373                 :          0 :                         r = dns_zone_put(&scope->zone, scope, txt_data->rr, true);
    1374         [ #  # ]:          0 :                         if (r < 0)
    1375         [ #  # ]:          0 :                                 log_warning_errno(r, "Failed to add TXT record to MDNS zone: %m");
    1376                 :            :                 }
    1377                 :            :         }
    1378                 :            : 
    1379                 :          0 :         return 0;
    1380                 :            : }
    1381                 :            : 
    1382                 :          0 : int dns_scope_remove_dnssd_services(DnsScope *scope) {
    1383                 :          0 :         _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
    1384                 :            :         Iterator i;
    1385                 :            :         DnssdService *service;
    1386                 :            :         DnssdTxtData *txt_data;
    1387                 :            :         int r;
    1388                 :            : 
    1389         [ #  # ]:          0 :         assert(scope);
    1390                 :            : 
    1391                 :          0 :         key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_PTR,
    1392                 :            :                                    "_services._dns-sd._udp.local");
    1393         [ #  # ]:          0 :         if (!key)
    1394                 :          0 :                 return log_oom();
    1395                 :            : 
    1396                 :          0 :         r = dns_zone_remove_rrs_by_key(&scope->zone, key);
    1397         [ #  # ]:          0 :         if (r < 0)
    1398                 :          0 :                 return r;
    1399                 :            : 
    1400         [ #  # ]:          0 :         HASHMAP_FOREACH(service, scope->manager->dnssd_services, i) {
    1401                 :          0 :                 dns_zone_remove_rr(&scope->zone, service->ptr_rr);
    1402                 :          0 :                 dns_zone_remove_rr(&scope->zone, service->srv_rr);
    1403         [ #  # ]:          0 :                 LIST_FOREACH(items, txt_data, service->txt_data_items)
    1404                 :          0 :                         dns_zone_remove_rr(&scope->zone, txt_data->rr);
    1405                 :            :         }
    1406                 :            : 
    1407                 :          0 :         return 0;
    1408                 :            : }
    1409                 :            : 
    1410                 :          0 : static bool dns_scope_has_route_only_domains(DnsScope *scope) {
    1411                 :            :         DnsSearchDomain *domain, *first;
    1412                 :          0 :         bool route_only = false;
    1413                 :            : 
    1414         [ #  # ]:          0 :         assert(scope);
    1415         [ #  # ]:          0 :         assert(scope->protocol == DNS_PROTOCOL_DNS);
    1416                 :            : 
    1417                 :            :         /* Returns 'true' if this scope is suitable for queries to specific domains only. For that we check
    1418                 :            :          * if there are any route-only domains on this interface, as a heuristic to discern VPN-style links
    1419                 :            :          * from non-VPN-style links. Returns 'false' for all other cases, i.e. if the scope is intended to
    1420                 :            :          * take queries to arbitrary domains, i.e. has no routing domains set. */
    1421                 :            : 
    1422         [ #  # ]:          0 :         if (scope->link)
    1423                 :          0 :                 first = scope->link->search_domains;
    1424                 :            :         else
    1425                 :          0 :                 first = scope->manager->search_domains;
    1426                 :            : 
    1427         [ #  # ]:          0 :         LIST_FOREACH(domains, domain, first) {
    1428                 :            :                 /* "." means "any domain", thus the interface takes any kind of traffic. Thus, we exit early
    1429                 :            :                  * here, as it doesn't really matter whether this link has any route-only domains or not,
    1430                 :            :                  * "~."  really trumps everything and clearly indicates that this interface shall receive all
    1431                 :            :                  * traffic it can get. */
    1432         [ #  # ]:          0 :                 if (dns_name_is_root(DNS_SEARCH_DOMAIN_NAME(domain)))
    1433                 :          0 :                         return false;
    1434                 :            : 
    1435         [ #  # ]:          0 :                 if (domain->route_only)
    1436                 :          0 :                         route_only = true;
    1437                 :            :         }
    1438                 :            : 
    1439                 :          0 :         return route_only;
    1440                 :            : }
    1441                 :            : 
    1442                 :          0 : bool dns_scope_is_default_route(DnsScope *scope) {
    1443         [ #  # ]:          0 :         assert(scope);
    1444                 :            : 
    1445                 :            :         /* Only use DNS scopes as default routes */
    1446         [ #  # ]:          0 :         if (scope->protocol != DNS_PROTOCOL_DNS)
    1447                 :          0 :                 return false;
    1448                 :            : 
    1449                 :            :         /* The global DNS scope is always suitable as default route */
    1450         [ #  # ]:          0 :         if (!scope->link)
    1451                 :          0 :                 return true;
    1452                 :            : 
    1453                 :            :         /* Honour whatever is explicitly configured. This is really the best approach, and trumps any
    1454                 :            :          * automatic logic. */
    1455         [ #  # ]:          0 :         if (scope->link->default_route >= 0)
    1456                 :          0 :                 return scope->link->default_route;
    1457                 :            : 
    1458                 :            :         /* Otherwise check if we have any route-only domains, as a sensible heuristic: if so, let's not
    1459                 :            :          * volunteer as default route. */
    1460                 :          0 :         return !dns_scope_has_route_only_domains(scope);
    1461                 :            : }

Generated by: LCOV version 1.14