]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-resolve/sd-resolve.c
log: minimize includes in log.h
[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 fd_inc_sndbuf(resolve->fds[REQUEST_SEND_FD], QUERIES_MAX * BUFSIZE);
511 fd_inc_rcvbuf(resolve->fds[REQUEST_RECV_FD], QUERIES_MAX * BUFSIZE);
512 fd_inc_sndbuf(resolve->fds[RESPONSE_SEND_FD], QUERIES_MAX * BUFSIZE);
513 fd_inc_rcvbuf(resolve->fds[RESPONSE_RECV_FD], QUERIES_MAX * BUFSIZE);
514
515 fd_nonblock(resolve->fds[RESPONSE_RECV_FD], true);
516
517 *ret = resolve;
518 return 0;
519
520 fail:
521 sd_resolve_unref(resolve);
522 return r;
523 }
524
525 _public_ int sd_resolve_default(sd_resolve **ret) {
526
527 static thread_local sd_resolve *default_resolve = NULL;
528 sd_resolve *e = NULL;
529 int r;
530
531 if (!ret)
532 return !!default_resolve;
533
534 if (default_resolve) {
535 *ret = sd_resolve_ref(default_resolve);
536 return 0;
537 }
538
539 r = sd_resolve_new(&e);
540 if (r < 0)
541 return r;
542
543 e->default_resolve_ptr = &default_resolve;
544 e->tid = gettid();
545 default_resolve = e;
546
547 *ret = e;
548 return 1;
549 }
550
551 _public_ int sd_resolve_get_tid(sd_resolve *resolve, pid_t *tid) {
552 assert_return(resolve, -EINVAL);
553 assert_return(tid, -EINVAL);
554 assert_return(!resolve_pid_changed(resolve), -ECHILD);
555
556 if (resolve->tid != 0) {
557 *tid = resolve->tid;
558 return 0;
559 }
560
561 if (resolve->event)
562 return sd_event_get_tid(resolve->event, tid);
563
564 return -ENXIO;
565 }
566
567 static void resolve_free(sd_resolve *resolve) {
568 PROTECT_ERRNO;
569 sd_resolve_query *q;
570 unsigned i;
571
572 assert(resolve);
573
574 while ((q = resolve->queries)) {
575 assert(q->floating);
576 resolve_query_disconnect(q);
577 sd_resolve_query_unref(q);
578 }
579
580 if (resolve->default_resolve_ptr)
581 *(resolve->default_resolve_ptr) = NULL;
582
583 resolve->dead = true;
584
585 sd_resolve_detach_event(resolve);
586
587 if (resolve->fds[REQUEST_SEND_FD] >= 0) {
588
589 RHeader req = {
590 .type = REQUEST_TERMINATE,
591 .length = sizeof(req)
592 };
593
594 /* Send one termination packet for each worker */
595 for (i = 0; i < resolve->n_valid_workers; i++)
596 (void) send(resolve->fds[REQUEST_SEND_FD], &req, req.length, MSG_NOSIGNAL);
597 }
598
599 /* Now terminate them and wait until they are gone.
600 If we get an error than most likely the thread already exited. */
601 for (i = 0; i < resolve->n_valid_workers; i++)
602 (void) pthread_join(resolve->workers[i], NULL);
603
604 /* Close all communication channels */
605 close_many(resolve->fds, _FD_MAX);
606 free(resolve);
607 }
608
609 _public_ sd_resolve* sd_resolve_ref(sd_resolve *resolve) {
610 assert_return(resolve, NULL);
611
612 assert(resolve->n_ref >= 1);
613 resolve->n_ref++;
614
615 return resolve;
616 }
617
618 _public_ sd_resolve* sd_resolve_unref(sd_resolve *resolve) {
619
620 if (!resolve)
621 return NULL;
622
623 assert(resolve->n_ref >= 1);
624 resolve->n_ref--;
625
626 if (resolve->n_ref <= 0)
627 resolve_free(resolve);
628
629 return NULL;
630 }
631
632 _public_ int sd_resolve_get_fd(sd_resolve *resolve) {
633 assert_return(resolve, -EINVAL);
634 assert_return(!resolve_pid_changed(resolve), -ECHILD);
635
636 return resolve->fds[RESPONSE_RECV_FD];
637 }
638
639 _public_ int sd_resolve_get_events(sd_resolve *resolve) {
640 assert_return(resolve, -EINVAL);
641 assert_return(!resolve_pid_changed(resolve), -ECHILD);
642
643 return resolve->n_queries > resolve->n_done ? POLLIN : 0;
644 }
645
646 _public_ int sd_resolve_get_timeout(sd_resolve *resolve, uint64_t *usec) {
647 assert_return(resolve, -EINVAL);
648 assert_return(usec, -EINVAL);
649 assert_return(!resolve_pid_changed(resolve), -ECHILD);
650
651 *usec = (uint64_t) -1;
652 return 0;
653 }
654
655 static sd_resolve_query *lookup_query(sd_resolve *resolve, unsigned id) {
656 sd_resolve_query *q;
657
658 assert(resolve);
659
660 q = resolve->query_array[id % QUERIES_MAX];
661 if (q)
662 if (q->id == id)
663 return q;
664
665 return NULL;
666 }
667
668 static int complete_query(sd_resolve *resolve, sd_resolve_query *q) {
669 int r;
670
671 assert(q);
672 assert(!q->done);
673 assert(q->resolve == resolve);
674
675 q->done = true;
676 resolve->n_done++;
677
678 resolve->current = sd_resolve_query_ref(q);
679
680 switch (q->type) {
681
682 case REQUEST_ADDRINFO:
683 r = getaddrinfo_done(q);
684 break;
685
686 case REQUEST_NAMEINFO:
687 r = getnameinfo_done(q);
688 break;
689
690 default:
691 assert_not_reached("Cannot complete unknown query type");
692 }
693
694 resolve->current = NULL;
695
696 if (q->floating) {
697 resolve_query_disconnect(q);
698 sd_resolve_query_unref(q);
699 }
700
701 sd_resolve_query_unref(q);
702
703 return r;
704 }
705
706 static int unserialize_addrinfo(const void **p, size_t *length, struct addrinfo **ret_ai) {
707 AddrInfoSerialization s;
708 size_t l;
709 struct addrinfo *ai;
710
711 assert(p);
712 assert(*p);
713 assert(ret_ai);
714 assert(length);
715
716 if (*length < sizeof(AddrInfoSerialization))
717 return -EBADMSG;
718
719 memcpy(&s, *p, sizeof(s));
720
721 l = sizeof(AddrInfoSerialization) + s.ai_addrlen + s.canonname_len;
722 if (*length < l)
723 return -EBADMSG;
724
725 ai = new0(struct addrinfo, 1);
726 if (!ai)
727 return -ENOMEM;
728
729 ai->ai_flags = s.ai_flags;
730 ai->ai_family = s.ai_family;
731 ai->ai_socktype = s.ai_socktype;
732 ai->ai_protocol = s.ai_protocol;
733 ai->ai_addrlen = s.ai_addrlen;
734
735 if (s.ai_addrlen > 0) {
736 ai->ai_addr = memdup((const uint8_t*) *p + sizeof(AddrInfoSerialization), s.ai_addrlen);
737 if (!ai->ai_addr) {
738 free(ai);
739 return -ENOMEM;
740 }
741 }
742
743 if (s.canonname_len > 0) {
744 ai->ai_canonname = memdup((const uint8_t*) *p + sizeof(AddrInfoSerialization) + s.ai_addrlen, s.canonname_len);
745 if (!ai->ai_canonname) {
746 free(ai->ai_addr);
747 free(ai);
748 return -ENOMEM;
749 }
750 }
751
752 *length -= l;
753 *ret_ai = ai;
754 *p = ((const uint8_t*) *p) + l;
755
756 return 0;
757 }
758
759 static int handle_response(sd_resolve *resolve, const Packet *packet, size_t length) {
760 const RHeader *resp;
761 sd_resolve_query *q;
762 int r;
763
764 assert(resolve);
765
766 resp = &packet->rheader;
767 assert(resp);
768 assert(length >= sizeof(RHeader));
769 assert(length == resp->length);
770
771 if (resp->type == RESPONSE_DIED) {
772 resolve->dead = true;
773 return 0;
774 }
775
776 assert(resolve->n_outstanding > 0);
777 resolve->n_outstanding--;
778
779 q = lookup_query(resolve, resp->id);
780 if (!q)
781 return 0;
782
783 switch (resp->type) {
784
785 case RESPONSE_ADDRINFO: {
786 const AddrInfoResponse *ai_resp = &packet->addrinfo_response;
787 const void *p;
788 size_t l;
789 struct addrinfo *prev = NULL;
790
791 assert(length >= sizeof(AddrInfoResponse));
792 assert(q->type == REQUEST_ADDRINFO);
793
794 q->ret = ai_resp->ret;
795 q->_errno = ai_resp->_errno;
796 q->_h_errno = ai_resp->_h_errno;
797
798 l = length - sizeof(AddrInfoResponse);
799 p = (const uint8_t*) resp + sizeof(AddrInfoResponse);
800
801 while (l > 0 && p) {
802 struct addrinfo *ai = NULL;
803
804 r = unserialize_addrinfo(&p, &l, &ai);
805 if (r < 0) {
806 q->ret = EAI_SYSTEM;
807 q->_errno = -r;
808 q->_h_errno = 0;
809 freeaddrinfo(q->addrinfo);
810 q->addrinfo = NULL;
811 break;
812 }
813
814 if (prev)
815 prev->ai_next = ai;
816 else
817 q->addrinfo = ai;
818
819 prev = ai;
820 }
821
822 return complete_query(resolve, q);
823 }
824
825 case RESPONSE_NAMEINFO: {
826 const NameInfoResponse *ni_resp = &packet->nameinfo_response;
827
828 assert(length >= sizeof(NameInfoResponse));
829 assert(q->type == REQUEST_NAMEINFO);
830
831 if (ni_resp->hostlen > DNS_HOSTNAME_MAX ||
832 ni_resp->servlen > DNS_HOSTNAME_MAX ||
833 sizeof(NameInfoResponse) + ni_resp->hostlen + ni_resp->servlen > length + 2) {
834 q->ret = EAI_SYSTEM;
835 q->_errno = -EIO;
836 q->_h_errno = 0;
837
838 } else {
839 q->ret = ni_resp->ret;
840 q->_errno = ni_resp->_errno;
841 q->_h_errno = ni_resp->_h_errno;
842
843 if (ni_resp->hostlen > 0) {
844 q->host = strndup((const char*) ni_resp + sizeof(NameInfoResponse),
845 ni_resp->hostlen-1);
846 if (!q->host) {
847 q->ret = EAI_MEMORY;
848 q->_errno = ENOMEM;
849 q->_h_errno = 0;
850 }
851 }
852
853 if (ni_resp->servlen > 0) {
854 q->serv = strndup((const char*) ni_resp + sizeof(NameInfoResponse) + ni_resp->hostlen,
855 ni_resp->servlen-1);
856 if (!q->serv) {
857 q->ret = EAI_MEMORY;
858 q->_errno = ENOMEM;
859 q->_h_errno = 0;
860 }
861 }
862 }
863
864 return complete_query(resolve, q);
865 }
866
867 default:
868 return 0;
869 }
870 }
871
872 _public_ int sd_resolve_process(sd_resolve *resolve) {
873 RESOLVE_DONT_DESTROY(resolve);
874
875 union {
876 Packet packet;
877 uint8_t space[BUFSIZE];
878 } buf;
879 ssize_t l;
880 int r;
881
882 assert_return(resolve, -EINVAL);
883 assert_return(!resolve_pid_changed(resolve), -ECHILD);
884
885 /* We don't allow recursively invoking sd_resolve_process(). */
886 assert_return(!resolve->current, -EBUSY);
887
888 l = recv(resolve->fds[RESPONSE_RECV_FD], &buf, sizeof(buf), 0);
889 if (l < 0) {
890 if (errno == EAGAIN)
891 return 0;
892
893 return -errno;
894 }
895 if (l == 0)
896 return -ECONNREFUSED;
897
898 r = handle_response(resolve, &buf.packet, (size_t) l);
899 if (r < 0)
900 return r;
901
902 return 1;
903 }
904
905 _public_ int sd_resolve_wait(sd_resolve *resolve, uint64_t timeout_usec) {
906 int r;
907
908 assert_return(resolve, -EINVAL);
909 assert_return(!resolve_pid_changed(resolve), -ECHILD);
910
911 if (resolve->n_done >= resolve->n_queries)
912 return 0;
913
914 do {
915 r = fd_wait_for_event(resolve->fds[RESPONSE_RECV_FD], POLLIN, timeout_usec);
916 } while (r == -EINTR);
917
918 if (r < 0)
919 return r;
920 if (r == 0)
921 return -ETIMEDOUT;
922
923 return sd_resolve_process(resolve);
924 }
925
926 static int alloc_query(sd_resolve *resolve, bool floating, sd_resolve_query **_q) {
927 sd_resolve_query *q;
928 int r;
929
930 assert(resolve);
931 assert(_q);
932
933 if (resolve->n_queries >= QUERIES_MAX)
934 return -ENOBUFS;
935
936 r = start_threads(resolve, 1);
937 if (r < 0)
938 return r;
939
940 while (resolve->query_array[resolve->current_id % QUERIES_MAX])
941 resolve->current_id++;
942
943 q = resolve->query_array[resolve->current_id % QUERIES_MAX] = new0(sd_resolve_query, 1);
944 if (!q)
945 return -ENOMEM;
946
947 q->n_ref = 1;
948 q->resolve = resolve;
949 q->floating = floating;
950 q->id = resolve->current_id++;
951
952 if (!floating)
953 sd_resolve_ref(resolve);
954
955 LIST_PREPEND(queries, resolve->queries, q);
956 resolve->n_queries++;
957
958 *_q = q;
959 return 0;
960 }
961
962 _public_ int sd_resolve_getaddrinfo(
963 sd_resolve *resolve,
964 sd_resolve_query **_q,
965 const char *node, const char *service,
966 const struct addrinfo *hints,
967 sd_resolve_getaddrinfo_handler_t callback, void *userdata) {
968
969 AddrInfoRequest req = {};
970 struct msghdr mh = {};
971 struct iovec iov[3];
972 sd_resolve_query *q;
973 int r;
974
975 assert_return(resolve, -EINVAL);
976 assert_return(node || service, -EINVAL);
977 assert_return(callback, -EINVAL);
978 assert_return(!resolve_pid_changed(resolve), -ECHILD);
979
980 r = alloc_query(resolve, !_q, &q);
981 if (r < 0)
982 return r;
983
984 q->type = REQUEST_ADDRINFO;
985 q->getaddrinfo_handler = callback;
986 q->userdata = userdata;
987
988 req.node_len = node ? strlen(node)+1 : 0;
989 req.service_len = service ? strlen(service)+1 : 0;
990
991 req.header.id = q->id;
992 req.header.type = REQUEST_ADDRINFO;
993 req.header.length = sizeof(AddrInfoRequest) + req.node_len + req.service_len;
994
995 if (hints) {
996 req.hints_valid = true;
997 req.ai_flags = hints->ai_flags;
998 req.ai_family = hints->ai_family;
999 req.ai_socktype = hints->ai_socktype;
1000 req.ai_protocol = hints->ai_protocol;
1001 }
1002
1003 iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(AddrInfoRequest) };
1004 if (node)
1005 iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = (void*) node, .iov_len = req.node_len };
1006 if (service)
1007 iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = (void*) service, .iov_len = req.service_len };
1008 mh.msg_iov = iov;
1009
1010 if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) {
1011 sd_resolve_query_unref(q);
1012 return -errno;
1013 }
1014
1015 resolve->n_outstanding++;
1016
1017 if (_q)
1018 *_q = q;
1019
1020 return 0;
1021 }
1022
1023 static int getaddrinfo_done(sd_resolve_query* q) {
1024 assert(q);
1025 assert(q->done);
1026 assert(q->getaddrinfo_handler);
1027
1028 errno = q->_errno;
1029 h_errno = q->_h_errno;
1030
1031 return q->getaddrinfo_handler(q, q->ret, q->addrinfo, q->userdata);
1032 }
1033
1034 _public_ int sd_resolve_getnameinfo(
1035 sd_resolve *resolve,
1036 sd_resolve_query**_q,
1037 const struct sockaddr *sa, socklen_t salen,
1038 int flags,
1039 uint64_t get,
1040 sd_resolve_getnameinfo_handler_t callback,
1041 void *userdata) {
1042
1043 NameInfoRequest req = {};
1044 struct msghdr mh = {};
1045 struct iovec iov[2];
1046 sd_resolve_query *q;
1047 int r;
1048
1049 assert_return(resolve, -EINVAL);
1050 assert_return(sa, -EINVAL);
1051 assert_return(salen >= sizeof(struct sockaddr), -EINVAL);
1052 assert_return(salen <= sizeof(union sockaddr_union), -EINVAL);
1053 assert_return((get & ~SD_RESOLVE_GET_BOTH) == 0, -EINVAL);
1054 assert_return(callback, -EINVAL);
1055 assert_return(!resolve_pid_changed(resolve), -ECHILD);
1056
1057 r = alloc_query(resolve, !_q, &q);
1058 if (r < 0)
1059 return r;
1060
1061 q->type = REQUEST_NAMEINFO;
1062 q->getnameinfo_handler = callback;
1063 q->userdata = userdata;
1064
1065 req.header.id = q->id;
1066 req.header.type = REQUEST_NAMEINFO;
1067 req.header.length = sizeof(NameInfoRequest) + salen;
1068
1069 req.flags = flags;
1070 req.sockaddr_len = salen;
1071 req.gethost = !!(get & SD_RESOLVE_GET_HOST);
1072 req.getserv = !!(get & SD_RESOLVE_GET_SERVICE);
1073
1074 iov[0] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(NameInfoRequest) };
1075 iov[1] = (struct iovec) { .iov_base = (void*) sa, .iov_len = salen };
1076
1077 mh.msg_iov = iov;
1078 mh.msg_iovlen = 2;
1079
1080 if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) {
1081 sd_resolve_query_unref(q);
1082 return -errno;
1083 }
1084
1085 resolve->n_outstanding++;
1086
1087 if (_q)
1088 *_q = q;
1089
1090 return 0;
1091 }
1092
1093 static int getnameinfo_done(sd_resolve_query *q) {
1094
1095 assert(q);
1096 assert(q->done);
1097 assert(q->getnameinfo_handler);
1098
1099 errno = q->_errno;
1100 h_errno= q->_h_errno;
1101
1102 return q->getnameinfo_handler(q, q->ret, q->host, q->serv, q->userdata);
1103 }
1104
1105 _public_ sd_resolve_query* sd_resolve_query_ref(sd_resolve_query *q) {
1106 assert_return(q, NULL);
1107
1108 assert(q->n_ref >= 1);
1109 q->n_ref++;
1110
1111 return q;
1112 }
1113
1114 static void resolve_freeaddrinfo(struct addrinfo *ai) {
1115 while (ai) {
1116 struct addrinfo *next = ai->ai_next;
1117
1118 free(ai->ai_addr);
1119 free(ai->ai_canonname);
1120 free(ai);
1121 ai = next;
1122 }
1123 }
1124
1125 static void resolve_query_disconnect(sd_resolve_query *q) {
1126 sd_resolve *resolve;
1127 unsigned i;
1128
1129 assert(q);
1130
1131 if (!q->resolve)
1132 return;
1133
1134 resolve = q->resolve;
1135 assert(resolve->n_queries > 0);
1136
1137 if (q->done) {
1138 assert(resolve->n_done > 0);
1139 resolve->n_done--;
1140 }
1141
1142 i = q->id % QUERIES_MAX;
1143 assert(resolve->query_array[i] == q);
1144 resolve->query_array[i] = NULL;
1145 LIST_REMOVE(queries, resolve->queries, q);
1146 resolve->n_queries--;
1147
1148 q->resolve = NULL;
1149 if (!q->floating)
1150 sd_resolve_unref(resolve);
1151 }
1152
1153 static void resolve_query_free(sd_resolve_query *q) {
1154 assert(q);
1155
1156 resolve_query_disconnect(q);
1157
1158 resolve_freeaddrinfo(q->addrinfo);
1159 free(q->host);
1160 free(q->serv);
1161 free(q);
1162 }
1163
1164 _public_ sd_resolve_query* sd_resolve_query_unref(sd_resolve_query* q) {
1165 if (!q)
1166 return NULL;
1167
1168 assert(q->n_ref >= 1);
1169 q->n_ref--;
1170
1171 if (q->n_ref <= 0)
1172 resolve_query_free(q);
1173
1174 return NULL;
1175 }
1176
1177 _public_ int sd_resolve_query_is_done(sd_resolve_query *q) {
1178 assert_return(q, -EINVAL);
1179 assert_return(!resolve_pid_changed(q->resolve), -ECHILD);
1180
1181 return q->done;
1182 }
1183
1184 _public_ void* sd_resolve_query_set_userdata(sd_resolve_query *q, void *userdata) {
1185 void *ret;
1186
1187 assert_return(q, NULL);
1188 assert_return(!resolve_pid_changed(q->resolve), NULL);
1189
1190 ret = q->userdata;
1191 q->userdata = userdata;
1192
1193 return ret;
1194 }
1195
1196 _public_ void* sd_resolve_query_get_userdata(sd_resolve_query *q) {
1197 assert_return(q, NULL);
1198 assert_return(!resolve_pid_changed(q->resolve), NULL);
1199
1200 return q->userdata;
1201 }
1202
1203 _public_ sd_resolve *sd_resolve_query_get_resolve(sd_resolve_query *q) {
1204 assert_return(q, NULL);
1205 assert_return(!resolve_pid_changed(q->resolve), NULL);
1206
1207 return q->resolve;
1208 }
1209
1210 static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
1211 sd_resolve *resolve = userdata;
1212 int r;
1213
1214 assert(resolve);
1215
1216 r = sd_resolve_process(resolve);
1217 if (r < 0)
1218 return r;
1219
1220 return 1;
1221 }
1222
1223 _public_ int sd_resolve_attach_event(sd_resolve *resolve, sd_event *event, int64_t priority) {
1224 int r;
1225
1226 assert_return(resolve, -EINVAL);
1227 assert_return(!resolve->event, -EBUSY);
1228
1229 assert(!resolve->event_source);
1230
1231 if (event)
1232 resolve->event = sd_event_ref(event);
1233 else {
1234 r = sd_event_default(&resolve->event);
1235 if (r < 0)
1236 return r;
1237 }
1238
1239 r = sd_event_add_io(resolve->event, &resolve->event_source, resolve->fds[RESPONSE_RECV_FD], POLLIN, io_callback, resolve);
1240 if (r < 0)
1241 goto fail;
1242
1243 r = sd_event_source_set_priority(resolve->event_source, priority);
1244 if (r < 0)
1245 goto fail;
1246
1247 return 0;
1248
1249 fail:
1250 sd_resolve_detach_event(resolve);
1251 return r;
1252 }
1253
1254 _public_ int sd_resolve_detach_event(sd_resolve *resolve) {
1255 assert_return(resolve, -EINVAL);
1256
1257 if (!resolve->event)
1258 return 0;
1259
1260 if (resolve->event_source) {
1261 sd_event_source_set_enabled(resolve->event_source, SD_EVENT_OFF);
1262 resolve->event_source = sd_event_source_unref(resolve->event_source);
1263 }
1264
1265 resolve->event = sd_event_unref(resolve->event);
1266 return 1;
1267 }
1268
1269 _public_ sd_event *sd_resolve_get_event(sd_resolve *resolve) {
1270 assert_return(resolve, NULL);
1271
1272 return resolve->event;
1273 }