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

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <netinet/in.h>
       4                 :            : #include <resolv.h>
       5                 :            : 
       6                 :            : #include "errno-util.h"
       7                 :            : #include "fd-util.h"
       8                 :            : #include "resolved-llmnr.h"
       9                 :            : #include "resolved-manager.h"
      10                 :            : 
      11                 :          0 : void manager_llmnr_stop(Manager *m) {
      12         [ #  # ]:          0 :         assert(m);
      13                 :            : 
      14                 :          0 :         m->llmnr_ipv4_udp_event_source = sd_event_source_unref(m->llmnr_ipv4_udp_event_source);
      15                 :          0 :         m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd);
      16                 :            : 
      17                 :          0 :         m->llmnr_ipv6_udp_event_source = sd_event_source_unref(m->llmnr_ipv6_udp_event_source);
      18                 :          0 :         m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd);
      19                 :            : 
      20                 :          0 :         m->llmnr_ipv4_tcp_event_source = sd_event_source_unref(m->llmnr_ipv4_tcp_event_source);
      21                 :          0 :         m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd);
      22                 :            : 
      23                 :          0 :         m->llmnr_ipv6_tcp_event_source = sd_event_source_unref(m->llmnr_ipv6_tcp_event_source);
      24                 :          0 :         m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd);
      25                 :          0 : }
      26                 :            : 
      27                 :          0 : int manager_llmnr_start(Manager *m) {
      28                 :            :         int r;
      29                 :            : 
      30         [ #  # ]:          0 :         assert(m);
      31                 :            : 
      32         [ #  # ]:          0 :         if (m->llmnr_support == RESOLVE_SUPPORT_NO)
      33                 :          0 :                 return 0;
      34                 :            : 
      35                 :          0 :         r = manager_llmnr_ipv4_udp_fd(m);
      36         [ #  # ]:          0 :         if (r == -EADDRINUSE)
      37                 :          0 :                 goto eaddrinuse;
      38         [ #  # ]:          0 :         if (r < 0)
      39                 :          0 :                 return r;
      40                 :            : 
      41                 :          0 :         r = manager_llmnr_ipv4_tcp_fd(m);
      42         [ #  # ]:          0 :         if (r == -EADDRINUSE)
      43                 :          0 :                 goto eaddrinuse;
      44         [ #  # ]:          0 :         if (r < 0)
      45                 :          0 :                 return r;
      46                 :            : 
      47         [ #  # ]:          0 :         if (socket_ipv6_is_supported()) {
      48                 :          0 :                 r = manager_llmnr_ipv6_udp_fd(m);
      49         [ #  # ]:          0 :                 if (r == -EADDRINUSE)
      50                 :          0 :                         goto eaddrinuse;
      51         [ #  # ]:          0 :                 if (r < 0)
      52                 :          0 :                         return r;
      53                 :            : 
      54                 :          0 :                 r = manager_llmnr_ipv6_tcp_fd(m);
      55         [ #  # ]:          0 :                 if (r == -EADDRINUSE)
      56                 :          0 :                         goto eaddrinuse;
      57         [ #  # ]:          0 :                 if (r < 0)
      58                 :          0 :                         return r;
      59                 :            :         }
      60                 :            : 
      61                 :          0 :         return 0;
      62                 :            : 
      63                 :          0 : eaddrinuse:
      64         [ #  # ]:          0 :         log_warning("Another LLMNR responder prohibits binding the socket to the same port. Turning off LLMNR support.");
      65                 :          0 :         m->llmnr_support = RESOLVE_SUPPORT_NO;
      66                 :          0 :         manager_llmnr_stop(m);
      67                 :            : 
      68                 :          0 :         return 0;
      69                 :            : }
      70                 :            : 
      71                 :          0 : static int on_llmnr_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
      72                 :          0 :         _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
      73                 :          0 :         DnsTransaction *t = NULL;
      74                 :          0 :         Manager *m = userdata;
      75                 :            :         DnsScope *scope;
      76                 :            :         int r;
      77                 :            : 
      78         [ #  # ]:          0 :         assert(s);
      79         [ #  # ]:          0 :         assert(fd >= 0);
      80         [ #  # ]:          0 :         assert(m);
      81                 :            : 
      82                 :          0 :         r = manager_recv(m, fd, DNS_PROTOCOL_LLMNR, &p);
      83         [ #  # ]:          0 :         if (r <= 0)
      84                 :          0 :                 return r;
      85                 :            : 
      86         [ #  # ]:          0 :         if (manager_our_packet(m, p))
      87                 :          0 :                 return 0;
      88                 :            : 
      89                 :          0 :         scope = manager_find_scope(m, p);
      90         [ #  # ]:          0 :         if (!scope) {
      91         [ #  # ]:          0 :                 log_debug("Got LLMNR UDP packet on unknown scope. Ignoring.");
      92                 :          0 :                 return 0;
      93                 :            :         }
      94                 :            : 
      95         [ #  # ]:          0 :         if (dns_packet_validate_reply(p) > 0) {
      96         [ #  # ]:          0 :                 log_debug("Got LLMNR UDP reply packet for id %u", DNS_PACKET_ID(p));
      97                 :            : 
      98                 :          0 :                 dns_scope_check_conflicts(scope, p);
      99                 :            : 
     100                 :          0 :                 t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
     101         [ #  # ]:          0 :                 if (t)
     102                 :          0 :                         dns_transaction_process_reply(t, p);
     103                 :            : 
     104         [ #  # ]:          0 :         } else if (dns_packet_validate_query(p) > 0)  {
     105         [ #  # ]:          0 :                 log_debug("Got LLMNR UDP query packet for id %u", DNS_PACKET_ID(p));
     106                 :            : 
     107                 :          0 :                 dns_scope_process_query(scope, NULL, p);
     108                 :            :         } else
     109         [ #  # ]:          0 :                 log_debug("Invalid LLMNR UDP packet, ignoring.");
     110                 :            : 
     111                 :          0 :         return 0;
     112                 :            : }
     113                 :            : 
     114                 :          0 : int manager_llmnr_ipv4_udp_fd(Manager *m) {
     115                 :          0 :         union sockaddr_union sa = {
     116                 :            :                 .in.sin_family = AF_INET,
     117                 :          0 :                 .in.sin_port = htobe16(LLMNR_PORT),
     118                 :            :         };
     119                 :          0 :         _cleanup_close_ int s = -1;
     120                 :            :         int r;
     121                 :            : 
     122         [ #  # ]:          0 :         assert(m);
     123                 :            : 
     124         [ #  # ]:          0 :         if (m->llmnr_ipv4_udp_fd >= 0)
     125                 :          0 :                 return m->llmnr_ipv4_udp_fd;
     126                 :            : 
     127                 :          0 :         s = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
     128         [ #  # ]:          0 :         if (s < 0)
     129         [ #  # ]:          0 :                 return log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to create socket: %m");
     130                 :            : 
     131                 :            :         /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
     132                 :          0 :         r = setsockopt_int(s, IPPROTO_IP, IP_TTL, 255);
     133         [ #  # ]:          0 :         if (r < 0)
     134         [ #  # ]:          0 :                 return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set IP_TTL: %m");
     135                 :            : 
     136                 :          0 :         r = setsockopt_int(s, IPPROTO_IP, IP_MULTICAST_TTL, 255);
     137         [ #  # ]:          0 :         if (r < 0)
     138         [ #  # ]:          0 :                 return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set IP_MULTICAST_TTL: %m");
     139                 :            : 
     140                 :          0 :         r = setsockopt_int(s, IPPROTO_IP, IP_MULTICAST_LOOP, true);
     141         [ #  # ]:          0 :         if (r < 0)
     142         [ #  # ]:          0 :                 return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set IP_MULTICAST_LOOP: %m");
     143                 :            : 
     144                 :          0 :         r = setsockopt_int(s, IPPROTO_IP, IP_PKTINFO, true);
     145         [ #  # ]:          0 :         if (r < 0)
     146         [ #  # ]:          0 :                 return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set IP_PKTINFO: %m");
     147                 :            : 
     148                 :          0 :         r = setsockopt_int(s, IPPROTO_IP, IP_RECVTTL, true);
     149         [ #  # ]:          0 :         if (r < 0)
     150         [ #  # ]:          0 :                 return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set IP_RECVTTL: %m");
     151                 :            : 
     152                 :            :         /* Disable Don't-Fragment bit in the IP header */
     153                 :          0 :         r = setsockopt_int(s, IPPROTO_IP, IP_MTU_DISCOVER, IP_PMTUDISC_DONT);
     154         [ #  # ]:          0 :         if (r < 0)
     155         [ #  # ]:          0 :                 return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set IP_MTU_DISCOVER: %m");
     156                 :            : 
     157                 :            :         /* first try to bind without SO_REUSEADDR to detect another LLMNR responder */
     158                 :          0 :         r = bind(s, &sa.sa, sizeof(sa.in));
     159         [ #  # ]:          0 :         if (r < 0) {
     160         [ #  # ]:          0 :                 if (errno != EADDRINUSE)
     161         [ #  # ]:          0 :                         return log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to bind socket: %m");
     162                 :            : 
     163         [ #  # ]:          0 :                 log_warning("LLMNR-IPv4(UDP): There appears to be another LLMNR responder running, or previously systemd-resolved crashed with some outstanding transfers.");
     164                 :            : 
     165                 :            :                 /* try again with SO_REUSEADDR */
     166                 :          0 :                 r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true);
     167         [ #  # ]:          0 :                 if (r < 0)
     168         [ #  # ]:          0 :                         return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set SO_REUSEADDR: %m");
     169                 :            : 
     170                 :          0 :                 r = bind(s, &sa.sa, sizeof(sa.in));
     171         [ #  # ]:          0 :                 if (r < 0)
     172         [ #  # ]:          0 :                         return log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to bind socket: %m");
     173                 :            :         } else {
     174                 :            :                 /* enable SO_REUSEADDR for the case that the user really wants multiple LLMNR responders */
     175                 :          0 :                 r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true);
     176         [ #  # ]:          0 :                 if (r < 0)
     177         [ #  # ]:          0 :                         return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set SO_REUSEADDR: %m");
     178                 :            :         }
     179                 :            : 
     180                 :          0 :         r = sd_event_add_io(m->event, &m->llmnr_ipv4_udp_event_source, s, EPOLLIN, on_llmnr_packet, m);
     181         [ #  # ]:          0 :         if (r < 0)
     182         [ #  # ]:          0 :                 return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to create event source: %m");
     183                 :            : 
     184                 :          0 :         (void) sd_event_source_set_description(m->llmnr_ipv4_udp_event_source, "llmnr-ipv4-udp");
     185                 :            : 
     186                 :          0 :         return m->llmnr_ipv4_udp_fd = TAKE_FD(s);
     187                 :            : }
     188                 :            : 
     189                 :          0 : int manager_llmnr_ipv6_udp_fd(Manager *m) {
     190                 :          0 :         union sockaddr_union sa = {
     191                 :            :                 .in6.sin6_family = AF_INET6,
     192                 :          0 :                 .in6.sin6_port = htobe16(LLMNR_PORT),
     193                 :            :         };
     194                 :          0 :         _cleanup_close_ int s = -1;
     195                 :            :         int r;
     196                 :            : 
     197         [ #  # ]:          0 :         assert(m);
     198                 :            : 
     199         [ #  # ]:          0 :         if (m->llmnr_ipv6_udp_fd >= 0)
     200                 :          0 :                 return m->llmnr_ipv6_udp_fd;
     201                 :            : 
     202                 :          0 :         s = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
     203         [ #  # ]:          0 :         if (s < 0)
     204         [ #  # ]:          0 :                 return log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to create socket: %m");
     205                 :            : 
     206                 :          0 :         r = setsockopt_int(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 255);
     207         [ #  # ]:          0 :         if (r < 0)
     208         [ #  # ]:          0 :                 return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set IPV6_UNICAST_HOPS: %m");
     209                 :            : 
     210                 :            :         /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
     211                 :          0 :         r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 255);
     212         [ #  # ]:          0 :         if (r < 0)
     213         [ #  # ]:          0 :                 return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set IPV6_MULTICAST_HOPS: %m");
     214                 :            : 
     215                 :          0 :         r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, true);
     216         [ #  # ]:          0 :         if (r < 0)
     217         [ #  # ]:          0 :                 return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set IPV6_MULTICAST_LOOP: %m");
     218                 :            : 
     219                 :          0 :         r = setsockopt_int(s, IPPROTO_IPV6, IPV6_V6ONLY, true);
     220         [ #  # ]:          0 :         if (r < 0)
     221         [ #  # ]:          0 :                 return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set IPV6_V6ONLY: %m");
     222                 :            : 
     223                 :          0 :         r = setsockopt_int(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, true);
     224         [ #  # ]:          0 :         if (r < 0)
     225         [ #  # ]:          0 :                 return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set IPV6_RECVPKTINFO: %m");
     226                 :            : 
     227                 :          0 :         r = setsockopt_int(s, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, true);
     228         [ #  # ]:          0 :         if (r < 0)
     229         [ #  # ]:          0 :                 return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set IPV6_RECVHOPLIMIT: %m");
     230                 :            : 
     231                 :            :         /* first try to bind without SO_REUSEADDR to detect another LLMNR responder */
     232                 :          0 :         r = bind(s, &sa.sa, sizeof(sa.in6));
     233         [ #  # ]:          0 :         if (r < 0) {
     234         [ #  # ]:          0 :                 if (errno != EADDRINUSE)
     235         [ #  # ]:          0 :                         return log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to bind socket: %m");
     236                 :            : 
     237         [ #  # ]:          0 :                 log_warning("LLMNR-IPv6(UDP): There appears to be another LLMNR responder running, or previously systemd-resolved crashed with some outstanding transfers.");
     238                 :            : 
     239                 :            :                 /* try again with SO_REUSEADDR */
     240                 :          0 :                 r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true);
     241         [ #  # ]:          0 :                 if (r < 0)
     242         [ #  # ]:          0 :                         return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set SO_REUSEADDR: %m");
     243                 :            : 
     244                 :          0 :                 r = bind(s, &sa.sa, sizeof(sa.in6));
     245         [ #  # ]:          0 :                 if (r < 0)
     246         [ #  # ]:          0 :                         return log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to bind socket: %m");
     247                 :            :         } else {
     248                 :            :                 /* enable SO_REUSEADDR for the case that the user really wants multiple LLMNR responders */
     249                 :          0 :                 r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true);
     250         [ #  # ]:          0 :                 if (r < 0)
     251         [ #  # ]:          0 :                         return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set SO_REUSEADDR: %m");
     252                 :            :         }
     253                 :            : 
     254                 :          0 :         r = sd_event_add_io(m->event, &m->llmnr_ipv6_udp_event_source, s, EPOLLIN, on_llmnr_packet, m);
     255         [ #  # ]:          0 :         if (r < 0)
     256         [ #  # ]:          0 :                 return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to create event source: %m");
     257                 :            : 
     258                 :          0 :         (void) sd_event_source_set_description(m->llmnr_ipv6_udp_event_source, "llmnr-ipv6-udp");
     259                 :            : 
     260                 :          0 :         return m->llmnr_ipv6_udp_fd = TAKE_FD(s);
     261                 :            : }
     262                 :            : 
     263                 :          0 : static int on_llmnr_stream_packet(DnsStream *s) {
     264                 :          0 :         _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
     265                 :            :         DnsScope *scope;
     266                 :            : 
     267         [ #  # ]:          0 :         assert(s);
     268                 :            : 
     269                 :          0 :         p = dns_stream_take_read_packet(s);
     270         [ #  # ]:          0 :         assert(p);
     271                 :            : 
     272                 :          0 :         scope = manager_find_scope(s->manager, p);
     273         [ #  # ]:          0 :         if (!scope)
     274         [ #  # ]:          0 :                 log_debug("Got LLMNR TCP packet on unknown scope. Ignoring.");
     275         [ #  # ]:          0 :         else if (dns_packet_validate_query(p) > 0) {
     276         [ #  # ]:          0 :                 log_debug("Got LLMNR TCP query packet for id %u", DNS_PACKET_ID(p));
     277                 :            : 
     278                 :          0 :                 dns_scope_process_query(scope, s, p);
     279                 :            :         } else
     280         [ #  # ]:          0 :                 log_debug("Invalid LLMNR TCP packet, ignoring.");
     281                 :            : 
     282                 :          0 :         dns_stream_unref(s);
     283                 :          0 :         return 0;
     284                 :            : }
     285                 :            : 
     286                 :          0 : static int on_llmnr_stream(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
     287                 :            :         DnsStream *stream;
     288                 :          0 :         Manager *m = userdata;
     289                 :            :         int cfd, r;
     290                 :            : 
     291                 :          0 :         cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
     292         [ #  # ]:          0 :         if (cfd < 0) {
     293         [ #  # ]:          0 :                 if (ERRNO_IS_ACCEPT_AGAIN(errno))
     294                 :          0 :                         return 0;
     295                 :            : 
     296                 :          0 :                 return -errno;
     297                 :            :         }
     298                 :            : 
     299                 :          0 :         r = dns_stream_new(m, &stream, DNS_STREAM_LLMNR_RECV, DNS_PROTOCOL_LLMNR, cfd, NULL);
     300         [ #  # ]:          0 :         if (r < 0) {
     301                 :          0 :                 safe_close(cfd);
     302                 :          0 :                 return r;
     303                 :            :         }
     304                 :            : 
     305                 :          0 :         stream->on_packet = on_llmnr_stream_packet;
     306                 :            :         /* We don't configure a "complete" handler here, we rely on the default handler than simply drops the
     307                 :            :          * reference to the stream, thus freeing it */
     308                 :          0 :         return 0;
     309                 :            : }
     310                 :            : 
     311                 :          0 : int manager_llmnr_ipv4_tcp_fd(Manager *m) {
     312                 :          0 :         union sockaddr_union sa = {
     313                 :            :                 .in.sin_family = AF_INET,
     314                 :          0 :                 .in.sin_port = htobe16(LLMNR_PORT),
     315                 :            :         };
     316                 :          0 :         _cleanup_close_ int s = -1;
     317                 :            :         int r;
     318                 :            : 
     319         [ #  # ]:          0 :         assert(m);
     320                 :            : 
     321         [ #  # ]:          0 :         if (m->llmnr_ipv4_tcp_fd >= 0)
     322                 :          0 :                 return m->llmnr_ipv4_tcp_fd;
     323                 :            : 
     324                 :          0 :         s = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
     325         [ #  # ]:          0 :         if (s < 0)
     326         [ #  # ]:          0 :                 return log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to create socket: %m");
     327                 :            : 
     328                 :            :         /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */
     329                 :          0 :         r = setsockopt_int(s, IPPROTO_IP, IP_TTL, true);
     330         [ #  # ]:          0 :         if (r < 0)
     331         [ #  # ]:          0 :                 return log_error_errno(r, "LLMNR-IPv4(TCP): Failed to set IP_TTL: %m");
     332                 :            : 
     333                 :          0 :         r = setsockopt_int(s, IPPROTO_IP, IP_PKTINFO, true);
     334         [ #  # ]:          0 :         if (r < 0)
     335         [ #  # ]:          0 :                 return log_error_errno(r, "LLMNR-IPv4(TCP): Failed to set IP_PKTINFO: %m");
     336                 :            : 
     337                 :          0 :         r = setsockopt_int(s, IPPROTO_IP, IP_RECVTTL, true);
     338         [ #  # ]:          0 :         if (r < 0)
     339         [ #  # ]:          0 :                 return log_error_errno(r, "LLMNR-IPv4(TCP): Failed to set IP_RECVTTL: %m");
     340                 :            : 
     341                 :            :         /* Disable Don't-Fragment bit in the IP header */
     342                 :          0 :         r = setsockopt_int(s, IPPROTO_IP, IP_MTU_DISCOVER, IP_PMTUDISC_DONT);
     343         [ #  # ]:          0 :         if (r < 0)
     344         [ #  # ]:          0 :                 return log_error_errno(r, "LLMNR-IPv4(TCP): Failed to set IP_MTU_DISCOVER: %m");
     345                 :            : 
     346                 :            :         /* first try to bind without SO_REUSEADDR to detect another LLMNR responder */
     347                 :          0 :         r = bind(s, &sa.sa, sizeof(sa.in));
     348         [ #  # ]:          0 :         if (r < 0) {
     349         [ #  # ]:          0 :                 if (errno != EADDRINUSE)
     350         [ #  # ]:          0 :                         return log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to bind socket: %m");
     351                 :            : 
     352         [ #  # ]:          0 :                 log_warning("LLMNR-IPv4(TCP): There appears to be another LLMNR responder running, or previously systemd-resolved crashed with some outstanding transfers.");
     353                 :            : 
     354                 :            :                 /* try again with SO_REUSEADDR */
     355                 :          0 :                 r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true);
     356         [ #  # ]:          0 :                 if (r < 0)
     357         [ #  # ]:          0 :                         return log_error_errno(r, "LLMNR-IPv4(TCP): Failed to set SO_REUSEADDR: %m");
     358                 :            : 
     359                 :          0 :                 r = bind(s, &sa.sa, sizeof(sa.in));
     360         [ #  # ]:          0 :                 if (r < 0)
     361         [ #  # ]:          0 :                         return log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to bind socket: %m");
     362                 :            :         } else {
     363                 :            :                 /* enable SO_REUSEADDR for the case that the user really wants multiple LLMNR responders */
     364                 :          0 :                 r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true);
     365         [ #  # ]:          0 :                 if (r < 0)
     366         [ #  # ]:          0 :                         return log_error_errno(r, "LLMNR-IPv4(TCP): Failed to set SO_REUSEADDR: %m");
     367                 :            :         }
     368                 :            : 
     369                 :          0 :         r = listen(s, SOMAXCONN);
     370         [ #  # ]:          0 :         if (r < 0)
     371         [ #  # ]:          0 :                 return log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to listen the stream: %m");
     372                 :            : 
     373                 :          0 :         r = sd_event_add_io(m->event, &m->llmnr_ipv4_tcp_event_source, s, EPOLLIN, on_llmnr_stream, m);
     374         [ #  # ]:          0 :         if (r < 0)
     375         [ #  # ]:          0 :                 return log_error_errno(r, "LLMNR-IPv4(TCP): Failed to create event source: %m");
     376                 :            : 
     377                 :          0 :         (void) sd_event_source_set_description(m->llmnr_ipv4_tcp_event_source, "llmnr-ipv4-tcp");
     378                 :            : 
     379                 :          0 :         return m->llmnr_ipv4_tcp_fd = TAKE_FD(s);
     380                 :            : }
     381                 :            : 
     382                 :          0 : int manager_llmnr_ipv6_tcp_fd(Manager *m) {
     383                 :          0 :         union sockaddr_union sa = {
     384                 :            :                 .in6.sin6_family = AF_INET6,
     385                 :          0 :                 .in6.sin6_port = htobe16(LLMNR_PORT),
     386                 :            :         };
     387                 :          0 :         _cleanup_close_ int s = -1;
     388                 :            :         int r;
     389                 :            : 
     390         [ #  # ]:          0 :         assert(m);
     391                 :            : 
     392         [ #  # ]:          0 :         if (m->llmnr_ipv6_tcp_fd >= 0)
     393                 :          0 :                 return m->llmnr_ipv6_tcp_fd;
     394                 :            : 
     395                 :          0 :         s = socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
     396         [ #  # ]:          0 :         if (s < 0)
     397         [ #  # ]:          0 :                 return log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to create socket: %m");
     398                 :            : 
     399                 :            :         /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */
     400                 :          0 :         r = setsockopt_int(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, true);
     401         [ #  # ]:          0 :         if (r < 0)
     402         [ #  # ]:          0 :                 return log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set IPV6_UNICAST_HOPS: %m");
     403                 :            : 
     404                 :          0 :         r = setsockopt_int(s, IPPROTO_IPV6, IPV6_V6ONLY, true);
     405         [ #  # ]:          0 :         if (r < 0)
     406         [ #  # ]:          0 :                 return log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set IPV6_V6ONLY: %m");
     407                 :            : 
     408                 :          0 :         r = setsockopt_int(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, true);
     409         [ #  # ]:          0 :         if (r < 0)
     410         [ #  # ]:          0 :                 return log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set IPV6_RECVPKTINFO: %m");
     411                 :            : 
     412                 :          0 :         r = setsockopt_int(s, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, true);
     413         [ #  # ]:          0 :         if (r < 0)
     414         [ #  # ]:          0 :                 return log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set IPV6_RECVHOPLIMIT: %m");
     415                 :            : 
     416                 :            :         /* first try to bind without SO_REUSEADDR to detect another LLMNR responder */
     417                 :          0 :         r = bind(s, &sa.sa, sizeof(sa.in6));
     418         [ #  # ]:          0 :         if (r < 0) {
     419         [ #  # ]:          0 :                 if (errno != EADDRINUSE)
     420         [ #  # ]:          0 :                         return log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to bind socket: %m");
     421                 :            : 
     422         [ #  # ]:          0 :                 log_warning("LLMNR-IPv6(TCP): There appears to be another LLMNR responder running, or previously systemd-resolved crashed with some outstanding transfers.");
     423                 :            : 
     424                 :            :                 /* try again with SO_REUSEADDR */
     425                 :          0 :                 r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true);
     426         [ #  # ]:          0 :                 if (r < 0)
     427         [ #  # ]:          0 :                         return log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set SO_REUSEADDR: %m");
     428                 :            : 
     429                 :          0 :                 r = bind(s, &sa.sa, sizeof(sa.in6));
     430         [ #  # ]:          0 :                 if (r < 0)
     431         [ #  # ]:          0 :                         return log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to bind socket: %m");
     432                 :            :         } else {
     433                 :            :                 /* enable SO_REUSEADDR for the case that the user really wants multiple LLMNR responders */
     434                 :          0 :                 r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true);
     435         [ #  # ]:          0 :                 if (r < 0)
     436         [ #  # ]:          0 :                         return log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set SO_REUSEADDR: %m");
     437                 :            :         }
     438                 :            : 
     439                 :          0 :         r = listen(s, SOMAXCONN);
     440         [ #  # ]:          0 :         if (r < 0)
     441         [ #  # ]:          0 :                 return log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to listen the stream: %m");
     442                 :            : 
     443                 :          0 :         r = sd_event_add_io(m->event, &m->llmnr_ipv6_tcp_event_source, s, EPOLLIN, on_llmnr_stream, m);
     444         [ #  # ]:          0 :         if (r < 0)
     445         [ #  # ]:          0 :                 return log_error_errno(r, "LLMNR-IPv6(TCP): Failed to create event source: %m");
     446                 :            : 
     447                 :          0 :         (void) sd_event_source_set_description(m->llmnr_ipv6_tcp_event_source, "llmnr-ipv6-tcp");
     448                 :            : 
     449                 :          0 :         return m->llmnr_ipv6_tcp_fd = TAKE_FD(s);
     450                 :            : }

Generated by: LCOV version 1.14