LCOV - code coverage report
Current view: top level - libsystemd/sd-resolve - sd-resolve.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 451 600 75.2 %
Date: 2019-08-22 15:41:25 Functions: 34 48 70.8 %

          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           3 : static void query_assign_errno(sd_resolve_query *q, int ret, int error, int h_error) {
     170           3 :         assert(q);
     171             : 
     172           3 :         q->ret = ret;
     173           3 :         q->_errno = abs(error);
     174           3 :         q->_h_errno = h_error;
     175           3 : }
     176             : 
     177           3 : static int send_died(int out_fd) {
     178           3 :         RHeader rh = {
     179             :                 .type = RESPONSE_DIED,
     180             :                 .length = sizeof(RHeader),
     181             :         };
     182             : 
     183           3 :         assert(out_fd >= 0);
     184             : 
     185           3 :         if (send(out_fd, &rh, rh.length, MSG_NOSIGNAL) < 0)
     186           0 :                 return -errno;
     187             : 
     188           3 :         return 0;
     189             : }
     190             : 
     191           6 : 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           6 :         assert(p);
     196           6 :         assert(ai);
     197           6 :         assert(length);
     198           6 :         assert(*length <= maxlength);
     199             : 
     200           6 :         cnl = ai->ai_canonname ? strlen(ai->ai_canonname)+1 : 0;
     201           6 :         l = sizeof(AddrInfoSerialization) + ai->ai_addrlen + cnl;
     202             : 
     203           6 :         if (*length + l > maxlength)
     204           0 :                 return NULL;
     205             : 
     206           6 :         s = (AddrInfoSerialization) {
     207           6 :                 .ai_flags = ai->ai_flags,
     208           6 :                 .ai_family = ai->ai_family,
     209           6 :                 .ai_socktype = ai->ai_socktype,
     210           6 :                 .ai_protocol = ai->ai_protocol,
     211           6 :                 .ai_addrlen = ai->ai_addrlen,
     212             :                 .canonname_len = cnl,
     213             :         };
     214             : 
     215           6 :         memcpy((uint8_t*) p, &s, sizeof(AddrInfoSerialization));
     216           6 :         memcpy((uint8_t*) p + sizeof(AddrInfoSerialization), ai->ai_addr, ai->ai_addrlen);
     217           6 :         memcpy_safe((char*) p + sizeof(AddrInfoSerialization) + ai->ai_addrlen,
     218           6 :                     ai->ai_canonname, cnl);
     219             : 
     220           6 :         *length += l;
     221           6 :         return (uint8_t*) p + l;
     222             : }
     223             : 
     224           2 : 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           2 :         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           2 :         assert(out_fd >= 0);
     241             : 
     242           2 :         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           2 :         if (ret == 0 && ai) {
     254           2 :                 void *p = &buffer;
     255             :                 struct addrinfo *k;
     256             : 
     257           8 :                 for (k = ai; k; k = k->ai_next) {
     258           6 :                         p = serialize_addrinfo(p, k, &resp.header.length, (uint8_t*) &buffer + BUFSIZE - (uint8_t*) p);
     259           6 :                         if (!p) {
     260           0 :                                 freeaddrinfo(ai);
     261           0 :                                 return -ENOBUFS;
     262             :                         }
     263             :                 }
     264             :         }
     265             : 
     266           2 :         if (ai)
     267           2 :                 freeaddrinfo(ai);
     268             : 
     269           2 :         iov[0] = IOVEC_MAKE(&resp, sizeof(AddrInfoResponse));
     270           2 :         iov[1] = IOVEC_MAKE(&buffer, resp.header.length - sizeof(AddrInfoResponse));
     271             : 
     272           2 :         mh = (struct msghdr) {
     273             :                 .msg_iov = iov,
     274             :                 .msg_iovlen = ELEMENTSOF(iov)
     275             :         };
     276             : 
     277           2 :         if (sendmsg(out_fd, &mh, MSG_NOSIGNAL) < 0)
     278           0 :                 return -errno;
     279             : 
     280           2 :         return 0;
     281             : }
     282             : 
     283           1 : 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           1 :         NameInfoResponse resp = {};
     293             :         struct iovec iov[3];
     294             :         struct msghdr mh;
     295             :         size_t hl, sl;
     296             : 
     297           1 :         assert(out_fd >= 0);
     298             : 
     299           1 :         sl = serv ? strlen(serv)+1 : 0;
     300           1 :         hl = host ? strlen(host)+1 : 0;
     301             : 
     302           1 :         resp = (NameInfoResponse) {
     303             :                 .header.type = RESPONSE_NAMEINFO,
     304             :                 .header.id = id,
     305           1 :                 .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           1 :         iov[0] = IOVEC_MAKE(&resp, sizeof(NameInfoResponse));
     316           1 :         iov[1] = IOVEC_MAKE((void*) host, hl);
     317           1 :         iov[2] = IOVEC_MAKE((void*) serv, sl);
     318             : 
     319           1 :         mh = (struct msghdr) {
     320             :                 .msg_iov = iov,
     321             :                 .msg_iovlen = ELEMENTSOF(iov)
     322             :         };
     323             : 
     324           1 :         if (sendmsg(out_fd, &mh, MSG_NOSIGNAL) < 0)
     325           0 :                 return -errno;
     326             : 
     327           1 :         return 0;
     328             : }
     329             : 
     330           6 : static int handle_request(int out_fd, const Packet *packet, size_t length) {
     331             :         const RHeader *req;
     332             : 
     333           6 :         assert(out_fd >= 0);
     334           6 :         assert(packet);
     335             : 
     336           6 :         req = &packet->rheader;
     337             : 
     338           6 :         assert_return(length >= sizeof(RHeader), -EIO);
     339           6 :         assert_return(length == req->length, -EIO);
     340             : 
     341           6 :         switch (req->type) {
     342             : 
     343           2 :         case REQUEST_ADDRINFO: {
     344           2 :                const AddrInfoRequest *ai_req = &packet->addrinfo_request;
     345           2 :                struct addrinfo hints, *result = NULL;
     346             :                const char *node, *service;
     347             :                int ret;
     348             : 
     349           2 :                assert_return(length >= sizeof(AddrInfoRequest), -EBADMSG);
     350           2 :                assert_return(length == sizeof(AddrInfoRequest) + ai_req->node_len + ai_req->service_len, -EBADMSG);
     351             : 
     352           2 :                hints = (struct addrinfo) {
     353           2 :                        .ai_flags = ai_req->ai_flags,
     354           2 :                        .ai_family = ai_req->ai_family,
     355           2 :                        .ai_socktype = ai_req->ai_socktype,
     356           2 :                        .ai_protocol = ai_req->ai_protocol,
     357             :                };
     358             : 
     359             :                msan_unpoison(&hints, sizeof(hints));
     360             : 
     361           2 :                node = ai_req->node_len ? (const char*) ai_req + sizeof(AddrInfoRequest) : NULL;
     362           2 :                service = ai_req->service_len ? (const char*) ai_req + sizeof(AddrInfoRequest) + ai_req->node_len : NULL;
     363             : 
     364           2 :                ret = getaddrinfo(node, service,
     365           2 :                                  ai_req->hints_valid ? &hints : NULL,
     366             :                                  &result);
     367             : 
     368             :                /* send_addrinfo_reply() frees result */
     369           2 :                return send_addrinfo_reply(out_fd, req->id, ret, result, errno, h_errno);
     370             :         }
     371             : 
     372           1 :         case REQUEST_NAMEINFO: {
     373           1 :                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           1 :                assert_return(length >= sizeof(NameInfoRequest), -EBADMSG);
     379           1 :                assert_return(length == sizeof(NameInfoRequest) + ni_req->sockaddr_len, -EBADMSG);
     380           1 :                assert_return(ni_req->sockaddr_len <= sizeof(sa), -EBADMSG);
     381             : 
     382           1 :                memcpy(&sa, (const uint8_t *) ni_req + sizeof(NameInfoRequest), ni_req->sockaddr_len);
     383             : 
     384           3 :                ret = getnameinfo(&sa.sa, ni_req->sockaddr_len,
     385           2 :                                  ni_req->gethost ? hostbuf : NULL, ni_req->gethost ? sizeof(hostbuf) : 0,
     386           1 :                                  ni_req->getserv ? servbuf : NULL, ni_req->getserv ? sizeof(servbuf) : 0,
     387             :                                  ni_req->flags);
     388             : 
     389           2 :                return send_nameinfo_reply(out_fd, req->id, ret,
     390           1 :                                           ret == 0 && ni_req->gethost ? hostbuf : NULL,
     391           1 :                                           ret == 0 && ni_req->getserv ? servbuf : NULL,
     392           1 :                                           errno, h_errno);
     393             :         }
     394             : 
     395           3 :         case REQUEST_TERMINATE:
     396             :                  /* Quit */
     397           3 :                  return -ECONNRESET;
     398             : 
     399           0 :         default:
     400           0 :                 assert_not_reached("Unknown request");
     401             :         }
     402             : 
     403             :         return 0;
     404             : }
     405             : 
     406           3 : static void* thread_worker(void *p) {
     407           3 :         sd_resolve *resolve = p;
     408             : 
     409             :         /* Assign a pretty name to this thread */
     410           3 :         (void) pthread_setname_np(pthread_self(), "sd-resolve");
     411             : 
     412           6 :         while (!resolve->dead) {
     413             :                 union {
     414             :                         Packet packet;
     415             :                         uint8_t space[BUFSIZE];
     416             :                 } buf;
     417             :                 ssize_t length;
     418             : 
     419           6 :                 length = recv(resolve->fds[REQUEST_RECV_FD], &buf, sizeof buf, 0);
     420           6 :                 if (length < 0) {
     421           0 :                         if (errno == EINTR)
     422           0 :                                 continue;
     423             : 
     424           3 :                         break;
     425             :                 }
     426           6 :                 if (length == 0)
     427           0 :                         break;
     428             : 
     429           6 :                 if (handle_request(resolve->fds[RESPONSE_SEND_FD], &buf.packet, (size_t) length) < 0)
     430           3 :                         break;
     431             :         }
     432             : 
     433           3 :         send_died(resolve->fds[RESPONSE_SEND_FD]);
     434             : 
     435           3 :         return NULL;
     436             : }
     437             : 
     438           3 : static int start_threads(sd_resolve *resolve, unsigned extra) {
     439             :         sigset_t ss, saved_ss;
     440             :         unsigned n;
     441             :         int r, k;
     442             : 
     443           3 :         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           3 :         r = pthread_sigmask(SIG_BLOCK, &ss, &saved_ss);
     448           3 :         if (r > 0)
     449           0 :                 return -r;
     450             : 
     451           3 :         n = resolve->n_outstanding + extra;
     452           3 :         n = CLAMP(n, WORKERS_MIN, WORKERS_MAX);
     453             : 
     454           6 :         while (resolve->n_valid_workers < n) {
     455           3 :                 r = pthread_create(&resolve->workers[resolve->n_valid_workers], NULL, thread_worker, resolve);
     456           3 :                 if (r > 0) {
     457           0 :                         r = -r;
     458           0 :                         goto finish;
     459             :                 }
     460             : 
     461           3 :                 resolve->n_valid_workers++;
     462             :         }
     463             : 
     464           3 :         r = 0;
     465             : 
     466           3 : finish:
     467           3 :         k = pthread_sigmask(SIG_SETMASK, &saved_ss, NULL);
     468           3 :         if (k > 0 && r >= 0)
     469           0 :                 r = -k;
     470             : 
     471           3 :         return r;
     472             : }
     473             : 
     474          10 : static bool resolve_pid_changed(sd_resolve *r) {
     475          10 :         assert(r);
     476             : 
     477             :         /* We don't support people creating a resolver and keeping it
     478             :          * around after fork(). Let's complain. */
     479             : 
     480          10 :         return r->original_pid != getpid_cached();
     481             : }
     482             : 
     483           3 : _public_ int sd_resolve_new(sd_resolve **ret) {
     484           3 :         _cleanup_(sd_resolve_unrefp) sd_resolve *resolve = NULL;
     485             :         int i;
     486             : 
     487           3 :         assert_return(ret, -EINVAL);
     488             : 
     489           3 :         resolve = new0(sd_resolve, 1);
     490           3 :         if (!resolve)
     491           0 :                 return -ENOMEM;
     492             : 
     493           3 :         resolve->n_ref = 1;
     494           3 :         resolve->original_pid = getpid_cached();
     495             : 
     496          15 :         for (i = 0; i < _FD_MAX; i++)
     497          12 :                 resolve->fds[i] = -1;
     498             : 
     499           3 :         if (socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds + REQUEST_RECV_FD) < 0)
     500           0 :                 return -errno;
     501             : 
     502           3 :         if (socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds + RESPONSE_RECV_FD) < 0)
     503           0 :                 return -errno;
     504             : 
     505          15 :         for (i = 0; i < _FD_MAX; i++)
     506          12 :                 resolve->fds[i] = fd_move_above_stdio(resolve->fds[i]);
     507             : 
     508           3 :         (void) fd_inc_sndbuf(resolve->fds[REQUEST_SEND_FD], QUERIES_MAX * BUFSIZE);
     509           3 :         (void) fd_inc_rcvbuf(resolve->fds[REQUEST_RECV_FD], QUERIES_MAX * BUFSIZE);
     510           3 :         (void) fd_inc_sndbuf(resolve->fds[RESPONSE_SEND_FD], QUERIES_MAX * BUFSIZE);
     511           3 :         (void) fd_inc_rcvbuf(resolve->fds[RESPONSE_RECV_FD], QUERIES_MAX * BUFSIZE);
     512             : 
     513           3 :         (void) fd_nonblock(resolve->fds[RESPONSE_RECV_FD], true);
     514             : 
     515           3 :         *ret = TAKE_PTR(resolve);
     516           3 :         return 0;
     517             : }
     518             : 
     519           3 : _public_ int sd_resolve_default(sd_resolve **ret) {
     520             :         static thread_local sd_resolve *default_resolve = NULL;
     521           3 :         sd_resolve *e = NULL;
     522             :         int r;
     523             : 
     524           3 :         if (!ret)
     525           0 :                 return !!default_resolve;
     526             : 
     527           3 :         if (default_resolve) {
     528           0 :                 *ret = sd_resolve_ref(default_resolve);
     529           0 :                 return 0;
     530             :         }
     531             : 
     532           3 :         r = sd_resolve_new(&e);
     533           3 :         if (r < 0)
     534           0 :                 return r;
     535             : 
     536           3 :         e->default_resolve_ptr = &default_resolve;
     537           3 :         e->tid = gettid();
     538           3 :         default_resolve = e;
     539             : 
     540           3 :         *ret = e;
     541           3 :         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           3 : static sd_resolve *resolve_free(sd_resolve *resolve) {
     561           3 :         PROTECT_ERRNO;
     562             :         sd_resolve_query *q;
     563             :         unsigned i;
     564             : 
     565           3 :         assert(resolve);
     566             : 
     567           3 :         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           3 :         if (resolve->default_resolve_ptr)
     574           3 :                 *(resolve->default_resolve_ptr) = NULL;
     575             : 
     576           3 :         resolve->dead = true;
     577             : 
     578           3 :         sd_resolve_detach_event(resolve);
     579             : 
     580           3 :         if (resolve->fds[REQUEST_SEND_FD] >= 0) {
     581             : 
     582           3 :                 RHeader req = {
     583             :                         .type = REQUEST_TERMINATE,
     584             :                         .length = sizeof req,
     585             :                 };
     586             : 
     587             :                 /* Send one termination packet for each worker */
     588           6 :                 for (i = 0; i < resolve->n_valid_workers; i++)
     589           3 :                         (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           6 :         for (i = 0; i < resolve->n_valid_workers; i++)
     595           3 :                 (void) pthread_join(resolve->workers[i], NULL);
     596             : 
     597             :         /* Close all communication channels */
     598           3 :         close_many(resolve->fds, _FD_MAX);
     599             : 
     600           3 :         return mfree(resolve);
     601             : }
     602             : 
     603          17 : 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           3 : static sd_resolve_query *lookup_query(sd_resolve *resolve, unsigned id) {
     629             :         sd_resolve_query *q;
     630             : 
     631           3 :         assert(resolve);
     632             : 
     633           3 :         q = resolve->query_array[id % QUERIES_MAX];
     634           3 :         if (q)
     635           3 :                 if (q->id == id)
     636           3 :                         return q;
     637             : 
     638           0 :         return NULL;
     639             : }
     640             : 
     641           3 : static int complete_query(sd_resolve *resolve, sd_resolve_query *q) {
     642             :         int r;
     643             : 
     644           3 :         assert(q);
     645           3 :         assert(!q->done);
     646           3 :         assert(q->resolve == resolve);
     647             : 
     648           3 :         q->done = true;
     649           3 :         resolve->n_done++;
     650             : 
     651           3 :         resolve->current = sd_resolve_query_ref(q);
     652             : 
     653           3 :         switch (q->type) {
     654             : 
     655           2 :         case REQUEST_ADDRINFO:
     656           2 :                 r = getaddrinfo_done(q);
     657           2 :                 break;
     658             : 
     659           1 :         case REQUEST_NAMEINFO:
     660           1 :                 r = getnameinfo_done(q);
     661           1 :                 break;
     662             : 
     663           0 :         default:
     664           0 :                 assert_not_reached("Cannot complete unknown query type");
     665             :         }
     666             : 
     667           3 :         resolve->current = NULL;
     668             : 
     669           3 :         if (q->floating) {
     670           1 :                 resolve_query_disconnect(q);
     671           1 :                 sd_resolve_query_unref(q);
     672             :         }
     673             : 
     674           3 :         sd_resolve_query_unref(q);
     675             : 
     676           3 :         return r;
     677             : }
     678             : 
     679           6 : 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           6 :         assert(p);
     685           6 :         assert(*p);
     686           6 :         assert(ret_ai);
     687           6 :         assert(length);
     688             : 
     689           6 :         if (*length < sizeof(AddrInfoSerialization))
     690           0 :                 return -EBADMSG;
     691             : 
     692           6 :         memcpy(&s, *p, sizeof(s));
     693             : 
     694           6 :         l = sizeof(AddrInfoSerialization) + s.ai_addrlen + s.canonname_len;
     695           6 :         if (*length < l)
     696           0 :                 return -EBADMSG;
     697             : 
     698           6 :         ai = new(struct addrinfo, 1);
     699           6 :         if (!ai)
     700           0 :                 return -ENOMEM;
     701             : 
     702           6 :         *ai = (struct addrinfo) {
     703           6 :                 .ai_flags = s.ai_flags,
     704           6 :                 .ai_family = s.ai_family,
     705           6 :                 .ai_socktype = s.ai_socktype,
     706           6 :                 .ai_protocol = s.ai_protocol,
     707           6 :                 .ai_addrlen = s.ai_addrlen,
     708             :         };
     709             : 
     710           6 :         if (s.ai_addrlen > 0) {
     711           6 :                 ai->ai_addr = memdup((const uint8_t*) *p + sizeof(AddrInfoSerialization), s.ai_addrlen);
     712           6 :                 if (!ai->ai_addr) {
     713           0 :                         free(ai);
     714           0 :                         return -ENOMEM;
     715             :                 }
     716             :         }
     717             : 
     718           6 :         if (s.canonname_len > 0) {
     719           1 :                 ai->ai_canonname = memdup((const uint8_t*) *p + sizeof(AddrInfoSerialization) + s.ai_addrlen, s.canonname_len);
     720           1 :                 if (!ai->ai_canonname) {
     721           0 :                         free(ai->ai_addr);
     722           0 :                         free(ai);
     723           0 :                         return -ENOMEM;
     724             :                 }
     725             :         }
     726             : 
     727           6 :         *length -= l;
     728           6 :         *ret_ai = ai;
     729           6 :         *p = ((const uint8_t*) *p) + l;
     730             : 
     731           6 :         return 0;
     732             : }
     733             : 
     734           3 : 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           3 :         assert(resolve);
     740           3 :         assert(packet);
     741             : 
     742           3 :         resp = &packet->rheader;
     743           3 :         assert_return(length >= sizeof(RHeader), -EIO);
     744           3 :         assert_return(length == resp->length, -EIO);
     745             : 
     746           3 :         if (resp->type == RESPONSE_DIED) {
     747           0 :                 resolve->dead = true;
     748           0 :                 return 0;
     749             :         }
     750             : 
     751           3 :         assert(resolve->n_outstanding > 0);
     752           3 :         resolve->n_outstanding--;
     753             : 
     754           3 :         q = lookup_query(resolve, resp->id);
     755           3 :         if (!q)
     756           0 :                 return 0;
     757             : 
     758           3 :         switch (resp->type) {
     759             : 
     760           2 :         case RESPONSE_ADDRINFO: {
     761           2 :                 const AddrInfoResponse *ai_resp = &packet->addrinfo_response;
     762             :                 const void *p;
     763             :                 size_t l;
     764           2 :                 struct addrinfo *prev = NULL;
     765             : 
     766           2 :                 assert_return(length >= sizeof(AddrInfoResponse), -EBADMSG);
     767           2 :                 assert_return(q->type == REQUEST_ADDRINFO, -EBADMSG);
     768             : 
     769           2 :                 query_assign_errno(q, ai_resp->ret, ai_resp->_errno, ai_resp->_h_errno);
     770             : 
     771           2 :                 l = length - sizeof(AddrInfoResponse);
     772           2 :                 p = (const uint8_t*) resp + sizeof(AddrInfoResponse);
     773             : 
     774           8 :                 while (l > 0 && p) {
     775           6 :                         struct addrinfo *ai = NULL;
     776             : 
     777           6 :                         r = unserialize_addrinfo(&p, &l, &ai);
     778           6 :                         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           6 :                         if (prev)
     786           4 :                                 prev->ai_next = ai;
     787             :                         else
     788           2 :                                 q->addrinfo = ai;
     789             : 
     790           6 :                         prev = ai;
     791             :                 }
     792             : 
     793           2 :                 return complete_query(resolve, q);
     794             :         }
     795             : 
     796           1 :         case RESPONSE_NAMEINFO: {
     797           1 :                 const NameInfoResponse *ni_resp = &packet->nameinfo_response;
     798             : 
     799           1 :                 assert_return(length >= sizeof(NameInfoResponse), -EBADMSG);
     800           1 :                 assert_return(q->type == REQUEST_NAMEINFO, -EBADMSG);
     801             : 
     802           1 :                 if (ni_resp->hostlen > DNS_HOSTNAME_MAX ||
     803           1 :                     ni_resp->servlen > DNS_HOSTNAME_MAX ||
     804           1 :                     sizeof(NameInfoResponse) + ni_resp->hostlen + ni_resp->servlen > length)
     805           0 :                         query_assign_errno(q, EAI_SYSTEM, EIO, 0);
     806             :                 else {
     807           1 :                         query_assign_errno(q, ni_resp->ret, ni_resp->_errno, ni_resp->_h_errno);
     808             : 
     809           1 :                         if (ni_resp->hostlen > 0) {
     810           1 :                                 q->host = strndup((const char*) ni_resp + sizeof(NameInfoResponse),
     811           1 :                                                   ni_resp->hostlen-1);
     812           1 :                                 if (!q->host)
     813           0 :                                         query_assign_errno(q, EAI_MEMORY, ENOMEM, 0);
     814             :                         }
     815             : 
     816           1 :                         if (ni_resp->servlen > 0) {
     817           1 :                                 q->serv = strndup((const char*) ni_resp + sizeof(NameInfoResponse) + ni_resp->hostlen,
     818           1 :                                                   ni_resp->servlen-1);
     819           1 :                                 if (!q->serv)
     820           0 :                                         query_assign_errno(q, EAI_MEMORY, ENOMEM, 0);
     821             :                         }
     822             :                 }
     823             : 
     824           1 :                 return complete_query(resolve, q);
     825             :         }
     826             : 
     827           0 :         default:
     828           0 :                 return 0;
     829             :         }
     830             : }
     831             : 
     832           3 : _public_ int sd_resolve_process(sd_resolve *resolve) {
     833           6 :         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           3 :         assert_return(resolve, -EINVAL);
     843           3 :         assert_return(!resolve_pid_changed(resolve), -ECHILD);
     844             : 
     845             :         /* We don't allow recursively invoking sd_resolve_process(). */
     846           3 :         assert_return(!resolve->current, -EBUSY);
     847             : 
     848           3 :         l = recv(resolve->fds[RESPONSE_RECV_FD], &buf, sizeof buf, 0);
     849           3 :         if (l < 0) {
     850           0 :                 if (errno == EAGAIN)
     851           0 :                         return 0;
     852             : 
     853           0 :                 return -errno;
     854             :         }
     855           3 :         if (l == 0)
     856           0 :                 return -ECONNREFUSED;
     857             : 
     858           3 :         r = handle_response(resolve, &buf.packet, (size_t) l);
     859           3 :         if (r < 0)
     860           0 :                 return r;
     861             : 
     862           3 :         return 1;
     863             : }
     864             : 
     865           4 : _public_ int sd_resolve_wait(sd_resolve *resolve, uint64_t timeout_usec) {
     866             :         int r;
     867             : 
     868           4 :         assert_return(resolve, -EINVAL);
     869           4 :         assert_return(!resolve_pid_changed(resolve), -ECHILD);
     870             : 
     871           4 :         if (resolve->n_done >= resolve->n_queries)
     872           1 :                 return 0;
     873             : 
     874             :         do {
     875           3 :                 r = fd_wait_for_event(resolve->fds[RESPONSE_RECV_FD], POLLIN, timeout_usec);
     876           3 :         } while (r == -EINTR);
     877             : 
     878           3 :         if (r < 0)
     879           0 :                 return r;
     880           3 :         if (r == 0)
     881           0 :                 return -ETIMEDOUT;
     882             : 
     883           3 :         return sd_resolve_process(resolve);
     884             : }
     885             : 
     886           3 : static int alloc_query(sd_resolve *resolve, bool floating, sd_resolve_query **_q) {
     887             :         sd_resolve_query *q;
     888             :         int r;
     889             : 
     890           3 :         assert(resolve);
     891           3 :         assert(_q);
     892             : 
     893           3 :         if (resolve->n_queries >= QUERIES_MAX)
     894           0 :                 return -ENOBUFS;
     895             : 
     896           3 :         r = start_threads(resolve, 1);
     897           3 :         if (r < 0)
     898           0 :                 return r;
     899             : 
     900           3 :         while (resolve->query_array[resolve->current_id % QUERIES_MAX])
     901           0 :                 resolve->current_id++;
     902             : 
     903           3 :         q = resolve->query_array[resolve->current_id % QUERIES_MAX] = new0(sd_resolve_query, 1);
     904           3 :         if (!q)
     905           0 :                 return -ENOMEM;
     906             : 
     907           3 :         q->n_ref = 1;
     908           3 :         q->resolve = resolve;
     909           3 :         q->floating = floating;
     910           3 :         q->id = resolve->current_id++;
     911             : 
     912           3 :         if (!floating)
     913           2 :                 sd_resolve_ref(resolve);
     914             : 
     915           3 :         LIST_PREPEND(queries, resolve->queries, q);
     916           3 :         resolve->n_queries++;
     917             : 
     918           3 :         *_q = q;
     919           3 :         return 0;
     920             : }
     921             : 
     922           2 : 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           2 :         _cleanup_(sd_resolve_query_unrefp) sd_resolve_query *q = NULL;
     932             :         size_t node_len, service_len;
     933           2 :         AddrInfoRequest req = {};
     934             :         struct iovec iov[3];
     935           2 :         struct msghdr mh = {};
     936             :         int r;
     937             : 
     938           2 :         assert_return(resolve, -EINVAL);
     939           2 :         assert_return(node || service, -EINVAL);
     940           2 :         assert_return(callback, -EINVAL);
     941           2 :         assert_return(!resolve_pid_changed(resolve), -ECHILD);
     942             : 
     943           2 :         r = alloc_query(resolve, !ret_query, &q);
     944           2 :         if (r < 0)
     945           0 :                 return r;
     946             : 
     947           2 :         q->type = REQUEST_ADDRINFO;
     948           2 :         q->getaddrinfo_handler = callback;
     949           2 :         q->userdata = userdata;
     950             : 
     951           2 :         node_len = node ? strlen(node) + 1 : 0;
     952           2 :         service_len = service ? strlen(service) + 1 : 0;
     953             : 
     954           4 :         req = (AddrInfoRequest) {
     955             :                 .node_len = node_len,
     956             :                 .service_len = service_len,
     957             : 
     958           2 :                 .header.id = q->id,
     959             :                 .header.type = REQUEST_ADDRINFO,
     960           2 :                 .header.length = sizeof(AddrInfoRequest) + node_len + service_len,
     961             : 
     962             :                 .hints_valid = hints,
     963           2 :                 .ai_flags = hints ? hints->ai_flags : 0,
     964           2 :                 .ai_family = hints ? hints->ai_family : 0,
     965           2 :                 .ai_socktype = hints ? hints->ai_socktype : 0,
     966           2 :                 .ai_protocol = hints ? hints->ai_protocol : 0,
     967             :         };
     968             : 
     969             :         msan_unpoison(&req, sizeof(req));
     970             : 
     971           2 :         iov[mh.msg_iovlen++] = IOVEC_MAKE(&req, sizeof(AddrInfoRequest));
     972           2 :         if (node)
     973           2 :                 iov[mh.msg_iovlen++] = IOVEC_MAKE((void*) node, req.node_len);
     974           2 :         if (service)
     975           1 :                 iov[mh.msg_iovlen++] = IOVEC_MAKE((void*) service, req.service_len);
     976           2 :         mh.msg_iov = iov;
     977             : 
     978           2 :         if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0)
     979           0 :                 return -errno;
     980             : 
     981           2 :         resolve->n_outstanding++;
     982           2 :         q->destroy_callback = destroy_callback;
     983             : 
     984           2 :         if (ret_query)
     985           1 :                 *ret_query = q;
     986             : 
     987           2 :         TAKE_PTR(q);
     988             : 
     989           2 :         return 0;
     990             : }
     991             : 
     992           2 : _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           2 :         return resolve_getaddrinfo_with_destroy_callback(resolve, ret_query, node, service, hints, callback, NULL, userdata);
    1001             : }
    1002             : 
    1003           2 : static int getaddrinfo_done(sd_resolve_query* q) {
    1004           2 :         assert(q);
    1005           2 :         assert(q->done);
    1006           2 :         assert(q->getaddrinfo_handler);
    1007             : 
    1008           2 :         errno = q->_errno;
    1009           2 :         h_errno = q->_h_errno;
    1010             : 
    1011           2 :         return q->getaddrinfo_handler(q, q->ret, q->addrinfo, q->userdata);
    1012             : }
    1013             : 
    1014           1 : 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           1 :         _cleanup_(sd_resolve_query_unrefp) sd_resolve_query *q = NULL;
    1025           1 :         NameInfoRequest req = {};
    1026             :         struct iovec iov[2];
    1027             :         struct msghdr mh;
    1028             :         int r;
    1029             : 
    1030           1 :         assert_return(resolve, -EINVAL);
    1031           1 :         assert_return(sa, -EINVAL);
    1032           1 :         assert_return(salen >= sizeof(struct sockaddr), -EINVAL);
    1033           1 :         assert_return(salen <= sizeof(union sockaddr_union), -EINVAL);
    1034           1 :         assert_return((get & ~SD_RESOLVE_GET_BOTH) == 0, -EINVAL);
    1035           1 :         assert_return(callback, -EINVAL);
    1036           1 :         assert_return(!resolve_pid_changed(resolve), -ECHILD);
    1037             : 
    1038           1 :         r = alloc_query(resolve, !ret_query, &q);
    1039           1 :         if (r < 0)
    1040           0 :                 return r;
    1041             : 
    1042           1 :         q->type = REQUEST_NAMEINFO;
    1043           1 :         q->getnameinfo_handler = callback;
    1044           1 :         q->userdata = userdata;
    1045             : 
    1046           1 :         req = (NameInfoRequest) {
    1047           1 :                 .header.id = q->id,
    1048             :                 .header.type = REQUEST_NAMEINFO,
    1049           1 :                 .header.length = sizeof(NameInfoRequest) + salen,
    1050             : 
    1051             :                 .flags = flags,
    1052             :                 .sockaddr_len = salen,
    1053           1 :                 .gethost = !!(get & SD_RESOLVE_GET_HOST),
    1054           1 :                 .getserv = !!(get & SD_RESOLVE_GET_SERVICE),
    1055             :         };
    1056             : 
    1057             :         msan_unpoison(&req, sizeof(req));
    1058             : 
    1059           1 :         iov[0] = IOVEC_MAKE(&req, sizeof(NameInfoRequest));
    1060           1 :         iov[1] = IOVEC_MAKE((void*) sa, salen);
    1061             : 
    1062           1 :         mh = (struct msghdr) {
    1063             :                 .msg_iov = iov,
    1064             :                 .msg_iovlen = ELEMENTSOF(iov)
    1065             :         };
    1066             : 
    1067           1 :         if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0)
    1068           0 :                 return -errno;
    1069             : 
    1070           1 :         resolve->n_outstanding++;
    1071           1 :         q->destroy_callback = destroy_callback;
    1072             : 
    1073           1 :         if (ret_query)
    1074           1 :                 *ret_query = q;
    1075             : 
    1076           1 :         TAKE_PTR(q);
    1077             : 
    1078           1 :         return 0;
    1079             : }
    1080             : 
    1081           1 : _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           1 :         return resolve_getnameinfo_with_destroy_callback(resolve, ret_query, sa, salen, flags, get, callback, NULL, userdata);
    1091             : }
    1092             : 
    1093           1 : static int getnameinfo_done(sd_resolve_query *q) {
    1094             : 
    1095           1 :         assert(q);
    1096           1 :         assert(q->done);
    1097           1 :         assert(q->getnameinfo_handler);
    1098             : 
    1099           1 :         errno = q->_errno;
    1100           1 :         h_errno = q->_h_errno;
    1101             : 
    1102           1 :         return q->getnameinfo_handler(q, q->ret, q->host, q->serv, q->userdata);
    1103             : }
    1104             : 
    1105           3 : static void resolve_freeaddrinfo(struct addrinfo *ai) {
    1106           9 :         while (ai) {
    1107           6 :                 struct addrinfo *next = ai->ai_next;
    1108             : 
    1109           6 :                 free(ai->ai_addr);
    1110           6 :                 free(ai->ai_canonname);
    1111           6 :                 free(ai);
    1112           6 :                 ai = next;
    1113             :         }
    1114           3 : }
    1115             : 
    1116           4 : static void resolve_query_disconnect(sd_resolve_query *q) {
    1117             :         sd_resolve *resolve;
    1118             :         unsigned i;
    1119             : 
    1120           4 :         assert(q);
    1121             : 
    1122           4 :         if (!q->resolve)
    1123           1 :                 return;
    1124             : 
    1125           3 :         resolve = q->resolve;
    1126           3 :         assert(resolve->n_queries > 0);
    1127             : 
    1128           3 :         if (q->done) {
    1129           3 :                 assert(resolve->n_done > 0);
    1130           3 :                 resolve->n_done--;
    1131             :         }
    1132             : 
    1133           3 :         i = q->id % QUERIES_MAX;
    1134           3 :         assert(resolve->query_array[i] == q);
    1135           3 :         resolve->query_array[i] = NULL;
    1136           3 :         LIST_REMOVE(queries, resolve->queries, q);
    1137           3 :         resolve->n_queries--;
    1138             : 
    1139           3 :         q->resolve = NULL;
    1140           3 :         if (!q->floating)
    1141           2 :                 sd_resolve_unref(resolve);
    1142             : }
    1143             : 
    1144           3 : static sd_resolve_query *resolve_query_free(sd_resolve_query *q) {
    1145           3 :         assert(q);
    1146             : 
    1147           3 :         resolve_query_disconnect(q);
    1148             : 
    1149           3 :         if (q->destroy_callback)
    1150           0 :                 q->destroy_callback(q->userdata);
    1151             : 
    1152           3 :         resolve_freeaddrinfo(q->addrinfo);
    1153           3 :         free(q->host);
    1154           3 :         free(q->serv);
    1155             : 
    1156           3 :         return mfree(q);
    1157             : }
    1158             : 
    1159          10 : 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           2 : _public_ int sd_resolve_attach_event(sd_resolve *resolve, sd_event *event, int64_t priority) {
    1252             :         int r;
    1253             : 
    1254           2 :         assert_return(resolve, -EINVAL);
    1255           2 :         assert_return(!resolve->event, -EBUSY);
    1256             : 
    1257           2 :         assert(!resolve->event_source);
    1258             : 
    1259           2 :         if (event)
    1260           2 :                 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           2 :         r = sd_event_add_io(resolve->event, &resolve->event_source, resolve->fds[RESPONSE_RECV_FD], POLLIN, io_callback, resolve);
    1268           2 :         if (r < 0)
    1269           0 :                 goto fail;
    1270             : 
    1271           2 :         r = sd_event_source_set_priority(resolve->event_source, priority);
    1272           2 :         if (r < 0)
    1273           0 :                 goto fail;
    1274             : 
    1275           2 :         return 0;
    1276             : 
    1277           0 : fail:
    1278           0 :         sd_resolve_detach_event(resolve);
    1279           0 :         return r;
    1280             : }
    1281             : 
    1282           3 : _public_  int sd_resolve_detach_event(sd_resolve *resolve) {
    1283           3 :         assert_return(resolve, -EINVAL);
    1284             : 
    1285           3 :         if (!resolve->event)
    1286           1 :                 return 0;
    1287             : 
    1288           2 :         if (resolve->event_source) {
    1289           2 :                 sd_event_source_set_enabled(resolve->event_source, SD_EVENT_OFF);
    1290           2 :                 resolve->event_source = sd_event_source_unref(resolve->event_source);
    1291             :         }
    1292             : 
    1293           2 :         resolve->event = sd_event_unref(resolve->event);
    1294           2 :         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