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