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