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