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