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