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