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