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