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