chiark / gitweb /
libsystemd: split up into subdirs
[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
44 #include "sd-resolve.h"
45 #include "util.h"
46
47 #define MAX_WORKERS 16
48 #define MAX_QUERIES 256
49 #define BUFSIZE (10240)
50
51 typedef enum {
52         REQUEST_ADDRINFO,
53         RESPONSE_ADDRINFO,
54         REQUEST_NAMEINFO,
55         RESPONSE_NAMEINFO,
56         REQUEST_RES_QUERY,
57         REQUEST_RES_SEARCH,
58         RESPONSE_RES,
59         REQUEST_TERMINATE,
60         RESPONSE_DIED
61 } QueryType;
62
63 enum {
64         REQUEST_RECV_FD = 0,
65         REQUEST_SEND_FD = 1,
66         RESPONSE_RECV_FD = 2,
67         RESPONSE_SEND_FD = 3,
68         MESSAGE_FD_MAX = 4
69 };
70
71 struct sd_resolve {
72         int fds[MESSAGE_FD_MAX];
73
74         pthread_t workers[MAX_WORKERS];
75         unsigned valid_workers;
76
77         unsigned current_id, current_index;
78         sd_resolve_query* queries[MAX_QUERIES];
79
80         sd_resolve_query *done_head, *done_tail;
81
82         int n_queries;
83         int dead;
84 };
85
86 struct sd_resolve_query {
87         sd_resolve *resolve;
88         int done;
89         unsigned id;
90         QueryType type;
91         sd_resolve_query *done_next, *done_prev;
92         int ret;
93         int _errno;
94         int _h_errno;
95         struct addrinfo *addrinfo;
96         char *serv, *host;
97         void *userdata;
98 };
99
100 typedef struct RHeader {
101         QueryType type;
102         unsigned id;
103         size_t length;
104 } RHeader;
105
106 typedef struct AddrInfoRequest {
107         struct RHeader header;
108         int hints_is_null;
109         int ai_flags;
110         int ai_family;
111         int ai_socktype;
112         int ai_protocol;
113         size_t node_len, service_len;
114 } AddrInfoRequest;
115
116 typedef struct AddrInfoResponse {
117         struct RHeader header;
118         int ret;
119         int _errno;
120         int _h_errno;
121         /* followed by addrinfo_serialization[] */
122 } AddrInfoResponse;
123
124 typedef struct AddrInfoSerialization {
125         int ai_flags;
126         int ai_family;
127         int ai_socktype;
128         int ai_protocol;
129         size_t ai_addrlen;
130         size_t canonname_len;
131         /* Followed by ai_addr amd ai_canonname with variable lengths */
132 } AddrInfoSerialization;
133
134 typedef struct NameInfoRequest {
135         struct RHeader header;
136         int flags;
137         socklen_t sockaddr_len;
138         int gethost, getserv;
139 } NameInfoRequest;
140
141 typedef struct NameInfoResponse {
142         struct RHeader header;
143         size_t hostlen, servlen;
144         int ret;
145         int _errno;
146         int _h_errno;
147 } NameInfoResponse;
148
149 typedef struct ResRequest {
150         struct RHeader header;
151         int class;
152         int type;
153         size_t dname_len;
154 } ResRequest;
155
156 typedef struct ResResponse {
157         struct RHeader header;
158         int ret;
159         int _errno;
160         int _h_errno;
161 } ResResponse;
162
163 typedef union Packet {
164         RHeader rheader;
165         AddrInfoRequest addrinfo_request;
166         AddrInfoResponse addrinfo_response;
167         NameInfoRequest nameinfo_request;
168         NameInfoResponse nameinfo_response;
169         ResRequest res_request;
170         ResResponse res_response;
171 } Packet;
172
173 static int send_died(int out_fd) {
174         RHeader rh = {};
175         assert(out_fd > 0);
176
177         rh.type = RESPONSE_DIED;
178         rh.id = 0;
179         rh.length = sizeof(rh);
180
181         return send(out_fd, &rh, rh.length, MSG_NOSIGNAL);
182 }
183
184 static void *serialize_addrinfo(void *p, const struct addrinfo *ai, size_t *length, size_t maxlength) {
185         AddrInfoSerialization s;
186         size_t cnl, l;
187         assert(p);
188         assert(ai);
189         assert(length);
190         assert(*length <= maxlength);
191
192         cnl = (ai->ai_canonname ? strlen(ai->ai_canonname)+1 : 0);
193         l = sizeof(AddrInfoSerialization) + ai->ai_addrlen + cnl;
194
195         if (*length + l > maxlength)
196                 return NULL;
197
198         s.ai_flags = ai->ai_flags;
199         s.ai_family = ai->ai_family;
200         s.ai_socktype = ai->ai_socktype;
201         s.ai_protocol = ai->ai_protocol;
202         s.ai_addrlen = ai->ai_addrlen;
203         s.canonname_len = cnl;
204
205         memcpy((uint8_t*) p, &s, sizeof(AddrInfoSerialization));
206         memcpy((uint8_t*) p + sizeof(AddrInfoSerialization), ai->ai_addr, ai->ai_addrlen);
207
208         if (ai->ai_canonname)
209                 strcpy((char*) p + sizeof(AddrInfoSerialization) + ai->ai_addrlen, ai->ai_canonname);
210
211         *length += l;
212         return (uint8_t*) p + l;
213 }
214
215 static int send_addrinfo_reply(int out_fd, unsigned id, int ret, struct addrinfo *ai, int _errno, int _h_errno) {
216         AddrInfoResponse data[BUFSIZE/sizeof(AddrInfoResponse) + 1] = {};
217         AddrInfoResponse *resp = data;
218         assert(out_fd >= 0);
219
220         resp->header.type = RESPONSE_ADDRINFO;
221         resp->header.id = id;
222         resp->header.length = sizeof(AddrInfoResponse);
223         resp->ret = ret;
224         resp->_errno = _errno;
225         resp->_h_errno = _h_errno;
226
227         if (ret == 0 && ai) {
228                 void *p = data + 1;
229                 struct addrinfo *k;
230
231                 for (k = ai; k; k = k->ai_next) {
232                         p = serialize_addrinfo(p, k, &resp->header.length, (char*) data + BUFSIZE - (char*) p);
233                         if (!p) {
234                                 resp->ret = EAI_MEMORY;
235                                 break;
236                         }
237                 }
238         }
239
240         if (ai)
241                 freeaddrinfo(ai);
242
243         return send(out_fd, resp, resp->header.length, MSG_NOSIGNAL);
244 }
245
246 static int send_nameinfo_reply(int out_fd, unsigned id, int ret, const char *host, const char *serv, int _errno, int _h_errno) {
247         NameInfoResponse data[BUFSIZE/sizeof(NameInfoResponse) + 1] = {};
248         size_t hl, sl;
249         NameInfoResponse *resp = data;
250
251         assert(out_fd >= 0);
252
253         sl = serv ? strlen(serv)+1 : 0;
254         hl = host ? strlen(host)+1 : 0;
255
256         resp->header.type = RESPONSE_NAMEINFO;
257         resp->header.id = id;
258         resp->header.length = sizeof(NameInfoResponse) + hl + sl;
259         resp->ret = ret;
260         resp->_errno = _errno;
261         resp->_h_errno = _h_errno;
262         resp->hostlen = hl;
263         resp->servlen = sl;
264
265         assert(sizeof(data) >= resp->header.length);
266
267         if (host)
268                 memcpy((uint8_t *)data + sizeof(NameInfoResponse), host, hl);
269
270         if (serv)
271                 memcpy((uint8_t *)data + sizeof(NameInfoResponse) + hl, serv, sl);
272
273         return send(out_fd, resp, resp->header.length, MSG_NOSIGNAL);
274 }
275
276 static int send_res_reply(int out_fd, unsigned id, const unsigned char *answer, int ret, int _errno, int _h_errno) {
277         ResResponse data[BUFSIZE/sizeof(ResResponse) + 1] = {};
278         ResResponse *resp = data;
279
280         assert(out_fd >= 0);
281
282         resp->header.type = RESPONSE_RES;
283         resp->header.id = id;
284         resp->header.length = sizeof(ResResponse) + (ret < 0 ? 0 : ret);
285         resp->ret = ret;
286         resp->_errno = _errno;
287         resp->_h_errno = _h_errno;
288
289         assert(sizeof(data) >= resp->header.length);
290
291         if (ret > 0)
292                 memcpy((uint8_t *)data + sizeof(ResResponse), answer, ret);
293
294         return send(out_fd, resp, resp->header.length, MSG_NOSIGNAL);
295 }
296
297 static int handle_request(int out_fd, const Packet *packet, size_t length) {
298         const RHeader *req;
299         assert(out_fd >= 0);
300
301         req = &packet->rheader;
302         assert(req);
303         assert(length >= sizeof(RHeader));
304         assert(length == req->length);
305
306         switch (req->type) {
307         case REQUEST_ADDRINFO: {
308                struct addrinfo ai = {}, *result = NULL;
309                const AddrInfoRequest *ai_req = &packet->addrinfo_request;
310                const char *node, *service;
311                int ret;
312
313                assert(length >= sizeof(AddrInfoRequest));
314                assert(length == sizeof(AddrInfoRequest) + ai_req->node_len + ai_req->service_len);
315
316                ai.ai_flags = ai_req->ai_flags;
317                ai.ai_family = ai_req->ai_family;
318                ai.ai_socktype = ai_req->ai_socktype;
319                ai.ai_protocol = ai_req->ai_protocol;
320
321                node = ai_req->node_len ? (const char*) ai_req + sizeof(AddrInfoRequest) : NULL;
322                service = ai_req->service_len ? (const char*) ai_req + sizeof(AddrInfoRequest) + ai_req->node_len : NULL;
323
324                ret = getaddrinfo(node, service,
325                                ai_req->hints_is_null ? NULL : &ai,
326                                &result);
327
328                /* send_addrinfo_reply() frees result */
329                return send_addrinfo_reply(out_fd, req->id, ret, result, errno, h_errno);
330         }
331
332         case REQUEST_NAMEINFO: {
333                int ret;
334                const NameInfoRequest *ni_req = &packet->nameinfo_request;
335                char hostbuf[NI_MAXHOST], servbuf[NI_MAXSERV];
336                struct sockaddr_storage sa;
337
338                assert(length >= sizeof(NameInfoRequest));
339                assert(length == sizeof(NameInfoRequest) + ni_req->sockaddr_len);
340
341                memcpy(&sa, (const uint8_t *) ni_req + sizeof(NameInfoRequest), ni_req->sockaddr_len);
342
343                ret = getnameinfo((struct sockaddr *)&sa, ni_req->sockaddr_len,
344                                ni_req->gethost ? hostbuf : NULL, ni_req->gethost ? sizeof(hostbuf) : 0,
345                                ni_req->getserv ? servbuf : NULL, ni_req->getserv ? sizeof(servbuf) : 0,
346                                ni_req->flags);
347
348                return send_nameinfo_reply(out_fd, req->id, ret,
349                                ret == 0 && ni_req->gethost ? hostbuf : NULL,
350                                ret == 0 && ni_req->getserv ? servbuf : NULL,
351                                errno, h_errno);
352         }
353
354         case REQUEST_RES_QUERY:
355         case REQUEST_RES_SEARCH: {
356                  int ret;
357                  HEADER answer[BUFSIZE/sizeof(HEADER) + 1];
358                  const ResRequest *res_req = &packet->res_request;
359                  const char *dname;
360
361                  assert(length >= sizeof(ResRequest));
362                  assert(length == sizeof(ResRequest) + res_req->dname_len);
363
364                  dname = (const char *) req + sizeof(ResRequest);
365
366                  if (req->type == REQUEST_RES_QUERY)
367                          ret = res_query(dname, res_req->class, res_req->type, (unsigned char *) answer, BUFSIZE);
368                  else
369                          ret = res_search(dname, res_req->class, res_req->type, (unsigned char *) answer, BUFSIZE);
370
371                  return send_res_reply(out_fd, req->id, (unsigned char *) answer, ret, errno, h_errno);
372         }
373
374         case REQUEST_TERMINATE:
375                  /* Quit */
376                  return -1;
377
378         default:
379                  ;
380         }
381
382         return 0;
383 }
384
385 static void* thread_worker(void *p) {
386         sd_resolve *resolve = p;
387         sigset_t fullset;
388
389         /* No signals in this thread please */
390         sigfillset(&fullset);
391         pthread_sigmask(SIG_BLOCK, &fullset, NULL);
392
393         while (!resolve->dead) {
394                 Packet buf[BUFSIZE/sizeof(Packet) + 1];
395                 ssize_t length;
396
397                 length = recv(resolve->fds[REQUEST_RECV_FD], buf, sizeof(buf), 0);
398
399                 if (length <= 0) {
400                         if (length < 0 && (errno == EAGAIN || errno == EINTR))
401                                 continue;
402                         break;
403                 }
404
405                 if (resolve->dead)
406                         break;
407
408                 if (handle_request(resolve->fds[RESPONSE_SEND_FD], buf, (size_t) length) < 0)
409                         break;
410         }
411
412         send_died(resolve->fds[RESPONSE_SEND_FD]);
413
414         return NULL;
415 }
416
417 _public_ sd_resolve* sd_resolve_new(unsigned n_proc) {
418         sd_resolve *resolve = NULL;
419         int i, r;
420
421         assert(n_proc >= 1);
422
423         if (n_proc > MAX_WORKERS)
424                 n_proc = MAX_WORKERS;
425
426         resolve = new(sd_resolve, 1);
427         if (!resolve) {
428                 errno = ENOMEM;
429                 goto fail;
430         }
431
432         resolve->dead = 0;
433         resolve->valid_workers = 0;
434
435         for (i = 0; i < MESSAGE_FD_MAX; i++)
436                 resolve->fds[i] = -1;
437
438         memset(resolve->queries, 0, sizeof(resolve->queries));
439
440         r = socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds);
441         if (r < 0)
442                 goto fail;
443
444         r = socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds+2);
445         if (r < 0)
446                 goto fail;
447
448         for (resolve->valid_workers = 0; resolve->valid_workers < n_proc; resolve->valid_workers++) {
449                 r = pthread_create(&resolve->workers[resolve->valid_workers], NULL, thread_worker, resolve);
450                 if (r) {
451                         errno = r;
452                         goto fail;
453                 }
454         }
455
456         resolve->current_index = resolve->current_id = 0;
457         resolve->done_head = resolve->done_tail = NULL;
458         resolve->n_queries = 0;
459
460         fd_nonblock(resolve->fds[RESPONSE_RECV_FD], true);
461
462         return resolve;
463
464 fail:
465         if (resolve)
466                 sd_resolve_free(resolve);
467
468         return NULL;
469 }
470
471 _public_ void sd_resolve_free(sd_resolve *resolve) {
472         int i;
473         int saved_errno = errno;
474         unsigned p;
475
476         assert(resolve);
477
478         resolve->dead = 1;
479
480         if (resolve->fds[REQUEST_SEND_FD] >= 0) {
481                 RHeader req = {};
482
483                 req.type = REQUEST_TERMINATE;
484                 req.length = sizeof(req);
485                 req.id = 0;
486
487                 /* Send one termination packet for each worker */
488                 for (p = 0; p < resolve->valid_workers; p++)
489                         send(resolve->fds[REQUEST_SEND_FD], &req, req.length, MSG_NOSIGNAL);
490         }
491
492         /* Now terminate them and wait until they are gone. */
493         for (p = 0; p < resolve->valid_workers; p++) {
494                 for (;;) {
495                         if (pthread_join(resolve->workers[p], NULL) != EINTR)
496                                 break;
497                 }
498         }
499
500         /* Close all communication channels */
501         for (i = 0; i < MESSAGE_FD_MAX; i++)
502                 if (resolve->fds[i] >= 0)
503                         close(resolve->fds[i]);
504
505         for (p = 0; p < MAX_QUERIES; p++)
506                 if (resolve->queries[p])
507                         sd_resolve_cancel(resolve, resolve->queries[p]);
508
509         free(resolve);
510
511         errno = saved_errno;
512 }
513
514 _public_ int sd_resolve_fd(sd_resolve *resolve) {
515         assert(resolve);
516
517         return resolve->fds[RESPONSE_RECV_FD];
518 }
519
520 static sd_resolve_query *lookup_query(sd_resolve *resolve, unsigned id) {
521         sd_resolve_query *q;
522         assert(resolve);
523
524         q = resolve->queries[id % MAX_QUERIES];
525         if (q)
526                 if (q->id == id)
527                         return q;
528
529         return NULL;
530 }
531
532 static void complete_query(sd_resolve *resolve, sd_resolve_query *q) {
533         assert(resolve);
534         assert(q);
535         assert(!q->done);
536
537         q->done = 1;
538
539         if ((q->done_prev = resolve->done_tail))
540                 resolve->done_tail->done_next = q;
541         else
542                 resolve->done_head = q;
543
544         resolve->done_tail = q;
545         q->done_next = NULL;
546 }
547
548 static const void *unserialize_addrinfo(const void *p, struct addrinfo **ret_ai, size_t *length) {
549         AddrInfoSerialization s;
550         size_t l;
551         struct addrinfo *ai;
552         assert(p);
553         assert(ret_ai);
554         assert(length);
555
556         if (*length < sizeof(AddrInfoSerialization))
557                 return NULL;
558
559         memcpy(&s, p, sizeof(s));
560
561         l = sizeof(AddrInfoSerialization) + s.ai_addrlen + s.canonname_len;
562         if (*length < l)
563                 return NULL;
564
565         ai = new(struct addrinfo, 1);
566         if (!ai)
567                 goto fail;
568
569         ai->ai_addr = NULL;
570         ai->ai_canonname = NULL;
571         ai->ai_next = NULL;
572
573         if (s.ai_addrlen && !(ai->ai_addr = malloc(s.ai_addrlen)))
574                 goto fail;
575
576         if (s.canonname_len && !(ai->ai_canonname = malloc(s.canonname_len)))
577                 goto fail;
578
579         ai->ai_flags = s.ai_flags;
580         ai->ai_family = s.ai_family;
581         ai->ai_socktype = s.ai_socktype;
582         ai->ai_protocol = s.ai_protocol;
583         ai->ai_addrlen = s.ai_addrlen;
584
585         if (ai->ai_addr)
586                 memcpy(ai->ai_addr, (const uint8_t*) p + sizeof(AddrInfoSerialization), s.ai_addrlen);
587
588         if (ai->ai_canonname)
589                 memcpy(ai->ai_canonname, (const uint8_t*) p + sizeof(AddrInfoSerialization) + s.ai_addrlen, s.canonname_len);
590
591         *length -= l;
592         *ret_ai = ai;
593
594         return (const uint8_t*) p + l;
595
596
597 fail:
598         if (ai)
599                 sd_resolve_freeaddrinfo(ai);
600
601         return NULL;
602 }
603
604 static int handle_response(sd_resolve *resolve, const Packet *packet, size_t length) {
605         const RHeader *resp;
606         sd_resolve_query *q;
607
608         assert(resolve);
609
610         resp = &packet->rheader;
611         assert(resp);
612         assert(length >= sizeof(RHeader));
613         assert(length == resp->length);
614
615         if (resp->type == RESPONSE_DIED) {
616                 resolve->dead = 1;
617                 return 0;
618         }
619
620         q = lookup_query(resolve, resp->id);
621         if (!q)
622                 return 0;
623
624         switch (resp->type) {
625         case RESPONSE_ADDRINFO: {
626                 const AddrInfoResponse *ai_resp = &packet->addrinfo_response;
627                 const void *p;
628                 size_t l;
629                 struct addrinfo *prev = NULL;
630
631                 assert(length >= sizeof(AddrInfoResponse));
632                 assert(q->type == REQUEST_ADDRINFO);
633
634                 q->ret = ai_resp->ret;
635                 q->_errno = ai_resp->_errno;
636                 q->_h_errno = ai_resp->_h_errno;
637                 l = length - sizeof(AddrInfoResponse);
638                 p = (const uint8_t*) resp + sizeof(AddrInfoResponse);
639
640                 while (l > 0 && p) {
641                         struct addrinfo *ai = NULL;
642                         p = unserialize_addrinfo(p, &ai, &l);
643
644                         if (!p || !ai) {
645                                 q->ret = EAI_MEMORY;
646                                 break;
647                         }
648
649                         if (prev)
650                                 prev->ai_next = ai;
651                         else
652                                 q->addrinfo = ai;
653
654                         prev = ai;
655                 }
656
657                 complete_query(resolve, q);
658                 break;
659         }
660
661         case RESPONSE_NAMEINFO: {
662                 const NameInfoResponse *ni_resp = &packet->nameinfo_response;
663
664                 assert(length >= sizeof(NameInfoResponse));
665                 assert(q->type == REQUEST_NAMEINFO);
666
667                 q->ret = ni_resp->ret;
668                 q->_errno = ni_resp->_errno;
669                 q->_h_errno = ni_resp->_h_errno;
670
671                 if (ni_resp->hostlen)
672                         if (!(q->host = strndup((const char*) ni_resp + sizeof(NameInfoResponse), ni_resp->hostlen-1)))
673                                 q->ret = EAI_MEMORY;
674
675                 if (ni_resp->servlen)
676                         if (!(q->serv = strndup((const char*) ni_resp + sizeof(NameInfoResponse) + ni_resp->hostlen, ni_resp->servlen-1)))
677                                 q->ret = EAI_MEMORY;
678
679                 complete_query(resolve, q);
680                 break;
681         }
682
683         case RESPONSE_RES: {
684                 const ResResponse *res_resp = &packet->res_response;
685
686                 assert(length >= sizeof(ResResponse));
687                 assert(q->type == REQUEST_RES_QUERY || q->type == REQUEST_RES_SEARCH);
688
689                 q->ret = res_resp->ret;
690                 q->_errno = res_resp->_errno;
691                 q->_h_errno = res_resp->_h_errno;
692
693                 if (res_resp->ret >= 0)  {
694                         if (!(q->serv = malloc(res_resp->ret))) {
695                                 q->ret = -1;
696                                 q->_errno = ENOMEM;
697                         } else
698                                 memcpy(q->serv, (const char *)resp + sizeof(ResResponse), res_resp->ret);
699                 }
700
701                 complete_query(resolve, q);
702                 break;
703         }
704
705         default:
706                 ;
707         }
708
709         return 0;
710 }
711
712 _public_ int sd_resolve_wait(sd_resolve *resolve, int block) {
713         int handled = 0;
714         assert(resolve);
715
716         for (;;) {
717                 Packet buf[BUFSIZE/sizeof(Packet) + 1];
718                 ssize_t l;
719
720                 if (resolve->dead) {
721                         errno = ECHILD;
722                         return -1;
723                 }
724
725                 l = recv(resolve->fds[RESPONSE_RECV_FD], buf, sizeof(buf), 0);
726                 if (l < 0) {
727                         fd_set fds;
728
729                         if (errno != EAGAIN)
730                                 return -1;
731
732                         if (!block || handled)
733                                 return 0;
734
735                         FD_ZERO(&fds);
736                         FD_SET(resolve->fds[RESPONSE_RECV_FD], &fds);
737
738                         if (select(resolve->fds[RESPONSE_RECV_FD]+1, &fds, NULL, NULL, NULL) < 0)
739                                 return -1;
740
741                         continue;
742                 }
743
744                 if (handle_response(resolve, buf, (size_t) l) < 0)
745                         return -1;
746
747                 handled = 1;
748         }
749 }
750
751 static sd_resolve_query *alloc_query(sd_resolve *resolve) {
752         sd_resolve_query *q;
753         assert(resolve);
754
755         if (resolve->n_queries >= MAX_QUERIES) {
756                 errno = ENOMEM;
757                 return NULL;
758         }
759
760         while (resolve->queries[resolve->current_index]) {
761                 resolve->current_index++;
762                 resolve->current_id++;
763
764                 while (resolve->current_index >= MAX_QUERIES)
765                         resolve->current_index -= MAX_QUERIES;
766         }
767
768         q = resolve->queries[resolve->current_index] = new(sd_resolve_query, 1);
769         if (!q) {
770                 errno = ENOMEM;
771                 return NULL;
772         }
773
774         resolve->n_queries++;
775
776         q->resolve = resolve;
777         q->done = 0;
778         q->id = resolve->current_id;
779         q->done_next = q->done_prev = NULL;
780         q->ret = 0;
781         q->_errno = 0;
782         q->_h_errno = 0;
783         q->addrinfo = NULL;
784         q->userdata = NULL;
785         q->host = q->serv = NULL;
786
787         return q;
788 }
789
790 _public_ sd_resolve_query* sd_resolve_getaddrinfo(sd_resolve *resolve, const char *node, const char *service, const struct addrinfo *hints) {
791         AddrInfoRequest data[BUFSIZE/sizeof(AddrInfoRequest) + 1] = {};
792         AddrInfoRequest *req = data;
793         sd_resolve_query *q;
794         assert(resolve);
795         assert(node || service);
796
797         if (resolve->dead) {
798                 errno = ECHILD;
799                 return NULL;
800         }
801
802         q = alloc_query(resolve);
803         if (!q)
804                 return NULL;
805
806         req->node_len = node ? strlen(node)+1 : 0;
807         req->service_len = service ? strlen(service)+1 : 0;
808
809         req->header.id = q->id;
810         req->header.type = q->type = REQUEST_ADDRINFO;
811         req->header.length = sizeof(AddrInfoRequest) + req->node_len + req->service_len;
812
813         if (req->header.length > BUFSIZE) {
814                 errno = ENOMEM;
815                 goto fail;
816         }
817
818         if (!(req->hints_is_null = !hints)) {
819                 req->ai_flags = hints->ai_flags;
820                 req->ai_family = hints->ai_family;
821                 req->ai_socktype = hints->ai_socktype;
822                 req->ai_protocol = hints->ai_protocol;
823         }
824
825         if (node)
826                 strcpy((char*) req + sizeof(AddrInfoRequest), node);
827
828         if (service)
829                 strcpy((char*) req + sizeof(AddrInfoRequest) + req->node_len, service);
830
831         if (send(resolve->fds[REQUEST_SEND_FD], req, req->header.length, MSG_NOSIGNAL) < 0)
832                 goto fail;
833
834         return q;
835
836 fail:
837         if (q)
838                 sd_resolve_cancel(resolve, q);
839
840         return NULL;
841 }
842
843 _public_ int sd_resolve_getaddrinfo_done(sd_resolve *resolve, sd_resolve_query* q, struct addrinfo **ret_res) {
844         int ret;
845         assert(resolve);
846         assert(q);
847         assert(q->resolve == resolve);
848         assert(q->type == REQUEST_ADDRINFO);
849
850         if (resolve->dead) {
851                 errno = ECHILD;
852                 return EAI_SYSTEM;
853         }
854
855         if (!q->done)
856                 return EAI_AGAIN;
857
858         *ret_res = q->addrinfo;
859         q->addrinfo = NULL;
860
861         ret = q->ret;
862
863         if (ret == EAI_SYSTEM)
864                 errno = q->_errno;
865
866         if (ret != 0)
867                 h_errno = q->_h_errno;
868
869         sd_resolve_cancel(resolve, q);
870
871         return ret;
872 }
873
874 _public_ sd_resolve_query* sd_resolve_getnameinfo(sd_resolve *resolve, const struct sockaddr *sa, socklen_t salen, int flags, int gethost, int getserv) {
875         NameInfoRequest data[BUFSIZE/sizeof(NameInfoRequest) + 1] = {};
876         NameInfoRequest *req = data;
877         sd_resolve_query *q;
878
879         assert(resolve);
880         assert(sa);
881         assert(salen > 0);
882
883         if (resolve->dead) {
884                 errno = ECHILD;
885                 return NULL;
886         }
887
888         q = alloc_query(resolve);
889         if (!q)
890                 return NULL;
891
892         req->header.id = q->id;
893         req->header.type = q->type = REQUEST_NAMEINFO;
894         req->header.length = sizeof(NameInfoRequest) + salen;
895
896         if (req->header.length > BUFSIZE) {
897                 errno = ENOMEM;
898                 goto fail;
899         }
900
901         req->flags = flags;
902         req->sockaddr_len = salen;
903         req->gethost = gethost;
904         req->getserv = getserv;
905
906         memcpy((uint8_t*) req + sizeof(NameInfoRequest), sa, salen);
907
908         if (send(resolve->fds[REQUEST_SEND_FD], req, req->header.length, MSG_NOSIGNAL) < 0)
909                 goto fail;
910
911         return q;
912
913 fail:
914         if (q)
915                 sd_resolve_cancel(resolve, q);
916
917         return NULL;
918 }
919
920 _public_ int sd_resolve_getnameinfo_done(sd_resolve *resolve, sd_resolve_query* q, char *ret_host, size_t hostlen, char *ret_serv, size_t servlen) {
921         int ret;
922         assert(resolve);
923         assert(q);
924         assert(q->resolve == resolve);
925         assert(q->type == REQUEST_NAMEINFO);
926         assert(!ret_host || hostlen);
927         assert(!ret_serv || servlen);
928
929         if (resolve->dead) {
930                 errno = ECHILD;
931                 return EAI_SYSTEM;
932         }
933
934         if (!q->done)
935                 return EAI_AGAIN;
936
937         if (ret_host && q->host) {
938                 strncpy(ret_host, q->host, hostlen);
939                 ret_host[hostlen-1] = 0;
940         }
941
942         if (ret_serv && q->serv) {
943                 strncpy(ret_serv, q->serv, servlen);
944                 ret_serv[servlen-1] = 0;
945         }
946
947         ret = q->ret;
948
949         if (ret == EAI_SYSTEM)
950                 errno = q->_errno;
951
952         if (ret != 0)
953                 h_errno = q->_h_errno;
954
955         sd_resolve_cancel(resolve, q);
956
957         return ret;
958 }
959
960 static sd_resolve_query * resolve_res(sd_resolve *resolve, QueryType qtype, const char *dname, int class, int type) {
961         ResRequest data[BUFSIZE/sizeof(ResRequest) + 1];
962         ResRequest *req = data;
963         sd_resolve_query *q;
964
965         assert(resolve);
966         assert(dname);
967
968         if (resolve->dead) {
969                 errno = ECHILD;
970                 return NULL;
971         }
972
973         q = alloc_query(resolve);
974         if (!q)
975                 return NULL;
976
977         req->dname_len = strlen(dname) + 1;
978
979         req->header.id = q->id;
980         req->header.type = q->type = qtype;
981         req->header.length = sizeof(ResRequest) + req->dname_len;
982
983         if (req->header.length > BUFSIZE) {
984                 errno = ENOMEM;
985                 goto fail;
986         }
987
988         req->class = class;
989         req->type = type;
990
991         strcpy((char*) req + sizeof(ResRequest), dname);
992
993         if (send(resolve->fds[REQUEST_SEND_FD], req, req->header.length, MSG_NOSIGNAL) < 0)
994                 goto fail;
995
996         return q;
997
998 fail:
999         if (q)
1000                 sd_resolve_cancel(resolve, q);
1001
1002         return NULL;
1003 }
1004
1005 _public_ sd_resolve_query* sd_resolve_res_query(sd_resolve *resolve, const char *dname, int class, int type) {
1006         return resolve_res(resolve, REQUEST_RES_QUERY, dname, class, type);
1007 }
1008
1009 _public_ sd_resolve_query* sd_resolve_res_search(sd_resolve *resolve, const char *dname, int class, int type) {
1010         return resolve_res(resolve, REQUEST_RES_SEARCH, dname, class, type);
1011 }
1012
1013 _public_ int sd_resolve_res_done(sd_resolve *resolve, sd_resolve_query* q, unsigned char **answer) {
1014         int ret;
1015         assert(resolve);
1016         assert(q);
1017         assert(q->resolve == resolve);
1018         assert(q->type == REQUEST_RES_QUERY || q->type == REQUEST_RES_SEARCH);
1019         assert(answer);
1020
1021         if (resolve->dead) {
1022                 errno = ECHILD;
1023                 return -ECHILD;
1024         }
1025
1026         if (!q->done) {
1027                 errno = EAGAIN;
1028                 return -EAGAIN;
1029         }
1030
1031         *answer = (unsigned char *)q->serv;
1032         q->serv = NULL;
1033
1034         ret = q->ret;
1035
1036         if (ret < 0) {
1037                 errno = q->_errno;
1038                 h_errno = q->_h_errno;
1039         }
1040
1041         sd_resolve_cancel(resolve, q);
1042
1043         return ret < 0 ? -errno : ret;
1044 }
1045
1046 _public_ sd_resolve_query* sd_resolve_get_next(sd_resolve *resolve) {
1047         assert(resolve);
1048         return resolve->done_head;
1049 }
1050
1051 _public_ int sd_resolve_get_n_queries(sd_resolve *resolve) {
1052         assert(resolve);
1053         return resolve->n_queries;
1054 }
1055
1056 _public_ void sd_resolve_cancel(sd_resolve *resolve, sd_resolve_query* q) {
1057         int i;
1058         int saved_errno = errno;
1059
1060         assert(resolve);
1061         assert(q);
1062         assert(q->resolve == resolve);
1063         assert(resolve->n_queries > 0);
1064
1065         if (q->done) {
1066
1067                 if (q->done_prev)
1068                         q->done_prev->done_next = q->done_next;
1069                 else
1070                         resolve->done_head = q->done_next;
1071
1072                 if (q->done_next)
1073                         q->done_next->done_prev = q->done_prev;
1074                 else
1075                         resolve->done_tail = q->done_prev;
1076         }
1077
1078         i = q->id % MAX_QUERIES;
1079         assert(resolve->queries[i] == q);
1080         resolve->queries[i] = NULL;
1081
1082         sd_resolve_freeaddrinfo(q->addrinfo);
1083         free(q->host);
1084         free(q->serv);
1085
1086         resolve->n_queries--;
1087         free(q);
1088
1089         errno = saved_errno;
1090 }
1091
1092 _public_ void sd_resolve_freeaddrinfo(struct addrinfo *ai) {
1093         int saved_errno = errno;
1094
1095         while (ai) {
1096                 struct addrinfo *next = ai->ai_next;
1097
1098                 free(ai->ai_addr);
1099                 free(ai->ai_canonname);
1100                 free(ai);
1101
1102                 ai = next;
1103         }
1104
1105         errno = saved_errno;
1106 }
1107
1108 _public_ int sd_resolve_isdone(sd_resolve *resolve, sd_resolve_query*q) {
1109         assert(resolve);
1110         assert(q);
1111         assert(q->resolve == resolve);
1112
1113         return q->done;
1114 }
1115
1116 _public_ void sd_resolve_setuserdata(sd_resolve *resolve, sd_resolve_query *q, void *userdata) {
1117         assert(q);
1118         assert(resolve);
1119         assert(q->resolve = resolve);
1120
1121         q->userdata = userdata;
1122 }
1123
1124 _public_ void* sd_resolve_getuserdata(sd_resolve *resolve, sd_resolve_query *q) {
1125         assert(q);
1126         assert(resolve);
1127         assert(q->resolve = resolve);
1128
1129         return q->userdata;
1130 }