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