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