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