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