chiark / gitweb /
libsystemd-bus: rename to libsystemd
[elogind.git] / src / libsystemd / sd-dns.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-dns.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 } query_type_t;
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 asyncns {
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         asyncns_query_t* queries[MAX_QUERIES];
79
80         asyncns_query_t *done_head, *done_tail;
81
82         int n_queries;
83         int dead;
84 };
85
86 struct asyncns_query {
87         asyncns_t *asyncns;
88         int done;
89         unsigned id;
90         query_type_t type;
91         asyncns_query_t *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         query_type_t type;
102         unsigned id;
103         size_t length;
104 } rheader_t;
105
106 typedef struct addrinfo_request {
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 } addrinfo_request_t;
115
116 typedef struct addrinfo_response {
117         struct rheader header;
118         int ret;
119         int _errno;
120         int _h_errno;
121         /* followed by addrinfo_serialization[] */
122 } addrinfo_response_t;
123
124 typedef struct addrinfo_serialization {
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 } addrinfo_serialization_t;
133
134 typedef struct nameinfo_request {
135         struct rheader header;
136         int flags;
137         socklen_t sockaddr_len;
138         int gethost, getserv;
139 } nameinfo_request_t;
140
141 typedef struct nameinfo_response {
142         struct rheader header;
143         size_t hostlen, servlen;
144         int ret;
145         int _errno;
146         int _h_errno;
147 } nameinfo_response_t;
148
149 typedef struct res_request {
150         struct rheader header;
151         int class;
152         int type;
153         size_t dname_len;
154 } res_request_t;
155
156 typedef struct res_response {
157         struct rheader header;
158         int ret;
159         int _errno;
160         int _h_errno;
161 } res_response_t;
162
163 typedef union packet {
164         rheader_t rheader;
165         addrinfo_request_t addrinfo_request;
166         addrinfo_response_t addrinfo_response;
167         nameinfo_request_t nameinfo_request;
168         nameinfo_response_t nameinfo_response;
169         res_request_t res_request;
170         res_response_t res_response;
171 } packet_t;
172
173 static int send_died(int out_fd) {
174         rheader_t 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         addrinfo_serialization_t 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(addrinfo_serialization_t) + 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(addrinfo_serialization_t));
206         memcpy((uint8_t*) p + sizeof(addrinfo_serialization_t), ai->ai_addr, ai->ai_addrlen);
207
208         if (ai->ai_canonname)
209                 strcpy((char*) p + sizeof(addrinfo_serialization_t) + 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         addrinfo_response_t data[BUFSIZE/sizeof(addrinfo_response_t) + 1] = {};
217         addrinfo_response_t *resp = data;
218         assert(out_fd >= 0);
219
220         resp->header.type = RESPONSE_ADDRINFO;
221         resp->header.id = id;
222         resp->header.length = sizeof(addrinfo_response_t);
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         nameinfo_response_t data[BUFSIZE/sizeof(nameinfo_response_t) + 1] = {};
248         size_t hl, sl;
249         nameinfo_response_t *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(nameinfo_response_t) + 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(nameinfo_response_t), host, hl);
269
270         if (serv)
271                 memcpy((uint8_t *)data + sizeof(nameinfo_response_t) + 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         res_response_t data[BUFSIZE/sizeof(res_response_t) + 1] = {};
278         res_response_t *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(res_response_t) + (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(res_response_t), 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_t *packet, size_t length) {
298         const rheader_t *req;
299         assert(out_fd >= 0);
300
301         req = &packet->rheader;
302         assert(req);
303         assert(length >= sizeof(rheader_t));
304         assert(length == req->length);
305
306         switch (req->type) {
307         case REQUEST_ADDRINFO: {
308                struct addrinfo ai = {}, *result = NULL;
309                const addrinfo_request_t *ai_req = &packet->addrinfo_request;
310                const char *node, *service;
311                int ret;
312
313                assert(length >= sizeof(addrinfo_request_t));
314                assert(length == sizeof(addrinfo_request_t) + 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(addrinfo_request_t) : NULL;
322                service = ai_req->service_len ? (const char*) ai_req + sizeof(addrinfo_request_t) + 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 nameinfo_request_t *ni_req = &packet->nameinfo_request;
335                char hostbuf[NI_MAXHOST], servbuf[NI_MAXSERV];
336                struct sockaddr_storage sa;
337
338                assert(length >= sizeof(nameinfo_request_t));
339                assert(length == sizeof(nameinfo_request_t) + ni_req->sockaddr_len);
340
341                memcpy(&sa, (const uint8_t *) ni_req + sizeof(nameinfo_request_t), 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 res_request_t *res_req = &packet->res_request;
359                  const char *dname;
360
361                  assert(length >= sizeof(res_request_t));
362                  assert(length == sizeof(res_request_t) + res_req->dname_len);
363
364                  dname = (const char *) req + sizeof(res_request_t);
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         asyncns_t *asyncns = 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 (!asyncns->dead) {
394                 packet_t buf[BUFSIZE/sizeof(packet_t) + 1];
395                 ssize_t length;
396
397                 length = recv(asyncns->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 (asyncns->dead)
406                         break;
407
408                 if (handle_request(asyncns->fds[RESPONSE_SEND_FD], buf, (size_t) length) < 0)
409                         break;
410         }
411
412         send_died(asyncns->fds[RESPONSE_SEND_FD]);
413
414         return NULL;
415 }
416
417 asyncns_t* asyncns_new(unsigned n_proc) {
418         int i;
419         asyncns_t *asyncns = NULL;
420
421         assert(n_proc >= 1);
422
423         if (n_proc > MAX_WORKERS)
424                 n_proc = MAX_WORKERS;
425
426         asyncns = malloc(sizeof(asyncns_t));
427         if (!asyncns) {
428                 errno = ENOMEM;
429                 goto fail;
430         }
431
432         asyncns->dead = 0;
433         asyncns->valid_workers = 0;
434
435         for (i = 0; i < MESSAGE_FD_MAX; i++)
436                 asyncns->fds[i] = -1;
437
438         memset(asyncns->queries, 0, sizeof(asyncns->queries));
439
440 #ifdef SOCK_CLOEXEC
441         if (socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, asyncns->fds) < 0 ||
442                         socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, asyncns->fds+2) < 0) {
443
444                 /* Try again, without SOCK_CLOEXEC */
445                 if (errno == EINVAL) {
446 #endif
447                         if (socketpair(PF_UNIX, SOCK_DGRAM, 0, asyncns->fds) < 0 ||
448                                         socketpair(PF_UNIX, SOCK_DGRAM, 0, asyncns->fds+2) < 0)
449                                 goto fail;
450 #ifdef SOCK_CLOEXEC
451                 } else
452                         goto fail;
453         }
454 #endif
455
456         for (i = 0; i < MESSAGE_FD_MAX; i++)
457                 fd_cloexec(asyncns->fds[i], true);
458
459         for (asyncns->valid_workers = 0; asyncns->valid_workers < n_proc; asyncns->valid_workers++) {
460                 int r;
461                 r = pthread_create(&asyncns->workers[asyncns->valid_workers], NULL, thread_worker, asyncns);
462                 if (r) {
463                         errno = r;
464                         goto fail;
465                 }
466         }
467
468         asyncns->current_index = asyncns->current_id = 0;
469         asyncns->done_head = asyncns->done_tail = NULL;
470         asyncns->n_queries = 0;
471
472         fd_nonblock(asyncns->fds[RESPONSE_RECV_FD], true);
473
474         return asyncns;
475
476 fail:
477         if (asyncns)
478                 asyncns_free(asyncns);
479
480         return NULL;
481 }
482
483 void asyncns_free(asyncns_t *asyncns) {
484         int i;
485         int saved_errno = errno;
486         unsigned p;
487
488         assert(asyncns);
489
490         asyncns->dead = 1;
491
492         if (asyncns->fds[REQUEST_SEND_FD] >= 0) {
493                 rheader_t req = {};
494
495                 req.type = REQUEST_TERMINATE;
496                 req.length = sizeof(req);
497                 req.id = 0;
498
499                 /* Send one termination packet for each worker */
500                 for (p = 0; p < asyncns->valid_workers; p++)
501                         send(asyncns->fds[REQUEST_SEND_FD], &req, req.length, MSG_NOSIGNAL);
502         }
503
504         /* Now terminate them and wait until they are gone. */
505         for (p = 0; p < asyncns->valid_workers; p++) {
506                 for (;;) {
507                         if (pthread_join(asyncns->workers[p], NULL) != EINTR)
508                                 break;
509                 }
510         }
511
512         /* Close all communication channels */
513         for (i = 0; i < MESSAGE_FD_MAX; i++)
514                 if (asyncns->fds[i] >= 0)
515                         close(asyncns->fds[i]);
516
517         for (p = 0; p < MAX_QUERIES; p++)
518                 if (asyncns->queries[p])
519                         asyncns_cancel(asyncns, asyncns->queries[p]);
520
521         free(asyncns);
522
523         errno = saved_errno;
524 }
525
526 int asyncns_fd(asyncns_t *asyncns) {
527         assert(asyncns);
528
529         return asyncns->fds[RESPONSE_RECV_FD];
530 }
531
532 static asyncns_query_t *lookup_query(asyncns_t *asyncns, unsigned id) {
533         asyncns_query_t *q;
534         assert(asyncns);
535
536         q = asyncns->queries[id % MAX_QUERIES];
537         if (q)
538                 if (q->id == id)
539                         return q;
540
541         return NULL;
542 }
543
544 static void complete_query(asyncns_t *asyncns, asyncns_query_t *q) {
545         assert(asyncns);
546         assert(q);
547         assert(!q->done);
548
549         q->done = 1;
550
551         if ((q->done_prev = asyncns->done_tail))
552                 asyncns->done_tail->done_next = q;
553         else
554                 asyncns->done_head = q;
555
556         asyncns->done_tail = q;
557         q->done_next = NULL;
558 }
559
560 static const void *unserialize_addrinfo(const void *p, struct addrinfo **ret_ai, size_t *length) {
561         addrinfo_serialization_t s;
562         size_t l;
563         struct addrinfo *ai;
564         assert(p);
565         assert(ret_ai);
566         assert(length);
567
568         if (*length < sizeof(addrinfo_serialization_t))
569                 return NULL;
570
571         memcpy(&s, p, sizeof(s));
572
573         l = sizeof(addrinfo_serialization_t) + s.ai_addrlen + s.canonname_len;
574         if (*length < l)
575                 return NULL;
576
577         ai = malloc(sizeof(struct addrinfo));
578         if (!ai)
579                 goto fail;
580
581         ai->ai_addr = NULL;
582         ai->ai_canonname = NULL;
583         ai->ai_next = NULL;
584
585         if (s.ai_addrlen && !(ai->ai_addr = malloc(s.ai_addrlen)))
586                 goto fail;
587
588         if (s.canonname_len && !(ai->ai_canonname = malloc(s.canonname_len)))
589                 goto fail;
590
591         ai->ai_flags = s.ai_flags;
592         ai->ai_family = s.ai_family;
593         ai->ai_socktype = s.ai_socktype;
594         ai->ai_protocol = s.ai_protocol;
595         ai->ai_addrlen = s.ai_addrlen;
596
597         if (ai->ai_addr)
598                 memcpy(ai->ai_addr, (const uint8_t*) p + sizeof(addrinfo_serialization_t), s.ai_addrlen);
599
600         if (ai->ai_canonname)
601                 memcpy(ai->ai_canonname, (const uint8_t*) p + sizeof(addrinfo_serialization_t) + s.ai_addrlen, s.canonname_len);
602
603         *length -= l;
604         *ret_ai = ai;
605
606         return (const uint8_t*) p + l;
607
608
609 fail:
610         if (ai)
611                 asyncns_freeaddrinfo(ai);
612
613         return NULL;
614 }
615
616 static int handle_response(asyncns_t *asyncns, const packet_t *packet, size_t length) {
617         const rheader_t *resp;
618         asyncns_query_t *q;
619
620         assert(asyncns);
621
622         resp = &packet->rheader;
623         assert(resp);
624         assert(length >= sizeof(rheader_t));
625         assert(length == resp->length);
626
627         if (resp->type == RESPONSE_DIED) {
628                 asyncns->dead = 1;
629                 return 0;
630         }
631
632         q = lookup_query(asyncns, resp->id);
633         if (!q)
634                 return 0;
635
636         switch (resp->type) {
637         case RESPONSE_ADDRINFO: {
638                 const addrinfo_response_t *ai_resp = &packet->addrinfo_response;
639                 const void *p;
640                 size_t l;
641                 struct addrinfo *prev = NULL;
642
643                 assert(length >= sizeof(addrinfo_response_t));
644                 assert(q->type == REQUEST_ADDRINFO);
645
646                 q->ret = ai_resp->ret;
647                 q->_errno = ai_resp->_errno;
648                 q->_h_errno = ai_resp->_h_errno;
649                 l = length - sizeof(addrinfo_response_t);
650                 p = (const uint8_t*) resp + sizeof(addrinfo_response_t);
651
652                 while (l > 0 && p) {
653                         struct addrinfo *ai = NULL;
654                         p = unserialize_addrinfo(p, &ai, &l);
655
656                         if (!p || !ai) {
657                                 q->ret = EAI_MEMORY;
658                                 break;
659                         }
660
661                         if (prev)
662                                 prev->ai_next = ai;
663                         else
664                                 q->addrinfo = ai;
665
666                         prev = ai;
667                 }
668
669                 complete_query(asyncns, q);
670                 break;
671         }
672
673         case RESPONSE_NAMEINFO: {
674                 const nameinfo_response_t *ni_resp = &packet->nameinfo_response;
675
676                 assert(length >= sizeof(nameinfo_response_t));
677                 assert(q->type == REQUEST_NAMEINFO);
678
679                 q->ret = ni_resp->ret;
680                 q->_errno = ni_resp->_errno;
681                 q->_h_errno = ni_resp->_h_errno;
682
683                 if (ni_resp->hostlen)
684                         if (!(q->host = strndup((const char*) ni_resp + sizeof(nameinfo_response_t), ni_resp->hostlen-1)))
685                                 q->ret = EAI_MEMORY;
686
687                 if (ni_resp->servlen)
688                         if (!(q->serv = strndup((const char*) ni_resp + sizeof(nameinfo_response_t) + ni_resp->hostlen, ni_resp->servlen-1)))
689                                 q->ret = EAI_MEMORY;
690
691                 complete_query(asyncns, q);
692                 break;
693         }
694
695         case RESPONSE_RES: {
696                 const res_response_t *res_resp = &packet->res_response;
697
698                 assert(length >= sizeof(res_response_t));
699                 assert(q->type == REQUEST_RES_QUERY || q->type == REQUEST_RES_SEARCH);
700
701                 q->ret = res_resp->ret;
702                 q->_errno = res_resp->_errno;
703                 q->_h_errno = res_resp->_h_errno;
704
705                 if (res_resp->ret >= 0)  {
706                         if (!(q->serv = malloc(res_resp->ret))) {
707                                 q->ret = -1;
708                                 q->_errno = ENOMEM;
709                         } else
710                                 memcpy(q->serv, (const char *)resp + sizeof(res_response_t), res_resp->ret);
711                 }
712
713                 complete_query(asyncns, q);
714                 break;
715         }
716
717         default:
718                 ;
719         }
720
721         return 0;
722 }
723
724 int asyncns_wait(asyncns_t *asyncns, int block) {
725         int handled = 0;
726         assert(asyncns);
727
728         for (;;) {
729                 packet_t buf[BUFSIZE/sizeof(packet_t) + 1];
730                 ssize_t l;
731
732                 if (asyncns->dead) {
733                         errno = ECHILD;
734                         return -1;
735                 }
736
737                 l = recv(asyncns->fds[RESPONSE_RECV_FD], buf, sizeof(buf), 0);
738                 if (l < 0) {
739                         fd_set fds;
740
741                         if (errno != EAGAIN)
742                                 return -1;
743
744                         if (!block || handled)
745                                 return 0;
746
747                         FD_ZERO(&fds);
748                         FD_SET(asyncns->fds[RESPONSE_RECV_FD], &fds);
749
750                         if (select(asyncns->fds[RESPONSE_RECV_FD]+1, &fds, NULL, NULL, NULL) < 0)
751                                 return -1;
752
753                         continue;
754                 }
755
756                 if (handle_response(asyncns, buf, (size_t) l) < 0)
757                         return -1;
758
759                 handled = 1;
760         }
761 }
762
763 static asyncns_query_t *alloc_query(asyncns_t *asyncns) {
764         asyncns_query_t *q;
765         assert(asyncns);
766
767         if (asyncns->n_queries >= MAX_QUERIES) {
768                 errno = ENOMEM;
769                 return NULL;
770         }
771
772         while (asyncns->queries[asyncns->current_index]) {
773                 asyncns->current_index++;
774                 asyncns->current_id++;
775
776                 while (asyncns->current_index >= MAX_QUERIES)
777                         asyncns->current_index -= MAX_QUERIES;
778         }
779
780         q = asyncns->queries[asyncns->current_index] = malloc(sizeof(asyncns_query_t));
781         if (!q) {
782                 errno = ENOMEM;
783                 return NULL;
784         }
785
786         asyncns->n_queries++;
787
788         q->asyncns = asyncns;
789         q->done = 0;
790         q->id = asyncns->current_id;
791         q->done_next = q->done_prev = NULL;
792         q->ret = 0;
793         q->_errno = 0;
794         q->_h_errno = 0;
795         q->addrinfo = NULL;
796         q->userdata = NULL;
797         q->host = q->serv = NULL;
798
799         return q;
800 }
801
802 asyncns_query_t* asyncns_getaddrinfo(asyncns_t *asyncns, const char *node, const char *service, const struct addrinfo *hints) {
803         addrinfo_request_t data[BUFSIZE/sizeof(addrinfo_request_t) + 1] = {};
804         addrinfo_request_t *req = data;
805         asyncns_query_t *q;
806         assert(asyncns);
807         assert(node || service);
808
809         if (asyncns->dead) {
810                 errno = ECHILD;
811                 return NULL;
812         }
813
814         q = alloc_query(asyncns);
815         if (!q)
816                 return NULL;
817
818         req->node_len = node ? strlen(node)+1 : 0;
819         req->service_len = service ? strlen(service)+1 : 0;
820
821         req->header.id = q->id;
822         req->header.type = q->type = REQUEST_ADDRINFO;
823         req->header.length = sizeof(addrinfo_request_t) + req->node_len + req->service_len;
824
825         if (req->header.length > BUFSIZE) {
826                 errno = ENOMEM;
827                 goto fail;
828         }
829
830         if (!(req->hints_is_null = !hints)) {
831                 req->ai_flags = hints->ai_flags;
832                 req->ai_family = hints->ai_family;
833                 req->ai_socktype = hints->ai_socktype;
834                 req->ai_protocol = hints->ai_protocol;
835         }
836
837         if (node)
838                 strcpy((char*) req + sizeof(addrinfo_request_t), node);
839
840         if (service)
841                 strcpy((char*) req + sizeof(addrinfo_request_t) + req->node_len, service);
842
843         if (send(asyncns->fds[REQUEST_SEND_FD], req, req->header.length, MSG_NOSIGNAL) < 0)
844                 goto fail;
845
846         return q;
847
848 fail:
849         if (q)
850                 asyncns_cancel(asyncns, q);
851
852         return NULL;
853 }
854
855 int asyncns_getaddrinfo_done(asyncns_t *asyncns, asyncns_query_t* q, struct addrinfo **ret_res) {
856         int ret;
857         assert(asyncns);
858         assert(q);
859         assert(q->asyncns == asyncns);
860         assert(q->type == REQUEST_ADDRINFO);
861
862         if (asyncns->dead) {
863                 errno = ECHILD;
864                 return EAI_SYSTEM;
865         }
866
867         if (!q->done)
868                 return EAI_AGAIN;
869
870         *ret_res = q->addrinfo;
871         q->addrinfo = NULL;
872
873         ret = q->ret;
874
875         if (ret == EAI_SYSTEM)
876                 errno = q->_errno;
877
878         if (ret != 0)
879                 h_errno = q->_h_errno;
880
881         asyncns_cancel(asyncns, q);
882
883         return ret;
884 }
885
886 asyncns_query_t* asyncns_getnameinfo(asyncns_t *asyncns, const struct sockaddr *sa, socklen_t salen, int flags, int gethost, int getserv) {
887         nameinfo_request_t data[BUFSIZE/sizeof(nameinfo_request_t) + 1] = {};
888         nameinfo_request_t *req = data;
889         asyncns_query_t *q;
890
891         assert(asyncns);
892         assert(sa);
893         assert(salen > 0);
894
895         if (asyncns->dead) {
896                 errno = ECHILD;
897                 return NULL;
898         }
899
900         q = alloc_query(asyncns);
901         if (!q)
902                 return NULL;
903
904         req->header.id = q->id;
905         req->header.type = q->type = REQUEST_NAMEINFO;
906         req->header.length = sizeof(nameinfo_request_t) + salen;
907
908         if (req->header.length > BUFSIZE) {
909                 errno = ENOMEM;
910                 goto fail;
911         }
912
913         req->flags = flags;
914         req->sockaddr_len = salen;
915         req->gethost = gethost;
916         req->getserv = getserv;
917
918         memcpy((uint8_t*) req + sizeof(nameinfo_request_t), sa, salen);
919
920         if (send(asyncns->fds[REQUEST_SEND_FD], req, req->header.length, MSG_NOSIGNAL) < 0)
921                 goto fail;
922
923         return q;
924
925 fail:
926         if (q)
927                 asyncns_cancel(asyncns, q);
928
929         return NULL;
930 }
931
932 int asyncns_getnameinfo_done(asyncns_t *asyncns, asyncns_query_t* q, char *ret_host, size_t hostlen, char *ret_serv, size_t servlen) {
933         int ret;
934         assert(asyncns);
935         assert(q);
936         assert(q->asyncns == asyncns);
937         assert(q->type == REQUEST_NAMEINFO);
938         assert(!ret_host || hostlen);
939         assert(!ret_serv || servlen);
940
941         if (asyncns->dead) {
942                 errno = ECHILD;
943                 return EAI_SYSTEM;
944         }
945
946         if (!q->done)
947                 return EAI_AGAIN;
948
949         if (ret_host && q->host) {
950                 strncpy(ret_host, q->host, hostlen);
951                 ret_host[hostlen-1] = 0;
952         }
953
954         if (ret_serv && q->serv) {
955                 strncpy(ret_serv, q->serv, servlen);
956                 ret_serv[servlen-1] = 0;
957         }
958
959         ret = q->ret;
960
961         if (ret == EAI_SYSTEM)
962                 errno = q->_errno;
963
964         if (ret != 0)
965                 h_errno = q->_h_errno;
966
967         asyncns_cancel(asyncns, q);
968
969         return ret;
970 }
971
972 static asyncns_query_t * asyncns_res(asyncns_t *asyncns, query_type_t qtype, const char *dname, int class, int type) {
973         res_request_t data[BUFSIZE/sizeof(res_request_t) + 1];
974         res_request_t *req = data;
975         asyncns_query_t *q;
976
977         assert(asyncns);
978         assert(dname);
979
980         if (asyncns->dead) {
981                 errno = ECHILD;
982                 return NULL;
983         }
984
985         q = alloc_query(asyncns);
986         if (!q)
987                 return NULL;
988
989         req->dname_len = strlen(dname) + 1;
990
991         req->header.id = q->id;
992         req->header.type = q->type = qtype;
993         req->header.length = sizeof(res_request_t) + req->dname_len;
994
995         if (req->header.length > BUFSIZE) {
996                 errno = ENOMEM;
997                 goto fail;
998         }
999
1000         req->class = class;
1001         req->type = type;
1002
1003         strcpy((char*) req + sizeof(res_request_t), dname);
1004
1005         if (send(asyncns->fds[REQUEST_SEND_FD], req, req->header.length, MSG_NOSIGNAL) < 0)
1006                 goto fail;
1007
1008         return q;
1009
1010 fail:
1011         if (q)
1012                 asyncns_cancel(asyncns, q);
1013
1014         return NULL;
1015 }
1016
1017 asyncns_query_t* asyncns_res_query(asyncns_t *asyncns, const char *dname, int class, int type) {
1018         return asyncns_res(asyncns, REQUEST_RES_QUERY, dname, class, type);
1019 }
1020
1021 asyncns_query_t* asyncns_res_search(asyncns_t *asyncns, const char *dname, int class, int type) {
1022         return asyncns_res(asyncns, REQUEST_RES_SEARCH, dname, class, type);
1023 }
1024
1025 int asyncns_res_done(asyncns_t *asyncns, asyncns_query_t* q, unsigned char **answer) {
1026         int ret;
1027         assert(asyncns);
1028         assert(q);
1029         assert(q->asyncns == asyncns);
1030         assert(q->type == REQUEST_RES_QUERY || q->type == REQUEST_RES_SEARCH);
1031         assert(answer);
1032
1033         if (asyncns->dead) {
1034                 errno = ECHILD;
1035                 return -ECHILD;
1036         }
1037
1038         if (!q->done) {
1039                 errno = EAGAIN;
1040                 return -EAGAIN;
1041         }
1042
1043         *answer = (unsigned char *)q->serv;
1044         q->serv = NULL;
1045
1046         ret = q->ret;
1047
1048         if (ret < 0) {
1049                 errno = q->_errno;
1050                 h_errno = q->_h_errno;
1051         }
1052
1053         asyncns_cancel(asyncns, q);
1054
1055         return ret < 0 ? -errno : ret;
1056 }
1057
1058 asyncns_query_t* asyncns_getnext(asyncns_t *asyncns) {
1059         assert(asyncns);
1060         return asyncns->done_head;
1061 }
1062
1063 int asyncns_getnqueries(asyncns_t *asyncns) {
1064         assert(asyncns);
1065         return asyncns->n_queries;
1066 }
1067
1068 void asyncns_cancel(asyncns_t *asyncns, asyncns_query_t* q) {
1069         int i;
1070         int saved_errno = errno;
1071
1072         assert(asyncns);
1073         assert(q);
1074         assert(q->asyncns == asyncns);
1075         assert(asyncns->n_queries > 0);
1076
1077         if (q->done) {
1078
1079                 if (q->done_prev)
1080                         q->done_prev->done_next = q->done_next;
1081                 else
1082                         asyncns->done_head = q->done_next;
1083
1084                 if (q->done_next)
1085                         q->done_next->done_prev = q->done_prev;
1086                 else
1087                         asyncns->done_tail = q->done_prev;
1088         }
1089
1090         i = q->id % MAX_QUERIES;
1091         assert(asyncns->queries[i] == q);
1092         asyncns->queries[i] = NULL;
1093
1094         asyncns_freeaddrinfo(q->addrinfo);
1095         free(q->host);
1096         free(q->serv);
1097
1098         asyncns->n_queries--;
1099         free(q);
1100
1101         errno = saved_errno;
1102 }
1103
1104 void asyncns_freeaddrinfo(struct addrinfo *ai) {
1105         int saved_errno = errno;
1106
1107         while (ai) {
1108                 struct addrinfo *next = ai->ai_next;
1109
1110                 free(ai->ai_addr);
1111                 free(ai->ai_canonname);
1112                 free(ai);
1113
1114                 ai = next;
1115         }
1116
1117         errno = saved_errno;
1118 }
1119
1120 void asyncns_freeanswer(unsigned char *answer) {
1121         int saved_errno = errno;
1122
1123         if (!answer)
1124                 return;
1125
1126         /* Please note that this function is new in libasyncns 0.4. In
1127          * older versions you were supposed to free the answer directly
1128          * with free(). Hence, if this function is changed to do more than
1129          * just a simple free() this must be considered ABI/API breakage! */
1130
1131         free(answer);
1132
1133         errno = saved_errno;
1134 }
1135
1136 int asyncns_isdone(asyncns_t *asyncns, asyncns_query_t*q) {
1137         assert(asyncns);
1138         assert(q);
1139         assert(q->asyncns == asyncns);
1140
1141         return q->done;
1142 }
1143
1144 void asyncns_setuserdata(asyncns_t *asyncns, asyncns_query_t *q, void *userdata) {
1145         assert(q);
1146         assert(asyncns);
1147         assert(q->asyncns = asyncns);
1148
1149         q->userdata = userdata;
1150 }
1151
1152 void* asyncns_getuserdata(asyncns_t *asyncns, asyncns_query_t *q) {
1153         assert(q);
1154         assert(asyncns);
1155         assert(q->asyncns = asyncns);
1156
1157         return q->userdata;
1158 }