]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-resolve/sd-resolve.c
sd-resolve: drop res_query() API
[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 <signal.h>
23 #include <unistd.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <errno.h>
28 #include <resolv.h>
29 #include <stdint.h>
30 #include <pthread.h>
31 #include <sys/prctl.h>
32 #include <poll.h>
33
34 #include "util.h"
35 #include "list.h"
36 #include "socket-util.h"
37 #include "missing.h"
38 #include "resolve-util.h"
39 #include "sd-resolve.h"
40
41 #define WORKERS_MIN 1U
42 #define WORKERS_MAX 16U
43 #define QUERIES_MAX 256U
44 #define BUFSIZE 10240U
45
46 typedef enum {
47 REQUEST_ADDRINFO,
48 RESPONSE_ADDRINFO,
49 REQUEST_NAMEINFO,
50 RESPONSE_NAMEINFO,
51 REQUEST_TERMINATE,
52 RESPONSE_DIED
53 } QueryType;
54
55 enum {
56 REQUEST_RECV_FD,
57 REQUEST_SEND_FD,
58 RESPONSE_RECV_FD,
59 RESPONSE_SEND_FD,
60 _FD_MAX
61 };
62
63 struct sd_resolve {
64 unsigned n_ref;
65
66 bool dead:1;
67 pid_t original_pid;
68
69 int fds[_FD_MAX];
70
71 pthread_t workers[WORKERS_MAX];
72 unsigned n_valid_workers;
73
74 unsigned current_id;
75 sd_resolve_query* query_array[QUERIES_MAX];
76 unsigned n_queries, n_done, n_outstanding;
77
78 sd_event_source *event_source;
79 sd_event *event;
80
81 sd_resolve_query *current;
82
83 sd_resolve **default_resolve_ptr;
84 pid_t tid;
85
86 LIST_HEAD(sd_resolve_query, queries);
87 };
88
89 struct sd_resolve_query {
90 unsigned n_ref;
91
92 sd_resolve *resolve;
93
94 QueryType type:4;
95 bool done:1;
96 bool floating:1;
97 unsigned id;
98
99 int ret;
100 int _errno;
101 int _h_errno;
102 struct addrinfo *addrinfo;
103 char *serv, *host;
104
105 union {
106 sd_resolve_getaddrinfo_handler_t getaddrinfo_handler;
107 sd_resolve_getnameinfo_handler_t getnameinfo_handler;
108 };
109
110 void *userdata;
111
112 LIST_FIELDS(sd_resolve_query, queries);
113 };
114
115 typedef struct RHeader {
116 QueryType type;
117 unsigned id;
118 size_t length;
119 } RHeader;
120
121 typedef struct AddrInfoRequest {
122 struct RHeader header;
123 bool hints_valid;
124 int ai_flags;
125 int ai_family;
126 int ai_socktype;
127 int ai_protocol;
128 size_t node_len, service_len;
129 } AddrInfoRequest;
130
131 typedef struct AddrInfoResponse {
132 struct RHeader header;
133 int ret;
134 int _errno;
135 int _h_errno;
136 /* followed by addrinfo_serialization[] */
137 } AddrInfoResponse;
138
139 typedef struct AddrInfoSerialization {
140 int ai_flags;
141 int ai_family;
142 int ai_socktype;
143 int ai_protocol;
144 size_t ai_addrlen;
145 size_t canonname_len;
146 /* Followed by ai_addr amd ai_canonname with variable lengths */
147 } AddrInfoSerialization;
148
149 typedef struct NameInfoRequest {
150 struct RHeader header;
151 int flags;
152 socklen_t sockaddr_len;
153 bool gethost:1, getserv:1;
154 } NameInfoRequest;
155
156 typedef struct NameInfoResponse {
157 struct RHeader header;
158 size_t hostlen, servlen;
159 int ret;
160 int _errno;
161 int _h_errno;
162 } NameInfoResponse;
163
164 typedef union Packet {
165 RHeader rheader;
166 AddrInfoRequest addrinfo_request;
167 AddrInfoResponse addrinfo_response;
168 NameInfoRequest nameinfo_request;
169 NameInfoResponse nameinfo_response;
170 } Packet;
171
172 static int getaddrinfo_done(sd_resolve_query* q);
173 static int getnameinfo_done(sd_resolve_query *q);
174
175 static void resolve_query_disconnect(sd_resolve_query *q);
176
177 #define RESOLVE_DONT_DESTROY(resolve) \
178 _cleanup_resolve_unref_ _unused_ sd_resolve *_dont_destroy_##resolve = sd_resolve_ref(resolve)
179
180 static int send_died(int out_fd) {
181
182 RHeader rh = {
183 .type = RESPONSE_DIED,
184 .length = sizeof(RHeader),
185 };
186
187 assert(out_fd >= 0);
188
189 if (send(out_fd, &rh, rh.length, MSG_NOSIGNAL) < 0)
190 return -errno;
191
192 return 0;
193 }
194
195 static void *serialize_addrinfo(void *p, const struct addrinfo *ai, size_t *length, size_t maxlength) {
196 AddrInfoSerialization s;
197 size_t cnl, l;
198
199 assert(p);
200 assert(ai);
201 assert(length);
202 assert(*length <= maxlength);
203
204 cnl = ai->ai_canonname ? strlen(ai->ai_canonname)+1 : 0;
205 l = sizeof(AddrInfoSerialization) + ai->ai_addrlen + cnl;
206
207 if (*length + l > maxlength)
208 return NULL;
209
210 s.ai_flags = ai->ai_flags;
211 s.ai_family = ai->ai_family;
212 s.ai_socktype = ai->ai_socktype;
213 s.ai_protocol = ai->ai_protocol;
214 s.ai_addrlen = ai->ai_addrlen;
215 s.canonname_len = cnl;
216
217 memcpy((uint8_t*) p, &s, sizeof(AddrInfoSerialization));
218 memcpy((uint8_t*) p + sizeof(AddrInfoSerialization), ai->ai_addr, ai->ai_addrlen);
219
220 if (ai->ai_canonname)
221 memcpy((char*) p + sizeof(AddrInfoSerialization) + ai->ai_addrlen, ai->ai_canonname, cnl);
222
223 *length += l;
224 return (uint8_t*) p + l;
225 }
226
227 static int send_addrinfo_reply(
228 int out_fd,
229 unsigned id,
230 int ret,
231 struct addrinfo *ai,
232 int _errno,
233 int _h_errno) {
234
235 AddrInfoResponse resp = {
236 .header.type = RESPONSE_ADDRINFO,
237 .header.id = id,
238 .header.length = sizeof(AddrInfoResponse),
239 .ret = ret,
240 ._errno = _errno,
241 ._h_errno = _h_errno,
242 };
243
244 struct msghdr mh = {};
245 struct iovec iov[2];
246 union {
247 AddrInfoSerialization ais;
248 uint8_t space[BUFSIZE];
249 } buffer;
250
251 assert(out_fd >= 0);
252
253 if (ret == 0 && ai) {
254 void *p = &buffer;
255 struct addrinfo *k;
256
257 for (k = ai; k; k = k->ai_next) {
258 p = serialize_addrinfo(p, k, &resp.header.length, (uint8_t*) &buffer + BUFSIZE - (uint8_t*) p);
259 if (!p) {
260 freeaddrinfo(ai);
261 return -ENOBUFS;
262 }
263 }
264 }
265
266 if (ai)
267 freeaddrinfo(ai);
268
269 iov[0] = (struct iovec) { .iov_base = &resp, .iov_len = sizeof(AddrInfoResponse) };
270 iov[1] = (struct iovec) { .iov_base = &buffer, .iov_len = resp.header.length - sizeof(AddrInfoResponse) };
271
272 mh.msg_iov = iov;
273 mh.msg_iovlen = ELEMENTSOF(iov);
274
275 if (sendmsg(out_fd, &mh, MSG_NOSIGNAL) < 0)
276 return -errno;
277
278 return 0;
279 }
280
281 static int send_nameinfo_reply(
282 int out_fd,
283 unsigned id,
284 int ret,
285 const char *host,
286 const char *serv,
287 int _errno,
288 int _h_errno) {
289
290 NameInfoResponse resp = {
291 .header.type = RESPONSE_NAMEINFO,
292 .header.id = id,
293 .ret = ret,
294 ._errno = _errno,
295 ._h_errno = _h_errno,
296 };
297
298 struct msghdr mh = {};
299 struct iovec iov[3];
300 size_t hl, sl;
301
302 assert(out_fd >= 0);
303
304 sl = serv ? strlen(serv)+1 : 0;
305 hl = host ? strlen(host)+1 : 0;
306
307 resp.header.length = sizeof(NameInfoResponse) + hl + sl;
308 resp.hostlen = hl;
309 resp.servlen = sl;
310
311 iov[0] = (struct iovec) { .iov_base = &resp, .iov_len = sizeof(NameInfoResponse) };
312 iov[1] = (struct iovec) { .iov_base = (void*) host, .iov_len = hl };
313 iov[2] = (struct iovec) { .iov_base = (void*) serv, .iov_len = sl };
314
315 mh.msg_iov = iov;
316 mh.msg_iovlen = ELEMENTSOF(iov);
317
318 if (sendmsg(out_fd, &mh, MSG_NOSIGNAL) < 0)
319 return -errno;
320
321 return 0;
322 }
323
324 static int handle_request(int out_fd, const Packet *packet, size_t length) {
325 const RHeader *req;
326
327 assert(out_fd >= 0);
328 assert(packet);
329
330 req = &packet->rheader;
331
332 assert(length >= sizeof(RHeader));
333 assert(length == req->length);
334
335 switch (req->type) {
336
337 case REQUEST_ADDRINFO: {
338 const AddrInfoRequest *ai_req = &packet->addrinfo_request;
339 struct addrinfo hints = {}, *result = NULL;
340 const char *node, *service;
341 int ret;
342
343 assert(length >= sizeof(AddrInfoRequest));
344 assert(length == sizeof(AddrInfoRequest) + ai_req->node_len + ai_req->service_len);
345
346 hints.ai_flags = ai_req->ai_flags;
347 hints.ai_family = ai_req->ai_family;
348 hints.ai_socktype = ai_req->ai_socktype;
349 hints.ai_protocol = ai_req->ai_protocol;
350
351 node = ai_req->node_len ? (const char*) ai_req + sizeof(AddrInfoRequest) : NULL;
352 service = ai_req->service_len ? (const char*) ai_req + sizeof(AddrInfoRequest) + ai_req->node_len : NULL;
353
354 ret = getaddrinfo(
355 node, service,
356 ai_req->hints_valid ? &hints : NULL,
357 &result);
358
359 /* send_addrinfo_reply() frees result */
360 return send_addrinfo_reply(out_fd, req->id, ret, result, errno, h_errno);
361 }
362
363 case REQUEST_NAMEINFO: {
364 const NameInfoRequest *ni_req = &packet->nameinfo_request;
365 char hostbuf[NI_MAXHOST], servbuf[NI_MAXSERV];
366 union sockaddr_union sa;
367 int ret;
368
369 assert(length >= sizeof(NameInfoRequest));
370 assert(length == sizeof(NameInfoRequest) + ni_req->sockaddr_len);
371 assert(sizeof(sa) >= ni_req->sockaddr_len);
372
373 memcpy(&sa, (const uint8_t *) ni_req + sizeof(NameInfoRequest), ni_req->sockaddr_len);
374
375 ret = getnameinfo(&sa.sa, ni_req->sockaddr_len,
376 ni_req->gethost ? hostbuf : NULL, ni_req->gethost ? sizeof(hostbuf) : 0,
377 ni_req->getserv ? servbuf : NULL, ni_req->getserv ? sizeof(servbuf) : 0,
378 ni_req->flags);
379
380 return send_nameinfo_reply(out_fd, req->id, ret,
381 ret == 0 && ni_req->gethost ? hostbuf : NULL,
382 ret == 0 && ni_req->getserv ? servbuf : NULL,
383 errno, h_errno);
384 }
385
386 case REQUEST_TERMINATE:
387 /* Quit */
388 return -ECONNRESET;
389
390 default:
391 assert_not_reached("Unknown request");
392 }
393
394 return 0;
395 }
396
397 static void* thread_worker(void *p) {
398 sd_resolve *resolve = p;
399 sigset_t fullset;
400
401 /* No signals in this thread please */
402 assert_se(sigfillset(&fullset) == 0);
403 assert_se(pthread_sigmask(SIG_BLOCK, &fullset, NULL) == 0);
404
405 /* Assign a pretty name to this thread */
406 prctl(PR_SET_NAME, (unsigned long) "sd-resolve");
407
408 while (!resolve->dead) {
409 union {
410 Packet packet;
411 uint8_t space[BUFSIZE];
412 } buf;
413 ssize_t length;
414
415 length = recv(resolve->fds[REQUEST_RECV_FD], &buf, sizeof(buf), 0);
416 if (length < 0) {
417 if (errno == EINTR)
418 continue;
419
420 break;
421 }
422 if (length == 0)
423 break;
424
425 if (resolve->dead)
426 break;
427
428 if (handle_request(resolve->fds[RESPONSE_SEND_FD], &buf.packet, (size_t) length) < 0)
429 break;
430 }
431
432 send_died(resolve->fds[RESPONSE_SEND_FD]);
433
434 return NULL;
435 }
436
437 static int start_threads(sd_resolve *resolve, unsigned extra) {
438 unsigned n;
439 int r;
440
441 n = resolve->n_outstanding + extra;
442 n = CLAMP(n, WORKERS_MIN, WORKERS_MAX);
443
444 while (resolve->n_valid_workers < n) {
445
446 r = pthread_create(&resolve->workers[resolve->n_valid_workers], NULL, thread_worker, resolve);
447 if (r != 0)
448 return -r;
449
450 resolve->n_valid_workers ++;
451 }
452
453 return 0;
454 }
455
456 static bool resolve_pid_changed(sd_resolve *r) {
457 assert(r);
458
459 /* We don't support people creating a resolver and keeping it
460 * around after fork(). Let's complain. */
461
462 return r->original_pid != getpid();
463 }
464
465 _public_ int sd_resolve_new(sd_resolve **ret) {
466 sd_resolve *resolve = NULL;
467 int i, r;
468
469 assert_return(ret, -EINVAL);
470
471 resolve = new0(sd_resolve, 1);
472 if (!resolve)
473 return -ENOMEM;
474
475 resolve->n_ref = 1;
476 resolve->original_pid = getpid();
477
478 for (i = 0; i < _FD_MAX; i++)
479 resolve->fds[i] = -1;
480
481 r = socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds + REQUEST_RECV_FD);
482 if (r < 0) {
483 r = -errno;
484 goto fail;
485 }
486
487 r = socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds + RESPONSE_RECV_FD);
488 if (r < 0) {
489 r = -errno;
490 goto fail;
491 }
492
493 fd_inc_sndbuf(resolve->fds[REQUEST_SEND_FD], QUERIES_MAX * BUFSIZE);
494 fd_inc_rcvbuf(resolve->fds[REQUEST_RECV_FD], QUERIES_MAX * BUFSIZE);
495 fd_inc_sndbuf(resolve->fds[RESPONSE_SEND_FD], QUERIES_MAX * BUFSIZE);
496 fd_inc_rcvbuf(resolve->fds[RESPONSE_RECV_FD], QUERIES_MAX * BUFSIZE);
497
498 fd_nonblock(resolve->fds[RESPONSE_RECV_FD], true);
499
500 *ret = resolve;
501 return 0;
502
503 fail:
504 sd_resolve_unref(resolve);
505 return r;
506 }
507
508 _public_ int sd_resolve_default(sd_resolve **ret) {
509
510 static thread_local sd_resolve *default_resolve = NULL;
511 sd_resolve *e = NULL;
512 int r;
513
514 if (!ret)
515 return !!default_resolve;
516
517 if (default_resolve) {
518 *ret = sd_resolve_ref(default_resolve);
519 return 0;
520 }
521
522 r = sd_resolve_new(&e);
523 if (r < 0)
524 return r;
525
526 e->default_resolve_ptr = &default_resolve;
527 e->tid = gettid();
528 default_resolve = e;
529
530 *ret = e;
531 return 1;
532 }
533
534 _public_ int sd_resolve_get_tid(sd_resolve *resolve, pid_t *tid) {
535 assert_return(resolve, -EINVAL);
536 assert_return(tid, -EINVAL);
537 assert_return(!resolve_pid_changed(resolve), -ECHILD);
538
539 if (resolve->tid != 0) {
540 *tid = resolve->tid;
541 return 0;
542 }
543
544 if (resolve->event)
545 return sd_event_get_tid(resolve->event, tid);
546
547 return -ENXIO;
548 }
549
550 static void resolve_free(sd_resolve *resolve) {
551 PROTECT_ERRNO;
552 sd_resolve_query *q;
553 unsigned i;
554
555 assert(resolve);
556
557 while ((q = resolve->queries)) {
558 assert(q->floating);
559 resolve_query_disconnect(q);
560 sd_resolve_query_unref(q);
561 }
562
563 if (resolve->default_resolve_ptr)
564 *(resolve->default_resolve_ptr) = NULL;
565
566 resolve->dead = true;
567
568 sd_resolve_detach_event(resolve);
569
570 if (resolve->fds[REQUEST_SEND_FD] >= 0) {
571
572 RHeader req = {
573 .type = REQUEST_TERMINATE,
574 .length = sizeof(req)
575 };
576
577 /* Send one termination packet for each worker */
578 for (i = 0; i < resolve->n_valid_workers; i++)
579 (void) send(resolve->fds[REQUEST_SEND_FD], &req, req.length, MSG_NOSIGNAL);
580 }
581
582 /* Now terminate them and wait until they are gone. */
583 for (i = 0; i < resolve->n_valid_workers; i++) {
584 for (;;) {
585 if (pthread_join(resolve->workers[i], NULL) != EINTR)
586 break;
587 }
588 }
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 }