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