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