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