chiark / gitweb /
f05fe10b6ae31d236d55e261cca2512f36bf6e5c
[elogind.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 }