LCOV - code coverage report
Current view: top level - libsystemd/sd-resolve - sd-resolve.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 451 600 75.2 %
Date: 2019-08-23 13:36:53 Functions: 34 48 70.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 261 568 46.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <errno.h>
       4                 :            : #include <poll.h>
       5                 :            : #include <pthread.h>
       6                 :            : #include <resolv.h>
       7                 :            : #include <signal.h>
       8                 :            : #include <stdint.h>
       9                 :            : #include <stdio.h>
      10                 :            : #include <stdlib.h>
      11                 :            : #include <string.h>
      12                 :            : #include <sys/prctl.h>
      13                 :            : #include <unistd.h>
      14                 :            : 
      15                 :            : #include "sd-resolve.h"
      16                 :            : 
      17                 :            : #include "alloc-util.h"
      18                 :            : #include "dns-domain.h"
      19                 :            : #include "errno-util.h"
      20                 :            : #include "fd-util.h"
      21                 :            : #include "io-util.h"
      22                 :            : #include "list.h"
      23                 :            : #include "memory-util.h"
      24                 :            : #include "missing.h"
      25                 :            : #include "process-util.h"
      26                 :            : #include "resolve-private.h"
      27                 :            : #include "socket-util.h"
      28                 :            : 
      29                 :            : #define WORKERS_MIN 1U
      30                 :            : #define WORKERS_MAX 16U
      31                 :            : #define QUERIES_MAX 256U
      32                 :            : #define BUFSIZE 10240U
      33                 :            : 
      34                 :            : typedef enum {
      35                 :            :         REQUEST_ADDRINFO,
      36                 :            :         RESPONSE_ADDRINFO,
      37                 :            :         REQUEST_NAMEINFO,
      38                 :            :         RESPONSE_NAMEINFO,
      39                 :            :         REQUEST_TERMINATE,
      40                 :            :         RESPONSE_DIED
      41                 :            : } QueryType;
      42                 :            : 
      43                 :            : enum {
      44                 :            :         REQUEST_RECV_FD,
      45                 :            :         REQUEST_SEND_FD,
      46                 :            :         RESPONSE_RECV_FD,
      47                 :            :         RESPONSE_SEND_FD,
      48                 :            :         _FD_MAX
      49                 :            : };
      50                 :            : 
      51                 :            : struct sd_resolve {
      52                 :            :         unsigned n_ref;
      53                 :            : 
      54                 :            :         bool dead:1;
      55                 :            :         pid_t original_pid;
      56                 :            : 
      57                 :            :         int fds[_FD_MAX];
      58                 :            : 
      59                 :            :         pthread_t workers[WORKERS_MAX];
      60                 :            :         unsigned n_valid_workers;
      61                 :            : 
      62                 :            :         unsigned current_id;
      63                 :            :         sd_resolve_query* query_array[QUERIES_MAX];
      64                 :            :         unsigned n_queries, n_done, n_outstanding;
      65                 :            : 
      66                 :            :         sd_event_source *event_source;
      67                 :            :         sd_event *event;
      68                 :            : 
      69                 :            :         sd_resolve_query *current;
      70                 :            : 
      71                 :            :         sd_resolve **default_resolve_ptr;
      72                 :            :         pid_t tid;
      73                 :            : 
      74                 :            :         LIST_HEAD(sd_resolve_query, queries);
      75                 :            : };
      76                 :            : 
      77                 :            : struct sd_resolve_query {
      78                 :            :         unsigned n_ref;
      79                 :            : 
      80                 :            :         sd_resolve *resolve;
      81                 :            : 
      82                 :            :         QueryType type:4;
      83                 :            :         bool done:1;
      84                 :            :         bool floating:1;
      85                 :            :         unsigned id;
      86                 :            : 
      87                 :            :         int ret;
      88                 :            :         int _errno;
      89                 :            :         int _h_errno;
      90                 :            :         struct addrinfo *addrinfo;
      91                 :            :         char *serv, *host;
      92                 :            : 
      93                 :            :         union {
      94                 :            :                 sd_resolve_getaddrinfo_handler_t getaddrinfo_handler;
      95                 :            :                 sd_resolve_getnameinfo_handler_t getnameinfo_handler;
      96                 :            :         };
      97                 :            : 
      98                 :            :         void *userdata;
      99                 :            :         sd_resolve_destroy_t destroy_callback;
     100                 :            : 
     101                 :            :         LIST_FIELDS(sd_resolve_query, queries);
     102                 :            : };
     103                 :            : 
     104                 :            : typedef struct RHeader {
     105                 :            :         QueryType type;
     106                 :            :         unsigned id;
     107                 :            :         size_t length;
     108                 :            : } RHeader;
     109                 :            : 
     110                 :            : typedef struct AddrInfoRequest {
     111                 :            :         struct RHeader header;
     112                 :            :         bool hints_valid;
     113                 :            :         int ai_flags;
     114                 :            :         int ai_family;
     115                 :            :         int ai_socktype;
     116                 :            :         int ai_protocol;
     117                 :            :         size_t node_len, service_len;
     118                 :            : } AddrInfoRequest;
     119                 :            : 
     120                 :            : typedef struct AddrInfoResponse {
     121                 :            :         struct RHeader header;
     122                 :            :         int ret;
     123                 :            :         int _errno;
     124                 :            :         int _h_errno;
     125                 :            :         /* followed by addrinfo_serialization[] */
     126                 :            : } AddrInfoResponse;
     127                 :            : 
     128                 :            : typedef struct AddrInfoSerialization {
     129                 :            :         int ai_flags;
     130                 :            :         int ai_family;
     131                 :            :         int ai_socktype;
     132                 :            :         int ai_protocol;
     133                 :            :         size_t ai_addrlen;
     134                 :            :         size_t canonname_len;
     135                 :            :         /* Followed by ai_addr amd ai_canonname with variable lengths */
     136                 :            : } AddrInfoSerialization;
     137                 :            : 
     138                 :            : typedef struct NameInfoRequest {
     139                 :            :         struct RHeader header;
     140                 :            :         int flags;
     141                 :            :         socklen_t sockaddr_len;
     142                 :            :         bool gethost:1, getserv:1;
     143                 :            : } NameInfoRequest;
     144                 :            : 
     145                 :            : typedef struct NameInfoResponse {
     146                 :            :         struct RHeader header;
     147                 :            :         size_t hostlen, servlen;
     148                 :            :         int ret;
     149                 :            :         int _errno;
     150                 :            :         int _h_errno;
     151                 :            : } NameInfoResponse;
     152                 :            : 
     153                 :            : typedef union Packet {
     154                 :            :         RHeader rheader;
     155                 :            :         AddrInfoRequest addrinfo_request;
     156                 :            :         AddrInfoResponse addrinfo_response;
     157                 :            :         NameInfoRequest nameinfo_request;
     158                 :            :         NameInfoResponse nameinfo_response;
     159                 :            : } Packet;
     160                 :            : 
     161                 :            : static int getaddrinfo_done(sd_resolve_query* q);
     162                 :            : static int getnameinfo_done(sd_resolve_query *q);
     163                 :            : 
     164                 :            : static void resolve_query_disconnect(sd_resolve_query *q);
     165                 :            : 
     166                 :            : #define RESOLVE_DONT_DESTROY(resolve) \
     167                 :            :         _cleanup_(sd_resolve_unrefp) _unused_ sd_resolve *_dont_destroy_##resolve = sd_resolve_ref(resolve)
     168                 :            : 
     169                 :         12 : static void query_assign_errno(sd_resolve_query *q, int ret, int error, int h_error) {
     170         [ -  + ]:         12 :         assert(q);
     171                 :            : 
     172                 :         12 :         q->ret = ret;
     173                 :         12 :         q->_errno = abs(error);
     174                 :         12 :         q->_h_errno = h_error;
     175                 :         12 : }
     176                 :            : 
     177                 :         12 : static int send_died(int out_fd) {
     178                 :         12 :         RHeader rh = {
     179                 :            :                 .type = RESPONSE_DIED,
     180                 :            :                 .length = sizeof(RHeader),
     181                 :            :         };
     182                 :            : 
     183         [ -  + ]:         12 :         assert(out_fd >= 0);
     184                 :            : 
     185         [ -  + ]:         12 :         if (send(out_fd, &rh, rh.length, MSG_NOSIGNAL) < 0)
     186                 :          0 :                 return -errno;
     187                 :            : 
     188                 :         12 :         return 0;
     189                 :            : }
     190                 :            : 
     191                 :         24 : static void *serialize_addrinfo(void *p, const struct addrinfo *ai, size_t *length, size_t maxlength) {
     192                 :            :         AddrInfoSerialization s;
     193                 :            :         size_t cnl, l;
     194                 :            : 
     195         [ -  + ]:         24 :         assert(p);
     196         [ -  + ]:         24 :         assert(ai);
     197         [ -  + ]:         24 :         assert(length);
     198         [ -  + ]:         24 :         assert(*length <= maxlength);
     199                 :            : 
     200         [ +  + ]:         24 :         cnl = ai->ai_canonname ? strlen(ai->ai_canonname)+1 : 0;
     201                 :         24 :         l = sizeof(AddrInfoSerialization) + ai->ai_addrlen + cnl;
     202                 :            : 
     203         [ -  + ]:         24 :         if (*length + l > maxlength)
     204                 :          0 :                 return NULL;
     205                 :            : 
     206                 :         24 :         s = (AddrInfoSerialization) {
     207                 :         24 :                 .ai_flags = ai->ai_flags,
     208                 :         24 :                 .ai_family = ai->ai_family,
     209                 :         24 :                 .ai_socktype = ai->ai_socktype,
     210                 :         24 :                 .ai_protocol = ai->ai_protocol,
     211                 :         24 :                 .ai_addrlen = ai->ai_addrlen,
     212                 :            :                 .canonname_len = cnl,
     213                 :            :         };
     214                 :            : 
     215                 :         24 :         memcpy((uint8_t*) p, &s, sizeof(AddrInfoSerialization));
     216                 :         24 :         memcpy((uint8_t*) p + sizeof(AddrInfoSerialization), ai->ai_addr, ai->ai_addrlen);
     217                 :         24 :         memcpy_safe((char*) p + sizeof(AddrInfoSerialization) + ai->ai_addrlen,
     218                 :         24 :                     ai->ai_canonname, cnl);
     219                 :            : 
     220                 :         24 :         *length += l;
     221                 :         24 :         return (uint8_t*) p + l;
     222                 :            : }
     223                 :            : 
     224                 :          8 : static int send_addrinfo_reply(
     225                 :            :                 int out_fd,
     226                 :            :                 unsigned id,
     227                 :            :                 int ret,
     228                 :            :                 struct addrinfo *ai,
     229                 :            :                 int _errno,
     230                 :            :                 int _h_errno) {
     231                 :            : 
     232                 :          8 :         AddrInfoResponse resp = {};
     233                 :            :         union {
     234                 :            :                 AddrInfoSerialization ais;
     235                 :            :                 uint8_t space[BUFSIZE];
     236                 :            :         } buffer;
     237                 :            :         struct iovec iov[2];
     238                 :            :         struct msghdr mh;
     239                 :            : 
     240         [ -  + ]:          8 :         assert(out_fd >= 0);
     241                 :            : 
     242                 :          8 :         resp = (AddrInfoResponse) {
     243                 :            :                 .header.type = RESPONSE_ADDRINFO,
     244                 :            :                 .header.id = id,
     245                 :            :                 .header.length = sizeof(AddrInfoResponse),
     246                 :            :                 .ret = ret,
     247                 :            :                 ._errno = _errno,
     248                 :            :                 ._h_errno = _h_errno,
     249                 :            :         };
     250                 :            : 
     251                 :            :         msan_unpoison(&resp, sizeof(resp));
     252                 :            : 
     253   [ +  -  +  - ]:          8 :         if (ret == 0 && ai) {
     254                 :          8 :                 void *p = &buffer;
     255                 :            :                 struct addrinfo *k;
     256                 :            : 
     257         [ +  + ]:         32 :                 for (k = ai; k; k = k->ai_next) {
     258                 :         24 :                         p = serialize_addrinfo(p, k, &resp.header.length, (uint8_t*) &buffer + BUFSIZE - (uint8_t*) p);
     259         [ -  + ]:         24 :                         if (!p) {
     260                 :          0 :                                 freeaddrinfo(ai);
     261                 :          0 :                                 return -ENOBUFS;
     262                 :            :                         }
     263                 :            :                 }
     264                 :            :         }
     265                 :            : 
     266         [ +  - ]:          8 :         if (ai)
     267                 :          8 :                 freeaddrinfo(ai);
     268                 :            : 
     269                 :          8 :         iov[0] = IOVEC_MAKE(&resp, sizeof(AddrInfoResponse));
     270                 :          8 :         iov[1] = IOVEC_MAKE(&buffer, resp.header.length - sizeof(AddrInfoResponse));
     271                 :            : 
     272                 :          8 :         mh = (struct msghdr) {
     273                 :            :                 .msg_iov = iov,
     274                 :            :                 .msg_iovlen = ELEMENTSOF(iov)
     275                 :            :         };
     276                 :            : 
     277         [ -  + ]:          8 :         if (sendmsg(out_fd, &mh, MSG_NOSIGNAL) < 0)
     278                 :          0 :                 return -errno;
     279                 :            : 
     280                 :          8 :         return 0;
     281                 :            : }
     282                 :            : 
     283                 :          4 : static int send_nameinfo_reply(
     284                 :            :                 int out_fd,
     285                 :            :                 unsigned id,
     286                 :            :                 int ret,
     287                 :            :                 const char *host,
     288                 :            :                 const char *serv,
     289                 :            :                 int _errno,
     290                 :            :                 int _h_errno) {
     291                 :            : 
     292                 :          4 :         NameInfoResponse resp = {};
     293                 :            :         struct iovec iov[3];
     294                 :            :         struct msghdr mh;
     295                 :            :         size_t hl, sl;
     296                 :            : 
     297         [ -  + ]:          4 :         assert(out_fd >= 0);
     298                 :            : 
     299         [ +  - ]:          4 :         sl = serv ? strlen(serv)+1 : 0;
     300         [ +  - ]:          4 :         hl = host ? strlen(host)+1 : 0;
     301                 :            : 
     302                 :          4 :         resp = (NameInfoResponse) {
     303                 :            :                 .header.type = RESPONSE_NAMEINFO,
     304                 :            :                 .header.id = id,
     305                 :          4 :                 .header.length = sizeof(NameInfoResponse) + hl + sl,
     306                 :            :                 .hostlen = hl,
     307                 :            :                 .servlen = sl,
     308                 :            :                 .ret = ret,
     309                 :            :                 ._errno = _errno,
     310                 :            :                 ._h_errno = _h_errno,
     311                 :            :         };
     312                 :            : 
     313                 :            :         msan_unpoison(&resp, sizeof(resp));
     314                 :            : 
     315                 :          4 :         iov[0] = IOVEC_MAKE(&resp, sizeof(NameInfoResponse));
     316                 :          4 :         iov[1] = IOVEC_MAKE((void*) host, hl);
     317                 :          4 :         iov[2] = IOVEC_MAKE((void*) serv, sl);
     318                 :            : 
     319                 :          4 :         mh = (struct msghdr) {
     320                 :            :                 .msg_iov = iov,
     321                 :            :                 .msg_iovlen = ELEMENTSOF(iov)
     322                 :            :         };
     323                 :            : 
     324         [ -  + ]:          4 :         if (sendmsg(out_fd, &mh, MSG_NOSIGNAL) < 0)
     325                 :          0 :                 return -errno;
     326                 :            : 
     327                 :          4 :         return 0;
     328                 :            : }
     329                 :            : 
     330                 :         22 : static int handle_request(int out_fd, const Packet *packet, size_t length) {
     331                 :            :         const RHeader *req;
     332                 :            : 
     333         [ -  + ]:         22 :         assert(out_fd >= 0);
     334         [ -  + ]:         22 :         assert(packet);
     335                 :            : 
     336                 :         22 :         req = &packet->rheader;
     337                 :            : 
     338   [ -  +  -  + ]:         22 :         assert_return(length >= sizeof(RHeader), -EIO);
     339   [ -  +  -  + ]:         22 :         assert_return(length == req->length, -EIO);
     340                 :            : 
     341   [ +  +  +  - ]:         22 :         switch (req->type) {
     342                 :            : 
     343                 :          8 :         case REQUEST_ADDRINFO: {
     344                 :          8 :                const AddrInfoRequest *ai_req = &packet->addrinfo_request;
     345                 :          8 :                struct addrinfo hints, *result = NULL;
     346                 :            :                const char *node, *service;
     347                 :            :                int ret;
     348                 :            : 
     349   [ -  +  -  + ]:          8 :                assert_return(length >= sizeof(AddrInfoRequest), -EBADMSG);
     350   [ -  +  -  + ]:          8 :                assert_return(length == sizeof(AddrInfoRequest) + ai_req->node_len + ai_req->service_len, -EBADMSG);
     351                 :            : 
     352                 :          8 :                hints = (struct addrinfo) {
     353                 :          8 :                        .ai_flags = ai_req->ai_flags,
     354                 :          8 :                        .ai_family = ai_req->ai_family,
     355                 :          8 :                        .ai_socktype = ai_req->ai_socktype,
     356                 :          8 :                        .ai_protocol = ai_req->ai_protocol,
     357                 :            :                };
     358                 :            : 
     359                 :            :                msan_unpoison(&hints, sizeof(hints));
     360                 :            : 
     361         [ +  - ]:          8 :                node = ai_req->node_len ? (const char*) ai_req + sizeof(AddrInfoRequest) : NULL;
     362         [ +  + ]:          8 :                service = ai_req->service_len ? (const char*) ai_req + sizeof(AddrInfoRequest) + ai_req->node_len : NULL;
     363                 :            : 
     364                 :          8 :                ret = getaddrinfo(node, service,
     365         [ +  + ]:          8 :                                  ai_req->hints_valid ? &hints : NULL,
     366                 :            :                                  &result);
     367                 :            : 
     368                 :            :                /* send_addrinfo_reply() frees result */
     369                 :          8 :                return send_addrinfo_reply(out_fd, req->id, ret, result, errno, h_errno);
     370                 :            :         }
     371                 :            : 
     372                 :          4 :         case REQUEST_NAMEINFO: {
     373                 :          4 :                const NameInfoRequest *ni_req = &packet->nameinfo_request;
     374                 :            :                char hostbuf[NI_MAXHOST], servbuf[NI_MAXSERV];
     375                 :            :                union sockaddr_union sa;
     376                 :            :                int ret;
     377                 :            : 
     378   [ -  +  -  + ]:          4 :                assert_return(length >= sizeof(NameInfoRequest), -EBADMSG);
     379   [ -  +  -  + ]:          4 :                assert_return(length == sizeof(NameInfoRequest) + ni_req->sockaddr_len, -EBADMSG);
     380   [ -  +  -  + ]:          4 :                assert_return(ni_req->sockaddr_len <= sizeof(sa), -EBADMSG);
     381                 :            : 
     382                 :          4 :                memcpy(&sa, (const uint8_t *) ni_req + sizeof(NameInfoRequest), ni_req->sockaddr_len);
     383                 :            : 
     384                 :         12 :                ret = getnameinfo(&sa.sa, ni_req->sockaddr_len,
     385   [ +  -  +  - ]:          8 :                                  ni_req->gethost ? hostbuf : NULL, ni_req->gethost ? sizeof(hostbuf) : 0,
     386         [ +  - ]:          4 :                                  ni_req->getserv ? servbuf : NULL, ni_req->getserv ? sizeof(servbuf) : 0,
     387                 :            :                                  ni_req->flags);
     388                 :            : 
     389         [ +  - ]:          8 :                return send_nameinfo_reply(out_fd, req->id, ret,
     390         [ +  - ]:          4 :                                           ret == 0 && ni_req->gethost ? hostbuf : NULL,
     391         [ +  - ]:          4 :                                           ret == 0 && ni_req->getserv ? servbuf : NULL,
     392         [ +  - ]:          4 :                                           errno, h_errno);
     393                 :            :         }
     394                 :            : 
     395                 :         10 :         case REQUEST_TERMINATE:
     396                 :            :                  /* Quit */
     397                 :         10 :                  return -ECONNRESET;
     398                 :            : 
     399                 :          0 :         default:
     400                 :          0 :                 assert_not_reached("Unknown request");
     401                 :            :         }
     402                 :            : 
     403                 :            :         return 0;
     404                 :            : }
     405                 :            : 
     406                 :         12 : static void* thread_worker(void *p) {
     407                 :         12 :         sd_resolve *resolve = p;
     408                 :            : 
     409                 :            :         /* Assign a pretty name to this thread */
     410                 :         12 :         (void) pthread_setname_np(pthread_self(), "sd-resolve");
     411                 :            : 
     412         [ +  + ]:         24 :         while (!resolve->dead) {
     413                 :            :                 union {
     414                 :            :                         Packet packet;
     415                 :            :                         uint8_t space[BUFSIZE];
     416                 :            :                 } buf;
     417                 :            :                 ssize_t length;
     418                 :            : 
     419                 :         22 :                 length = recv(resolve->fds[REQUEST_RECV_FD], &buf, sizeof buf, 0);
     420         [ -  + ]:         22 :                 if (length < 0) {
     421         [ #  # ]:          0 :                         if (errno == EINTR)
     422                 :          0 :                                 continue;
     423                 :            : 
     424                 :         10 :                         break;
     425                 :            :                 }
     426         [ -  + ]:         22 :                 if (length == 0)
     427                 :          0 :                         break;
     428                 :            : 
     429         [ +  + ]:         22 :                 if (handle_request(resolve->fds[RESPONSE_SEND_FD], &buf.packet, (size_t) length) < 0)
     430                 :         10 :                         break;
     431                 :            :         }
     432                 :            : 
     433                 :         12 :         send_died(resolve->fds[RESPONSE_SEND_FD]);
     434                 :            : 
     435                 :         12 :         return NULL;
     436                 :            : }
     437                 :            : 
     438                 :         12 : static int start_threads(sd_resolve *resolve, unsigned extra) {
     439                 :            :         sigset_t ss, saved_ss;
     440                 :            :         unsigned n;
     441                 :            :         int r, k;
     442                 :            : 
     443         [ -  + ]:         12 :         assert_se(sigfillset(&ss) >= 0);
     444                 :            : 
     445                 :            :         /* No signals in forked off threads please. We set the mask before forking, so that the threads never exist
     446                 :            :          * with a different mask than a fully blocked one */
     447                 :         12 :         r = pthread_sigmask(SIG_BLOCK, &ss, &saved_ss);
     448         [ -  + ]:         12 :         if (r > 0)
     449                 :          0 :                 return -r;
     450                 :            : 
     451                 :         12 :         n = resolve->n_outstanding + extra;
     452         [ +  - ]:         12 :         n = CLAMP(n, WORKERS_MIN, WORKERS_MAX);
     453                 :            : 
     454         [ +  + ]:         24 :         while (resolve->n_valid_workers < n) {
     455                 :         12 :                 r = pthread_create(&resolve->workers[resolve->n_valid_workers], NULL, thread_worker, resolve);
     456         [ -  + ]:         12 :                 if (r > 0) {
     457                 :          0 :                         r = -r;
     458                 :          0 :                         goto finish;
     459                 :            :                 }
     460                 :            : 
     461                 :         12 :                 resolve->n_valid_workers++;
     462                 :            :         }
     463                 :            : 
     464                 :         12 :         r = 0;
     465                 :            : 
     466                 :         12 : finish:
     467                 :         12 :         k = pthread_sigmask(SIG_SETMASK, &saved_ss, NULL);
     468   [ -  +  #  # ]:         12 :         if (k > 0 && r >= 0)
     469                 :          0 :                 r = -k;
     470                 :            : 
     471                 :         12 :         return r;
     472                 :            : }
     473                 :            : 
     474                 :         40 : static bool resolve_pid_changed(sd_resolve *r) {
     475         [ -  + ]:         40 :         assert(r);
     476                 :            : 
     477                 :            :         /* We don't support people creating a resolver and keeping it
     478                 :            :          * around after fork(). Let's complain. */
     479                 :            : 
     480                 :         40 :         return r->original_pid != getpid_cached();
     481                 :            : }
     482                 :            : 
     483                 :         12 : _public_ int sd_resolve_new(sd_resolve **ret) {
     484                 :         12 :         _cleanup_(sd_resolve_unrefp) sd_resolve *resolve = NULL;
     485                 :            :         int i;
     486                 :            : 
     487   [ -  +  -  + ]:         12 :         assert_return(ret, -EINVAL);
     488                 :            : 
     489                 :         12 :         resolve = new0(sd_resolve, 1);
     490         [ -  + ]:         12 :         if (!resolve)
     491                 :          0 :                 return -ENOMEM;
     492                 :            : 
     493                 :         12 :         resolve->n_ref = 1;
     494                 :         12 :         resolve->original_pid = getpid_cached();
     495                 :            : 
     496         [ +  + ]:         60 :         for (i = 0; i < _FD_MAX; i++)
     497                 :         48 :                 resolve->fds[i] = -1;
     498                 :            : 
     499         [ -  + ]:         12 :         if (socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds + REQUEST_RECV_FD) < 0)
     500                 :          0 :                 return -errno;
     501                 :            : 
     502         [ -  + ]:         12 :         if (socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds + RESPONSE_RECV_FD) < 0)
     503                 :          0 :                 return -errno;
     504                 :            : 
     505         [ +  + ]:         60 :         for (i = 0; i < _FD_MAX; i++)
     506                 :         48 :                 resolve->fds[i] = fd_move_above_stdio(resolve->fds[i]);
     507                 :            : 
     508                 :         12 :         (void) fd_inc_sndbuf(resolve->fds[REQUEST_SEND_FD], QUERIES_MAX * BUFSIZE);
     509                 :         12 :         (void) fd_inc_rcvbuf(resolve->fds[REQUEST_RECV_FD], QUERIES_MAX * BUFSIZE);
     510                 :         12 :         (void) fd_inc_sndbuf(resolve->fds[RESPONSE_SEND_FD], QUERIES_MAX * BUFSIZE);
     511                 :         12 :         (void) fd_inc_rcvbuf(resolve->fds[RESPONSE_RECV_FD], QUERIES_MAX * BUFSIZE);
     512                 :            : 
     513                 :         12 :         (void) fd_nonblock(resolve->fds[RESPONSE_RECV_FD], true);
     514                 :            : 
     515                 :         12 :         *ret = TAKE_PTR(resolve);
     516                 :         12 :         return 0;
     517                 :            : }
     518                 :            : 
     519                 :         12 : _public_ int sd_resolve_default(sd_resolve **ret) {
     520                 :            :         static thread_local sd_resolve *default_resolve = NULL;
     521                 :         12 :         sd_resolve *e = NULL;
     522                 :            :         int r;
     523                 :            : 
     524         [ -  + ]:         12 :         if (!ret)
     525                 :          0 :                 return !!default_resolve;
     526                 :            : 
     527         [ -  + ]:         12 :         if (default_resolve) {
     528                 :          0 :                 *ret = sd_resolve_ref(default_resolve);
     529                 :          0 :                 return 0;
     530                 :            :         }
     531                 :            : 
     532                 :         12 :         r = sd_resolve_new(&e);
     533         [ -  + ]:         12 :         if (r < 0)
     534                 :          0 :                 return r;
     535                 :            : 
     536                 :         12 :         e->default_resolve_ptr = &default_resolve;
     537                 :         12 :         e->tid = gettid();
     538                 :         12 :         default_resolve = e;
     539                 :            : 
     540                 :         12 :         *ret = e;
     541                 :         12 :         return 1;
     542                 :            : }
     543                 :            : 
     544                 :          0 : _public_ int sd_resolve_get_tid(sd_resolve *resolve, pid_t *tid) {
     545   [ #  #  #  # ]:          0 :         assert_return(resolve, -EINVAL);
     546   [ #  #  #  # ]:          0 :         assert_return(tid, -EINVAL);
     547   [ #  #  #  # ]:          0 :         assert_return(!resolve_pid_changed(resolve), -ECHILD);
     548                 :            : 
     549         [ #  # ]:          0 :         if (resolve->tid != 0) {
     550                 :          0 :                 *tid = resolve->tid;
     551                 :          0 :                 return 0;
     552                 :            :         }
     553                 :            : 
     554         [ #  # ]:          0 :         if (resolve->event)
     555                 :          0 :                 return sd_event_get_tid(resolve->event, tid);
     556                 :            : 
     557                 :          0 :         return -ENXIO;
     558                 :            : }
     559                 :            : 
     560                 :         12 : static sd_resolve *resolve_free(sd_resolve *resolve) {
     561                 :         12 :         PROTECT_ERRNO;
     562                 :            :         sd_resolve_query *q;
     563                 :            :         unsigned i;
     564                 :            : 
     565         [ -  + ]:         12 :         assert(resolve);
     566                 :            : 
     567         [ -  + ]:         12 :         while ((q = resolve->queries)) {
     568         [ #  # ]:          0 :                 assert(q->floating);
     569                 :          0 :                 resolve_query_disconnect(q);
     570                 :          0 :                 sd_resolve_query_unref(q);
     571                 :            :         }
     572                 :            : 
     573         [ +  - ]:         12 :         if (resolve->default_resolve_ptr)
     574                 :         12 :                 *(resolve->default_resolve_ptr) = NULL;
     575                 :            : 
     576                 :         12 :         resolve->dead = true;
     577                 :            : 
     578                 :         12 :         sd_resolve_detach_event(resolve);
     579                 :            : 
     580         [ +  - ]:         12 :         if (resolve->fds[REQUEST_SEND_FD] >= 0) {
     581                 :            : 
     582                 :         12 :                 RHeader req = {
     583                 :            :                         .type = REQUEST_TERMINATE,
     584                 :            :                         .length = sizeof req,
     585                 :            :                 };
     586                 :            : 
     587                 :            :                 /* Send one termination packet for each worker */
     588         [ +  + ]:         24 :                 for (i = 0; i < resolve->n_valid_workers; i++)
     589                 :         12 :                         (void) send(resolve->fds[REQUEST_SEND_FD], &req, req.length, MSG_NOSIGNAL);
     590                 :            :         }
     591                 :            : 
     592                 :            :         /* Now terminate them and wait until they are gone.
     593                 :            :            If we get an error than most likely the thread already exited. */
     594         [ +  + ]:         24 :         for (i = 0; i < resolve->n_valid_workers; i++)
     595                 :         12 :                 (void) pthread_join(resolve->workers[i], NULL);
     596                 :            : 
     597                 :            :         /* Close all communication channels */
     598                 :         12 :         close_many(resolve->fds, _FD_MAX);
     599                 :            : 
     600                 :         12 :         return mfree(resolve);
     601                 :            : }
     602                 :            : 
     603   [ +  +  -  +  :         68 : DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_resolve, sd_resolve, resolve_free);
                   +  + ]
     604                 :            : 
     605                 :          0 : _public_ int sd_resolve_get_fd(sd_resolve *resolve) {
     606   [ #  #  #  # ]:          0 :         assert_return(resolve, -EINVAL);
     607   [ #  #  #  # ]:          0 :         assert_return(!resolve_pid_changed(resolve), -ECHILD);
     608                 :            : 
     609                 :          0 :         return resolve->fds[RESPONSE_RECV_FD];
     610                 :            : }
     611                 :            : 
     612                 :          0 : _public_ int sd_resolve_get_events(sd_resolve *resolve) {
     613   [ #  #  #  # ]:          0 :         assert_return(resolve, -EINVAL);
     614   [ #  #  #  # ]:          0 :         assert_return(!resolve_pid_changed(resolve), -ECHILD);
     615                 :            : 
     616                 :          0 :         return resolve->n_queries > resolve->n_done ? POLLIN : 0;
     617                 :            : }
     618                 :            : 
     619                 :          0 : _public_ int sd_resolve_get_timeout(sd_resolve *resolve, uint64_t *usec) {
     620   [ #  #  #  # ]:          0 :         assert_return(resolve, -EINVAL);
     621   [ #  #  #  # ]:          0 :         assert_return(usec, -EINVAL);
     622   [ #  #  #  # ]:          0 :         assert_return(!resolve_pid_changed(resolve), -ECHILD);
     623                 :            : 
     624                 :          0 :         *usec = (uint64_t) -1;
     625                 :          0 :         return 0;
     626                 :            : }
     627                 :            : 
     628                 :         12 : static sd_resolve_query *lookup_query(sd_resolve *resolve, unsigned id) {
     629                 :            :         sd_resolve_query *q;
     630                 :            : 
     631         [ -  + ]:         12 :         assert(resolve);
     632                 :            : 
     633                 :         12 :         q = resolve->query_array[id % QUERIES_MAX];
     634         [ +  - ]:         12 :         if (q)
     635         [ +  - ]:         12 :                 if (q->id == id)
     636                 :         12 :                         return q;
     637                 :            : 
     638                 :          0 :         return NULL;
     639                 :            : }
     640                 :            : 
     641                 :         12 : static int complete_query(sd_resolve *resolve, sd_resolve_query *q) {
     642                 :            :         int r;
     643                 :            : 
     644         [ -  + ]:         12 :         assert(q);
     645         [ -  + ]:         12 :         assert(!q->done);
     646         [ -  + ]:         12 :         assert(q->resolve == resolve);
     647                 :            : 
     648                 :         12 :         q->done = true;
     649                 :         12 :         resolve->n_done++;
     650                 :            : 
     651                 :         12 :         resolve->current = sd_resolve_query_ref(q);
     652                 :            : 
     653      [ +  +  - ]:         12 :         switch (q->type) {
     654                 :            : 
     655                 :          8 :         case REQUEST_ADDRINFO:
     656                 :          8 :                 r = getaddrinfo_done(q);
     657                 :          8 :                 break;
     658                 :            : 
     659                 :          4 :         case REQUEST_NAMEINFO:
     660                 :          4 :                 r = getnameinfo_done(q);
     661                 :          4 :                 break;
     662                 :            : 
     663                 :          0 :         default:
     664                 :          0 :                 assert_not_reached("Cannot complete unknown query type");
     665                 :            :         }
     666                 :            : 
     667                 :         12 :         resolve->current = NULL;
     668                 :            : 
     669         [ +  + ]:         12 :         if (q->floating) {
     670                 :          4 :                 resolve_query_disconnect(q);
     671                 :          4 :                 sd_resolve_query_unref(q);
     672                 :            :         }
     673                 :            : 
     674                 :         12 :         sd_resolve_query_unref(q);
     675                 :            : 
     676                 :         12 :         return r;
     677                 :            : }
     678                 :            : 
     679                 :         24 : static int unserialize_addrinfo(const void **p, size_t *length, struct addrinfo **ret_ai) {
     680                 :            :         AddrInfoSerialization s;
     681                 :            :         struct addrinfo *ai;
     682                 :            :         size_t l;
     683                 :            : 
     684         [ -  + ]:         24 :         assert(p);
     685         [ -  + ]:         24 :         assert(*p);
     686         [ -  + ]:         24 :         assert(ret_ai);
     687         [ -  + ]:         24 :         assert(length);
     688                 :            : 
     689         [ -  + ]:         24 :         if (*length < sizeof(AddrInfoSerialization))
     690                 :          0 :                 return -EBADMSG;
     691                 :            : 
     692                 :         24 :         memcpy(&s, *p, sizeof(s));
     693                 :            : 
     694                 :         24 :         l = sizeof(AddrInfoSerialization) + s.ai_addrlen + s.canonname_len;
     695         [ -  + ]:         24 :         if (*length < l)
     696                 :          0 :                 return -EBADMSG;
     697                 :            : 
     698                 :         24 :         ai = new(struct addrinfo, 1);
     699         [ -  + ]:         24 :         if (!ai)
     700                 :          0 :                 return -ENOMEM;
     701                 :            : 
     702                 :         24 :         *ai = (struct addrinfo) {
     703                 :         24 :                 .ai_flags = s.ai_flags,
     704                 :         24 :                 .ai_family = s.ai_family,
     705                 :         24 :                 .ai_socktype = s.ai_socktype,
     706                 :         24 :                 .ai_protocol = s.ai_protocol,
     707                 :         24 :                 .ai_addrlen = s.ai_addrlen,
     708                 :            :         };
     709                 :            : 
     710         [ +  - ]:         24 :         if (s.ai_addrlen > 0) {
     711                 :         24 :                 ai->ai_addr = memdup((const uint8_t*) *p + sizeof(AddrInfoSerialization), s.ai_addrlen);
     712         [ -  + ]:         24 :                 if (!ai->ai_addr) {
     713                 :          0 :                         free(ai);
     714                 :          0 :                         return -ENOMEM;
     715                 :            :                 }
     716                 :            :         }
     717                 :            : 
     718         [ +  + ]:         24 :         if (s.canonname_len > 0) {
     719                 :          4 :                 ai->ai_canonname = memdup((const uint8_t*) *p + sizeof(AddrInfoSerialization) + s.ai_addrlen, s.canonname_len);
     720         [ -  + ]:          4 :                 if (!ai->ai_canonname) {
     721                 :          0 :                         free(ai->ai_addr);
     722                 :          0 :                         free(ai);
     723                 :          0 :                         return -ENOMEM;
     724                 :            :                 }
     725                 :            :         }
     726                 :            : 
     727                 :         24 :         *length -= l;
     728                 :         24 :         *ret_ai = ai;
     729                 :         24 :         *p = ((const uint8_t*) *p) + l;
     730                 :            : 
     731                 :         24 :         return 0;
     732                 :            : }
     733                 :            : 
     734                 :         12 : static int handle_response(sd_resolve *resolve, const Packet *packet, size_t length) {
     735                 :            :         const RHeader *resp;
     736                 :            :         sd_resolve_query *q;
     737                 :            :         int r;
     738                 :            : 
     739         [ -  + ]:         12 :         assert(resolve);
     740         [ -  + ]:         12 :         assert(packet);
     741                 :            : 
     742                 :         12 :         resp = &packet->rheader;
     743   [ -  +  -  + ]:         12 :         assert_return(length >= sizeof(RHeader), -EIO);
     744   [ -  +  -  + ]:         12 :         assert_return(length == resp->length, -EIO);
     745                 :            : 
     746         [ -  + ]:         12 :         if (resp->type == RESPONSE_DIED) {
     747                 :          0 :                 resolve->dead = true;
     748                 :          0 :                 return 0;
     749                 :            :         }
     750                 :            : 
     751         [ -  + ]:         12 :         assert(resolve->n_outstanding > 0);
     752                 :         12 :         resolve->n_outstanding--;
     753                 :            : 
     754                 :         12 :         q = lookup_query(resolve, resp->id);
     755         [ -  + ]:         12 :         if (!q)
     756                 :          0 :                 return 0;
     757                 :            : 
     758      [ +  +  - ]:         12 :         switch (resp->type) {
     759                 :            : 
     760                 :          8 :         case RESPONSE_ADDRINFO: {
     761                 :          8 :                 const AddrInfoResponse *ai_resp = &packet->addrinfo_response;
     762                 :            :                 const void *p;
     763                 :            :                 size_t l;
     764                 :          8 :                 struct addrinfo *prev = NULL;
     765                 :            : 
     766   [ -  +  -  + ]:          8 :                 assert_return(length >= sizeof(AddrInfoResponse), -EBADMSG);
     767   [ -  +  -  + ]:          8 :                 assert_return(q->type == REQUEST_ADDRINFO, -EBADMSG);
     768                 :            : 
     769                 :          8 :                 query_assign_errno(q, ai_resp->ret, ai_resp->_errno, ai_resp->_h_errno);
     770                 :            : 
     771                 :          8 :                 l = length - sizeof(AddrInfoResponse);
     772                 :          8 :                 p = (const uint8_t*) resp + sizeof(AddrInfoResponse);
     773                 :            : 
     774   [ +  +  +  - ]:         32 :                 while (l > 0 && p) {
     775                 :         24 :                         struct addrinfo *ai = NULL;
     776                 :            : 
     777                 :         24 :                         r = unserialize_addrinfo(&p, &l, &ai);
     778         [ -  + ]:         24 :                         if (r < 0) {
     779                 :          0 :                                 query_assign_errno(q, EAI_SYSTEM, r, 0);
     780                 :          0 :                                 freeaddrinfo(q->addrinfo);
     781                 :          0 :                                 q->addrinfo = NULL;
     782                 :          0 :                                 break;
     783                 :            :                         }
     784                 :            : 
     785         [ +  + ]:         24 :                         if (prev)
     786                 :         16 :                                 prev->ai_next = ai;
     787                 :            :                         else
     788                 :          8 :                                 q->addrinfo = ai;
     789                 :            : 
     790                 :         24 :                         prev = ai;
     791                 :            :                 }
     792                 :            : 
     793                 :          8 :                 return complete_query(resolve, q);
     794                 :            :         }
     795                 :            : 
     796                 :          4 :         case RESPONSE_NAMEINFO: {
     797                 :          4 :                 const NameInfoResponse *ni_resp = &packet->nameinfo_response;
     798                 :            : 
     799   [ -  +  -  + ]:          4 :                 assert_return(length >= sizeof(NameInfoResponse), -EBADMSG);
     800   [ -  +  -  + ]:          4 :                 assert_return(q->type == REQUEST_NAMEINFO, -EBADMSG);
     801                 :            : 
     802         [ +  - ]:          4 :                 if (ni_resp->hostlen > DNS_HOSTNAME_MAX ||
     803         [ +  - ]:          4 :                     ni_resp->servlen > DNS_HOSTNAME_MAX ||
     804         [ -  + ]:          4 :                     sizeof(NameInfoResponse) + ni_resp->hostlen + ni_resp->servlen > length)
     805                 :          0 :                         query_assign_errno(q, EAI_SYSTEM, EIO, 0);
     806                 :            :                 else {
     807                 :          4 :                         query_assign_errno(q, ni_resp->ret, ni_resp->_errno, ni_resp->_h_errno);
     808                 :            : 
     809         [ +  - ]:          4 :                         if (ni_resp->hostlen > 0) {
     810                 :          4 :                                 q->host = strndup((const char*) ni_resp + sizeof(NameInfoResponse),
     811                 :          4 :                                                   ni_resp->hostlen-1);
     812         [ -  + ]:          4 :                                 if (!q->host)
     813                 :          0 :                                         query_assign_errno(q, EAI_MEMORY, ENOMEM, 0);
     814                 :            :                         }
     815                 :            : 
     816         [ +  - ]:          4 :                         if (ni_resp->servlen > 0) {
     817                 :          4 :                                 q->serv = strndup((const char*) ni_resp + sizeof(NameInfoResponse) + ni_resp->hostlen,
     818                 :          4 :                                                   ni_resp->servlen-1);
     819         [ -  + ]:          4 :                                 if (!q->serv)
     820                 :          0 :                                         query_assign_errno(q, EAI_MEMORY, ENOMEM, 0);
     821                 :            :                         }
     822                 :            :                 }
     823                 :            : 
     824                 :          4 :                 return complete_query(resolve, q);
     825                 :            :         }
     826                 :            : 
     827                 :          0 :         default:
     828                 :          0 :                 return 0;
     829                 :            :         }
     830                 :            : }
     831                 :            : 
     832                 :         12 : _public_ int sd_resolve_process(sd_resolve *resolve) {
     833                 :         24 :         RESOLVE_DONT_DESTROY(resolve);
     834                 :            : 
     835                 :            :         union {
     836                 :            :                 Packet packet;
     837                 :            :                 uint8_t space[BUFSIZE];
     838                 :            :         } buf;
     839                 :            :         ssize_t l;
     840                 :            :         int r;
     841                 :            : 
     842   [ -  +  -  + ]:         12 :         assert_return(resolve, -EINVAL);
     843   [ -  +  -  + ]:         12 :         assert_return(!resolve_pid_changed(resolve), -ECHILD);
     844                 :            : 
     845                 :            :         /* We don't allow recursively invoking sd_resolve_process(). */
     846   [ -  +  -  + ]:         12 :         assert_return(!resolve->current, -EBUSY);
     847                 :            : 
     848                 :         12 :         l = recv(resolve->fds[RESPONSE_RECV_FD], &buf, sizeof buf, 0);
     849         [ -  + ]:         12 :         if (l < 0) {
     850         [ #  # ]:          0 :                 if (errno == EAGAIN)
     851                 :          0 :                         return 0;
     852                 :            : 
     853                 :          0 :                 return -errno;
     854                 :            :         }
     855         [ -  + ]:         12 :         if (l == 0)
     856                 :          0 :                 return -ECONNREFUSED;
     857                 :            : 
     858                 :         12 :         r = handle_response(resolve, &buf.packet, (size_t) l);
     859         [ -  + ]:         12 :         if (r < 0)
     860                 :          0 :                 return r;
     861                 :            : 
     862                 :         12 :         return 1;
     863                 :            : }
     864                 :            : 
     865                 :         16 : _public_ int sd_resolve_wait(sd_resolve *resolve, uint64_t timeout_usec) {
     866                 :            :         int r;
     867                 :            : 
     868   [ -  +  -  + ]:         16 :         assert_return(resolve, -EINVAL);
     869   [ -  +  -  + ]:         16 :         assert_return(!resolve_pid_changed(resolve), -ECHILD);
     870                 :            : 
     871         [ +  + ]:         16 :         if (resolve->n_done >= resolve->n_queries)
     872                 :          4 :                 return 0;
     873                 :            : 
     874                 :            :         do {
     875                 :         12 :                 r = fd_wait_for_event(resolve->fds[RESPONSE_RECV_FD], POLLIN, timeout_usec);
     876         [ -  + ]:         12 :         } while (r == -EINTR);
     877                 :            : 
     878         [ -  + ]:         12 :         if (r < 0)
     879                 :          0 :                 return r;
     880         [ -  + ]:         12 :         if (r == 0)
     881                 :          0 :                 return -ETIMEDOUT;
     882                 :            : 
     883                 :         12 :         return sd_resolve_process(resolve);
     884                 :            : }
     885                 :            : 
     886                 :         12 : static int alloc_query(sd_resolve *resolve, bool floating, sd_resolve_query **_q) {
     887                 :            :         sd_resolve_query *q;
     888                 :            :         int r;
     889                 :            : 
     890         [ -  + ]:         12 :         assert(resolve);
     891         [ -  + ]:         12 :         assert(_q);
     892                 :            : 
     893         [ -  + ]:         12 :         if (resolve->n_queries >= QUERIES_MAX)
     894                 :          0 :                 return -ENOBUFS;
     895                 :            : 
     896                 :         12 :         r = start_threads(resolve, 1);
     897         [ -  + ]:         12 :         if (r < 0)
     898                 :          0 :                 return r;
     899                 :            : 
     900         [ -  + ]:         12 :         while (resolve->query_array[resolve->current_id % QUERIES_MAX])
     901                 :          0 :                 resolve->current_id++;
     902                 :            : 
     903                 :         12 :         q = resolve->query_array[resolve->current_id % QUERIES_MAX] = new0(sd_resolve_query, 1);
     904         [ -  + ]:         12 :         if (!q)
     905                 :          0 :                 return -ENOMEM;
     906                 :            : 
     907                 :         12 :         q->n_ref = 1;
     908                 :         12 :         q->resolve = resolve;
     909                 :         12 :         q->floating = floating;
     910                 :         12 :         q->id = resolve->current_id++;
     911                 :            : 
     912         [ +  + ]:         12 :         if (!floating)
     913                 :          8 :                 sd_resolve_ref(resolve);
     914                 :            : 
     915   [ -  +  +  + ]:         12 :         LIST_PREPEND(queries, resolve->queries, q);
     916                 :         12 :         resolve->n_queries++;
     917                 :            : 
     918                 :         12 :         *_q = q;
     919                 :         12 :         return 0;
     920                 :            : }
     921                 :            : 
     922                 :          8 : int resolve_getaddrinfo_with_destroy_callback(
     923                 :            :                 sd_resolve *resolve,
     924                 :            :                 sd_resolve_query **ret_query,
     925                 :            :                 const char *node, const char *service,
     926                 :            :                 const struct addrinfo *hints,
     927                 :            :                 sd_resolve_getaddrinfo_handler_t callback,
     928                 :            :                 sd_resolve_destroy_t destroy_callback,
     929                 :            :                 void *userdata) {
     930                 :            : 
     931                 :          8 :         _cleanup_(sd_resolve_query_unrefp) sd_resolve_query *q = NULL;
     932                 :            :         size_t node_len, service_len;
     933                 :          8 :         AddrInfoRequest req = {};
     934                 :            :         struct iovec iov[3];
     935                 :          8 :         struct msghdr mh = {};
     936                 :            :         int r;
     937                 :            : 
     938   [ -  +  -  + ]:          8 :         assert_return(resolve, -EINVAL);
     939   [ -  +  #  #  :          8 :         assert_return(node || service, -EINVAL);
                   -  + ]
     940   [ -  +  -  + ]:          8 :         assert_return(callback, -EINVAL);
     941   [ -  +  -  + ]:          8 :         assert_return(!resolve_pid_changed(resolve), -ECHILD);
     942                 :            : 
     943                 :          8 :         r = alloc_query(resolve, !ret_query, &q);
     944         [ -  + ]:          8 :         if (r < 0)
     945                 :          0 :                 return r;
     946                 :            : 
     947                 :          8 :         q->type = REQUEST_ADDRINFO;
     948                 :          8 :         q->getaddrinfo_handler = callback;
     949                 :          8 :         q->userdata = userdata;
     950                 :            : 
     951         [ +  - ]:          8 :         node_len = node ? strlen(node) + 1 : 0;
     952         [ +  + ]:          8 :         service_len = service ? strlen(service) + 1 : 0;
     953                 :            : 
     954                 :         16 :         req = (AddrInfoRequest) {
     955                 :            :                 .node_len = node_len,
     956                 :            :                 .service_len = service_len,
     957                 :            : 
     958                 :          8 :                 .header.id = q->id,
     959                 :            :                 .header.type = REQUEST_ADDRINFO,
     960                 :          8 :                 .header.length = sizeof(AddrInfoRequest) + node_len + service_len,
     961                 :            : 
     962                 :            :                 .hints_valid = hints,
     963         [ +  + ]:          8 :                 .ai_flags = hints ? hints->ai_flags : 0,
     964         [ +  + ]:          8 :                 .ai_family = hints ? hints->ai_family : 0,
     965         [ +  + ]:          8 :                 .ai_socktype = hints ? hints->ai_socktype : 0,
     966         [ +  + ]:          8 :                 .ai_protocol = hints ? hints->ai_protocol : 0,
     967                 :            :         };
     968                 :            : 
     969                 :            :         msan_unpoison(&req, sizeof(req));
     970                 :            : 
     971                 :          8 :         iov[mh.msg_iovlen++] = IOVEC_MAKE(&req, sizeof(AddrInfoRequest));
     972         [ +  - ]:          8 :         if (node)
     973                 :          8 :                 iov[mh.msg_iovlen++] = IOVEC_MAKE((void*) node, req.node_len);
     974         [ +  + ]:          8 :         if (service)
     975                 :          4 :                 iov[mh.msg_iovlen++] = IOVEC_MAKE((void*) service, req.service_len);
     976                 :          8 :         mh.msg_iov = iov;
     977                 :            : 
     978         [ -  + ]:          8 :         if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0)
     979                 :          0 :                 return -errno;
     980                 :            : 
     981                 :          8 :         resolve->n_outstanding++;
     982                 :          8 :         q->destroy_callback = destroy_callback;
     983                 :            : 
     984         [ +  + ]:          8 :         if (ret_query)
     985                 :          4 :                 *ret_query = q;
     986                 :            : 
     987                 :          8 :         TAKE_PTR(q);
     988                 :            : 
     989                 :          8 :         return 0;
     990                 :            : }
     991                 :            : 
     992                 :          8 : _public_ int sd_resolve_getaddrinfo(
     993                 :            :                 sd_resolve *resolve,
     994                 :            :                 sd_resolve_query **ret_query,
     995                 :            :                 const char *node, const char *service,
     996                 :            :                 const struct addrinfo *hints,
     997                 :            :                 sd_resolve_getaddrinfo_handler_t callback,
     998                 :            :                 void *userdata) {
     999                 :            : 
    1000                 :          8 :         return resolve_getaddrinfo_with_destroy_callback(resolve, ret_query, node, service, hints, callback, NULL, userdata);
    1001                 :            : }
    1002                 :            : 
    1003                 :          8 : static int getaddrinfo_done(sd_resolve_query* q) {
    1004         [ -  + ]:          8 :         assert(q);
    1005         [ -  + ]:          8 :         assert(q->done);
    1006         [ -  + ]:          8 :         assert(q->getaddrinfo_handler);
    1007                 :            : 
    1008                 :          8 :         errno = q->_errno;
    1009                 :          8 :         h_errno = q->_h_errno;
    1010                 :            : 
    1011                 :          8 :         return q->getaddrinfo_handler(q, q->ret, q->addrinfo, q->userdata);
    1012                 :            : }
    1013                 :            : 
    1014                 :          4 : int resolve_getnameinfo_with_destroy_callback(
    1015                 :            :                 sd_resolve *resolve,
    1016                 :            :                 sd_resolve_query **ret_query,
    1017                 :            :                 const struct sockaddr *sa, socklen_t salen,
    1018                 :            :                 int flags,
    1019                 :            :                 uint64_t get,
    1020                 :            :                 sd_resolve_getnameinfo_handler_t callback,
    1021                 :            :                 sd_resolve_destroy_t destroy_callback,
    1022                 :            :                 void *userdata) {
    1023                 :            : 
    1024                 :          4 :         _cleanup_(sd_resolve_query_unrefp) sd_resolve_query *q = NULL;
    1025                 :          4 :         NameInfoRequest req = {};
    1026                 :            :         struct iovec iov[2];
    1027                 :            :         struct msghdr mh;
    1028                 :            :         int r;
    1029                 :            : 
    1030   [ -  +  -  + ]:          4 :         assert_return(resolve, -EINVAL);
    1031   [ -  +  -  + ]:          4 :         assert_return(sa, -EINVAL);
    1032   [ -  +  -  + ]:          4 :         assert_return(salen >= sizeof(struct sockaddr), -EINVAL);
    1033   [ -  +  -  + ]:          4 :         assert_return(salen <= sizeof(union sockaddr_union), -EINVAL);
    1034   [ -  +  -  + ]:          4 :         assert_return((get & ~SD_RESOLVE_GET_BOTH) == 0, -EINVAL);
    1035   [ -  +  -  + ]:          4 :         assert_return(callback, -EINVAL);
    1036   [ -  +  -  + ]:          4 :         assert_return(!resolve_pid_changed(resolve), -ECHILD);
    1037                 :            : 
    1038                 :          4 :         r = alloc_query(resolve, !ret_query, &q);
    1039         [ -  + ]:          4 :         if (r < 0)
    1040                 :          0 :                 return r;
    1041                 :            : 
    1042                 :          4 :         q->type = REQUEST_NAMEINFO;
    1043                 :          4 :         q->getnameinfo_handler = callback;
    1044                 :          4 :         q->userdata = userdata;
    1045                 :            : 
    1046                 :          4 :         req = (NameInfoRequest) {
    1047                 :          4 :                 .header.id = q->id,
    1048                 :            :                 .header.type = REQUEST_NAMEINFO,
    1049                 :          4 :                 .header.length = sizeof(NameInfoRequest) + salen,
    1050                 :            : 
    1051                 :            :                 .flags = flags,
    1052                 :            :                 .sockaddr_len = salen,
    1053                 :          4 :                 .gethost = !!(get & SD_RESOLVE_GET_HOST),
    1054                 :          4 :                 .getserv = !!(get & SD_RESOLVE_GET_SERVICE),
    1055                 :            :         };
    1056                 :            : 
    1057                 :            :         msan_unpoison(&req, sizeof(req));
    1058                 :            : 
    1059                 :          4 :         iov[0] = IOVEC_MAKE(&req, sizeof(NameInfoRequest));
    1060                 :          4 :         iov[1] = IOVEC_MAKE((void*) sa, salen);
    1061                 :            : 
    1062                 :          4 :         mh = (struct msghdr) {
    1063                 :            :                 .msg_iov = iov,
    1064                 :            :                 .msg_iovlen = ELEMENTSOF(iov)
    1065                 :            :         };
    1066                 :            : 
    1067         [ -  + ]:          4 :         if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0)
    1068                 :          0 :                 return -errno;
    1069                 :            : 
    1070                 :          4 :         resolve->n_outstanding++;
    1071                 :          4 :         q->destroy_callback = destroy_callback;
    1072                 :            : 
    1073         [ +  - ]:          4 :         if (ret_query)
    1074                 :          4 :                 *ret_query = q;
    1075                 :            : 
    1076                 :          4 :         TAKE_PTR(q);
    1077                 :            : 
    1078                 :          4 :         return 0;
    1079                 :            : }
    1080                 :            : 
    1081                 :          4 : _public_ int sd_resolve_getnameinfo(
    1082                 :            :                 sd_resolve *resolve,
    1083                 :            :                 sd_resolve_query **ret_query,
    1084                 :            :                 const struct sockaddr *sa, socklen_t salen,
    1085                 :            :                 int flags,
    1086                 :            :                 uint64_t get,
    1087                 :            :                 sd_resolve_getnameinfo_handler_t callback,
    1088                 :            :                 void *userdata) {
    1089                 :            : 
    1090                 :          4 :         return resolve_getnameinfo_with_destroy_callback(resolve, ret_query, sa, salen, flags, get, callback, NULL, userdata);
    1091                 :            : }
    1092                 :            : 
    1093                 :          4 : static int getnameinfo_done(sd_resolve_query *q) {
    1094                 :            : 
    1095         [ -  + ]:          4 :         assert(q);
    1096         [ -  + ]:          4 :         assert(q->done);
    1097         [ -  + ]:          4 :         assert(q->getnameinfo_handler);
    1098                 :            : 
    1099                 :          4 :         errno = q->_errno;
    1100                 :          4 :         h_errno = q->_h_errno;
    1101                 :            : 
    1102                 :          4 :         return q->getnameinfo_handler(q, q->ret, q->host, q->serv, q->userdata);
    1103                 :            : }
    1104                 :            : 
    1105                 :         12 : static void resolve_freeaddrinfo(struct addrinfo *ai) {
    1106         [ +  + ]:         36 :         while (ai) {
    1107                 :         24 :                 struct addrinfo *next = ai->ai_next;
    1108                 :            : 
    1109                 :         24 :                 free(ai->ai_addr);
    1110                 :         24 :                 free(ai->ai_canonname);
    1111                 :         24 :                 free(ai);
    1112                 :         24 :                 ai = next;
    1113                 :            :         }
    1114                 :         12 : }
    1115                 :            : 
    1116                 :         16 : static void resolve_query_disconnect(sd_resolve_query *q) {
    1117                 :            :         sd_resolve *resolve;
    1118                 :            :         unsigned i;
    1119                 :            : 
    1120         [ -  + ]:         16 :         assert(q);
    1121                 :            : 
    1122         [ +  + ]:         16 :         if (!q->resolve)
    1123                 :          4 :                 return;
    1124                 :            : 
    1125                 :         12 :         resolve = q->resolve;
    1126         [ -  + ]:         12 :         assert(resolve->n_queries > 0);
    1127                 :            : 
    1128         [ +  - ]:         12 :         if (q->done) {
    1129         [ -  + ]:         12 :                 assert(resolve->n_done > 0);
    1130                 :         12 :                 resolve->n_done--;
    1131                 :            :         }
    1132                 :            : 
    1133                 :         12 :         i = q->id % QUERIES_MAX;
    1134         [ -  + ]:         12 :         assert(resolve->query_array[i] == q);
    1135                 :         12 :         resolve->query_array[i] = NULL;
    1136   [ -  +  +  +  :         12 :         LIST_REMOVE(queries, resolve->queries, q);
             +  +  -  + ]
    1137                 :         12 :         resolve->n_queries--;
    1138                 :            : 
    1139                 :         12 :         q->resolve = NULL;
    1140         [ +  + ]:         12 :         if (!q->floating)
    1141                 :          8 :                 sd_resolve_unref(resolve);
    1142                 :            : }
    1143                 :            : 
    1144                 :         12 : static sd_resolve_query *resolve_query_free(sd_resolve_query *q) {
    1145         [ -  + ]:         12 :         assert(q);
    1146                 :            : 
    1147                 :         12 :         resolve_query_disconnect(q);
    1148                 :            : 
    1149         [ -  + ]:         12 :         if (q->destroy_callback)
    1150                 :          0 :                 q->destroy_callback(q->userdata);
    1151                 :            : 
    1152                 :         12 :         resolve_freeaddrinfo(q->addrinfo);
    1153                 :         12 :         free(q->host);
    1154                 :         12 :         free(q->serv);
    1155                 :            : 
    1156                 :         12 :         return mfree(q);
    1157                 :            : }
    1158                 :            : 
    1159   [ +  +  -  +  :         40 : DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_resolve_query, sd_resolve_query, resolve_query_free);
                   +  + ]
    1160                 :            : 
    1161                 :          0 : _public_ int sd_resolve_query_is_done(sd_resolve_query *q) {
    1162   [ #  #  #  # ]:          0 :         assert_return(q, -EINVAL);
    1163   [ #  #  #  # ]:          0 :         assert_return(!resolve_pid_changed(q->resolve), -ECHILD);
    1164                 :            : 
    1165                 :          0 :         return q->done;
    1166                 :            : }
    1167                 :            : 
    1168                 :          0 : _public_ void* sd_resolve_query_set_userdata(sd_resolve_query *q, void *userdata) {
    1169                 :            :         void *ret;
    1170                 :            : 
    1171   [ #  #  #  # ]:          0 :         assert_return(q, NULL);
    1172   [ #  #  #  # ]:          0 :         assert_return(!resolve_pid_changed(q->resolve), NULL);
    1173                 :            : 
    1174                 :          0 :         ret = q->userdata;
    1175                 :          0 :         q->userdata = userdata;
    1176                 :            : 
    1177                 :          0 :         return ret;
    1178                 :            : }
    1179                 :            : 
    1180                 :          0 : _public_ void* sd_resolve_query_get_userdata(sd_resolve_query *q) {
    1181   [ #  #  #  # ]:          0 :         assert_return(q, NULL);
    1182   [ #  #  #  # ]:          0 :         assert_return(!resolve_pid_changed(q->resolve), NULL);
    1183                 :            : 
    1184                 :          0 :         return q->userdata;
    1185                 :            : }
    1186                 :            : 
    1187                 :          0 : _public_ sd_resolve *sd_resolve_query_get_resolve(sd_resolve_query *q) {
    1188   [ #  #  #  # ]:          0 :         assert_return(q, NULL);
    1189   [ #  #  #  # ]:          0 :         assert_return(!resolve_pid_changed(q->resolve), NULL);
    1190                 :            : 
    1191                 :          0 :         return q->resolve;
    1192                 :            : }
    1193                 :            : 
    1194                 :          0 : _public_ int sd_resolve_query_get_destroy_callback(sd_resolve_query *q, sd_resolve_destroy_t *destroy_callback) {
    1195   [ #  #  #  # ]:          0 :         assert_return(q, -EINVAL);
    1196                 :            : 
    1197         [ #  # ]:          0 :         if (destroy_callback)
    1198                 :          0 :                 *destroy_callback = q->destroy_callback;
    1199                 :            : 
    1200                 :          0 :         return !!q->destroy_callback;
    1201                 :            : }
    1202                 :            : 
    1203                 :          0 : _public_ int sd_resolve_query_set_destroy_callback(sd_resolve_query *q, sd_resolve_destroy_t destroy_callback) {
    1204   [ #  #  #  # ]:          0 :         assert_return(q, -EINVAL);
    1205                 :            : 
    1206                 :          0 :         q->destroy_callback = destroy_callback;
    1207                 :          0 :         return 0;
    1208                 :            : }
    1209                 :            : 
    1210                 :          0 : _public_ int sd_resolve_query_get_floating(sd_resolve_query *q) {
    1211   [ #  #  #  # ]:          0 :         assert_return(q, -EINVAL);
    1212                 :            : 
    1213                 :          0 :         return q->floating;
    1214                 :            : }
    1215                 :            : 
    1216                 :          0 : _public_ int sd_resolve_query_set_floating(sd_resolve_query *q, int b) {
    1217   [ #  #  #  # ]:          0 :         assert_return(q, -EINVAL);
    1218                 :            : 
    1219         [ #  # ]:          0 :         if (q->floating == !!b)
    1220                 :          0 :                 return 0;
    1221                 :            : 
    1222         [ #  # ]:          0 :         if (!q->resolve) /* Already disconnected */
    1223                 :          0 :                 return -ESTALE;
    1224                 :            : 
    1225                 :          0 :         q->floating = b;
    1226                 :            : 
    1227         [ #  # ]:          0 :         if (b) {
    1228                 :          0 :                 sd_resolve_query_ref(q);
    1229                 :          0 :                 sd_resolve_unref(q->resolve);
    1230                 :            :         } else {
    1231                 :          0 :                 sd_resolve_ref(q->resolve);
    1232                 :          0 :                 sd_resolve_query_unref(q);
    1233                 :            :         }
    1234                 :            : 
    1235                 :          0 :         return 1;
    1236                 :            : }
    1237                 :            : 
    1238                 :          0 : static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
    1239                 :          0 :         sd_resolve *resolve = userdata;
    1240                 :            :         int r;
    1241                 :            : 
    1242         [ #  # ]:          0 :         assert(resolve);
    1243                 :            : 
    1244                 :          0 :         r = sd_resolve_process(resolve);
    1245         [ #  # ]:          0 :         if (r < 0)
    1246                 :          0 :                 return r;
    1247                 :            : 
    1248                 :          0 :         return 1;
    1249                 :            : }
    1250                 :            : 
    1251                 :          8 : _public_ int sd_resolve_attach_event(sd_resolve *resolve, sd_event *event, int64_t priority) {
    1252                 :            :         int r;
    1253                 :            : 
    1254   [ -  +  -  + ]:          8 :         assert_return(resolve, -EINVAL);
    1255   [ -  +  -  + ]:          8 :         assert_return(!resolve->event, -EBUSY);
    1256                 :            : 
    1257         [ -  + ]:          8 :         assert(!resolve->event_source);
    1258                 :            : 
    1259         [ +  - ]:          8 :         if (event)
    1260                 :          8 :                 resolve->event = sd_event_ref(event);
    1261                 :            :         else {
    1262                 :          0 :                 r = sd_event_default(&resolve->event);
    1263         [ #  # ]:          0 :                 if (r < 0)
    1264                 :          0 :                         return r;
    1265                 :            :         }
    1266                 :            : 
    1267                 :          8 :         r = sd_event_add_io(resolve->event, &resolve->event_source, resolve->fds[RESPONSE_RECV_FD], POLLIN, io_callback, resolve);
    1268         [ -  + ]:          8 :         if (r < 0)
    1269                 :          0 :                 goto fail;
    1270                 :            : 
    1271                 :          8 :         r = sd_event_source_set_priority(resolve->event_source, priority);
    1272         [ -  + ]:          8 :         if (r < 0)
    1273                 :          0 :                 goto fail;
    1274                 :            : 
    1275                 :          8 :         return 0;
    1276                 :            : 
    1277                 :          0 : fail:
    1278                 :          0 :         sd_resolve_detach_event(resolve);
    1279                 :          0 :         return r;
    1280                 :            : }
    1281                 :            : 
    1282                 :         12 : _public_  int sd_resolve_detach_event(sd_resolve *resolve) {
    1283   [ -  +  -  + ]:         12 :         assert_return(resolve, -EINVAL);
    1284                 :            : 
    1285         [ +  + ]:         12 :         if (!resolve->event)
    1286                 :          4 :                 return 0;
    1287                 :            : 
    1288         [ +  - ]:          8 :         if (resolve->event_source) {
    1289                 :          8 :                 sd_event_source_set_enabled(resolve->event_source, SD_EVENT_OFF);
    1290                 :          8 :                 resolve->event_source = sd_event_source_unref(resolve->event_source);
    1291                 :            :         }
    1292                 :            : 
    1293                 :          8 :         resolve->event = sd_event_unref(resolve->event);
    1294                 :          8 :         return 1;
    1295                 :            : }
    1296                 :            : 
    1297                 :          0 : _public_ sd_event *sd_resolve_get_event(sd_resolve *resolve) {
    1298   [ #  #  #  # ]:          0 :         assert_return(resolve, NULL);
    1299                 :            : 
    1300                 :          0 :         return resolve->event;
    1301                 :            : }

Generated by: LCOV version 1.14