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