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