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