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