]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-resolve/sd-resolve.c
Merge pull request #7379 from yuwata/follow-up-7309
[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
894 return sd_resolve_process(resolve);
895 }
896
897 static int alloc_query(sd_resolve *resolve, bool floating, sd_resolve_query **_q) {
898 sd_resolve_query *q;
899 int r;
900
901 assert(resolve);
902 assert(_q);
903
904 if (resolve->n_queries >= QUERIES_MAX)
905 return -ENOBUFS;
906
907 r = start_threads(resolve, 1);
908 if (r < 0)
909 return r;
910
911 while (resolve->query_array[resolve->current_id % QUERIES_MAX])
912 resolve->current_id++;
913
914 q = resolve->query_array[resolve->current_id % QUERIES_MAX] = new0(sd_resolve_query, 1);
915 if (!q)
916 return -ENOMEM;
917
918 q->n_ref = 1;
919 q->resolve = resolve;
920 q->floating = floating;
921 q->id = resolve->current_id++;
922
923 if (!floating)
924 sd_resolve_ref(resolve);
925
926 LIST_PREPEND(queries, resolve->queries, q);
927 resolve->n_queries++;
928
929 *_q = q;
930 return 0;
931 }
932
933 _public_ int sd_resolve_getaddrinfo(
934 sd_resolve *resolve,
935 sd_resolve_query **_q,
936 const char *node, const char *service,
937 const struct addrinfo *hints,
938 sd_resolve_getaddrinfo_handler_t callback, void *userdata) {
939
940 AddrInfoRequest req = {};
941 struct msghdr mh = {};
942 struct iovec iov[3];
943 sd_resolve_query *q;
944 int r;
945
946 assert_return(resolve, -EINVAL);
947 assert_return(node || service, -EINVAL);
948 assert_return(callback, -EINVAL);
949 assert_return(!resolve_pid_changed(resolve), -ECHILD);
950
951 r = alloc_query(resolve, !_q, &q);
952 if (r < 0)
953 return r;
954
955 q->type = REQUEST_ADDRINFO;
956 q->getaddrinfo_handler = callback;
957 q->userdata = userdata;
958
959 req.node_len = node ? strlen(node)+1 : 0;
960 req.service_len = service ? strlen(service)+1 : 0;
961
962 req.header.id = q->id;
963 req.header.type = REQUEST_ADDRINFO;
964 req.header.length = sizeof(AddrInfoRequest) + req.node_len + req.service_len;
965
966 if (hints) {
967 req.hints_valid = true;
968 req.ai_flags = hints->ai_flags;
969 req.ai_family = hints->ai_family;
970 req.ai_socktype = hints->ai_socktype;
971 req.ai_protocol = hints->ai_protocol;
972 }
973
974 iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(AddrInfoRequest) };
975 if (node)
976 iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = (void*) node, .iov_len = req.node_len };
977 if (service)
978 iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = (void*) service, .iov_len = req.service_len };
979 mh.msg_iov = iov;
980
981 if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) {
982 sd_resolve_query_unref(q);
983 return -errno;
984 }
985
986 resolve->n_outstanding++;
987
988 if (_q)
989 *_q = q;
990
991 return 0;
992 }
993
994 static int getaddrinfo_done(sd_resolve_query* q) {
995 assert(q);
996 assert(q->done);
997 assert(q->getaddrinfo_handler);
998
999 errno = q->_errno;
1000 h_errno = q->_h_errno;
1001
1002 return q->getaddrinfo_handler(q, q->ret, q->addrinfo, q->userdata);
1003 }
1004
1005 _public_ int sd_resolve_getnameinfo(
1006 sd_resolve *resolve,
1007 sd_resolve_query**_q,
1008 const struct sockaddr *sa, socklen_t salen,
1009 int flags,
1010 uint64_t get,
1011 sd_resolve_getnameinfo_handler_t callback,
1012 void *userdata) {
1013
1014 NameInfoRequest req = {};
1015 struct msghdr mh = {};
1016 struct iovec iov[2];
1017 sd_resolve_query *q;
1018 int r;
1019
1020 assert_return(resolve, -EINVAL);
1021 assert_return(sa, -EINVAL);
1022 assert_return(salen >= sizeof(struct sockaddr), -EINVAL);
1023 assert_return(salen <= sizeof(union sockaddr_union), -EINVAL);
1024 assert_return((get & ~SD_RESOLVE_GET_BOTH) == 0, -EINVAL);
1025 assert_return(callback, -EINVAL);
1026 assert_return(!resolve_pid_changed(resolve), -ECHILD);
1027
1028 r = alloc_query(resolve, !_q, &q);
1029 if (r < 0)
1030 return r;
1031
1032 q->type = REQUEST_NAMEINFO;
1033 q->getnameinfo_handler = callback;
1034 q->userdata = userdata;
1035
1036 req.header.id = q->id;
1037 req.header.type = REQUEST_NAMEINFO;
1038 req.header.length = sizeof(NameInfoRequest) + salen;
1039
1040 req.flags = flags;
1041 req.sockaddr_len = salen;
1042 req.gethost = !!(get & SD_RESOLVE_GET_HOST);
1043 req.getserv = !!(get & SD_RESOLVE_GET_SERVICE);
1044
1045 iov[0] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(NameInfoRequest) };
1046 iov[1] = (struct iovec) { .iov_base = (void*) sa, .iov_len = salen };
1047
1048 mh.msg_iov = iov;
1049 mh.msg_iovlen = 2;
1050
1051 if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) {
1052 sd_resolve_query_unref(q);
1053 return -errno;
1054 }
1055
1056 resolve->n_outstanding++;
1057
1058 if (_q)
1059 *_q = q;
1060
1061 return 0;
1062 }
1063
1064 static int getnameinfo_done(sd_resolve_query *q) {
1065
1066 assert(q);
1067 assert(q->done);
1068 assert(q->getnameinfo_handler);
1069
1070 errno = q->_errno;
1071 h_errno= q->_h_errno;
1072
1073 return q->getnameinfo_handler(q, q->ret, q->host, q->serv, q->userdata);
1074 }
1075
1076 _public_ sd_resolve_query* sd_resolve_query_ref(sd_resolve_query *q) {
1077 assert_return(q, NULL);
1078
1079 assert(q->n_ref >= 1);
1080 q->n_ref++;
1081
1082 return q;
1083 }
1084
1085 static void resolve_freeaddrinfo(struct addrinfo *ai) {
1086 while (ai) {
1087 struct addrinfo *next = ai->ai_next;
1088
1089 free(ai->ai_addr);
1090 free(ai->ai_canonname);
1091 free(ai);
1092 ai = next;
1093 }
1094 }
1095
1096 static void resolve_query_disconnect(sd_resolve_query *q) {
1097 sd_resolve *resolve;
1098 unsigned i;
1099
1100 assert(q);
1101
1102 if (!q->resolve)
1103 return;
1104
1105 resolve = q->resolve;
1106 assert(resolve->n_queries > 0);
1107
1108 if (q->done) {
1109 assert(resolve->n_done > 0);
1110 resolve->n_done--;
1111 }
1112
1113 i = q->id % QUERIES_MAX;
1114 assert(resolve->query_array[i] == q);
1115 resolve->query_array[i] = NULL;
1116 LIST_REMOVE(queries, resolve->queries, q);
1117 resolve->n_queries--;
1118
1119 q->resolve = NULL;
1120 if (!q->floating)
1121 sd_resolve_unref(resolve);
1122 }
1123
1124 static void resolve_query_free(sd_resolve_query *q) {
1125 assert(q);
1126
1127 resolve_query_disconnect(q);
1128
1129 resolve_freeaddrinfo(q->addrinfo);
1130 free(q->host);
1131 free(q->serv);
1132 free(q);
1133 }
1134
1135 _public_ sd_resolve_query* sd_resolve_query_unref(sd_resolve_query* q) {
1136 if (!q)
1137 return NULL;
1138
1139 assert(q->n_ref >= 1);
1140 q->n_ref--;
1141
1142 if (q->n_ref <= 0)
1143 resolve_query_free(q);
1144
1145 return NULL;
1146 }
1147
1148 _public_ int sd_resolve_query_is_done(sd_resolve_query *q) {
1149 assert_return(q, -EINVAL);
1150 assert_return(!resolve_pid_changed(q->resolve), -ECHILD);
1151
1152 return q->done;
1153 }
1154
1155 _public_ void* sd_resolve_query_set_userdata(sd_resolve_query *q, void *userdata) {
1156 void *ret;
1157
1158 assert_return(q, NULL);
1159 assert_return(!resolve_pid_changed(q->resolve), NULL);
1160
1161 ret = q->userdata;
1162 q->userdata = userdata;
1163
1164 return ret;
1165 }
1166
1167 _public_ void* sd_resolve_query_get_userdata(sd_resolve_query *q) {
1168 assert_return(q, NULL);
1169 assert_return(!resolve_pid_changed(q->resolve), NULL);
1170
1171 return q->userdata;
1172 }
1173
1174 _public_ sd_resolve *sd_resolve_query_get_resolve(sd_resolve_query *q) {
1175 assert_return(q, NULL);
1176 assert_return(!resolve_pid_changed(q->resolve), NULL);
1177
1178 return q->resolve;
1179 }
1180
1181 static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
1182 sd_resolve *resolve = userdata;
1183 int r;
1184
1185 assert(resolve);
1186
1187 r = sd_resolve_process(resolve);
1188 if (r < 0)
1189 return r;
1190
1191 return 1;
1192 }
1193
1194 _public_ int sd_resolve_attach_event(sd_resolve *resolve, sd_event *event, int64_t priority) {
1195 int r;
1196
1197 assert_return(resolve, -EINVAL);
1198 assert_return(!resolve->event, -EBUSY);
1199
1200 assert(!resolve->event_source);
1201
1202 if (event)
1203 resolve->event = sd_event_ref(event);
1204 else {
1205 r = sd_event_default(&resolve->event);
1206 if (r < 0)
1207 return r;
1208 }
1209
1210 r = sd_event_add_io(resolve->event, &resolve->event_source, resolve->fds[RESPONSE_RECV_FD], POLLIN, io_callback, resolve);
1211 if (r < 0)
1212 goto fail;
1213
1214 r = sd_event_source_set_priority(resolve->event_source, priority);
1215 if (r < 0)
1216 goto fail;
1217
1218 return 0;
1219
1220 fail:
1221 sd_resolve_detach_event(resolve);
1222 return r;
1223 }
1224
1225 _public_ int sd_resolve_detach_event(sd_resolve *resolve) {
1226 assert_return(resolve, -EINVAL);
1227
1228 if (!resolve->event)
1229 return 0;
1230
1231 if (resolve->event_source) {
1232 sd_event_source_set_enabled(resolve->event_source, SD_EVENT_OFF);
1233 resolve->event_source = sd_event_source_unref(resolve->event_source);
1234 }
1235
1236 resolve->event = sd_event_unref(resolve->event);
1237 return 1;
1238 }
1239
1240 _public_ sd_event *sd_resolve_get_event(sd_resolve *resolve) {
1241 assert_return(resolve, NULL);
1242
1243 return resolve->event;
1244 }