]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-resolv.c
README: list CONFIG_FHANDLE in main section
[thirdparty/systemd.git] / src / libsystemd / sd-resolv.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-resolv.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 sd_resolv {
72 int fds[MESSAGE_FD_MAX];
73
74 pthread_t workers[MAX_WORKERS];
75 unsigned valid_workers;
76
77 unsigned current_id, current_index;
78 sd_resolv_query_t* queries[MAX_QUERIES];
79
80 sd_resolv_query_t *done_head, *done_tail;
81
82 int n_queries;
83 int dead;
84 };
85
86 struct sd_resolv_query {
87 sd_resolv_t *resolv;
88 int done;
89 unsigned id;
90 query_type_t type;
91 sd_resolv_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 sd_resolv_t *resolv = 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 (!resolv->dead) {
394 packet_t buf[BUFSIZE/sizeof(packet_t) + 1];
395 ssize_t length;
396
397 length = recv(resolv->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 (resolv->dead)
406 break;
407
408 if (handle_request(resolv->fds[RESPONSE_SEND_FD], buf, (size_t) length) < 0)
409 break;
410 }
411
412 send_died(resolv->fds[RESPONSE_SEND_FD]);
413
414 return NULL;
415 }
416
417 sd_resolv_t* sd_resolv_new(unsigned n_proc) {
418 sd_resolv_t *resolv = NULL;
419 int i, r;
420
421 assert(n_proc >= 1);
422
423 if (n_proc > MAX_WORKERS)
424 n_proc = MAX_WORKERS;
425
426 resolv = malloc(sizeof(sd_resolv_t));
427 if (!resolv) {
428 errno = ENOMEM;
429 goto fail;
430 }
431
432 resolv->dead = 0;
433 resolv->valid_workers = 0;
434
435 for (i = 0; i < MESSAGE_FD_MAX; i++)
436 resolv->fds[i] = -1;
437
438 memset(resolv->queries, 0, sizeof(resolv->queries));
439
440 r = socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolv->fds);
441 if (r < 0)
442 goto fail;
443
444 r = socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolv->fds+2);
445 if (r < 0)
446 goto fail;
447
448 for (resolv->valid_workers = 0; resolv->valid_workers < n_proc; resolv->valid_workers++) {
449 r = pthread_create(&resolv->workers[resolv->valid_workers], NULL, thread_worker, resolv);
450 if (r) {
451 errno = r;
452 goto fail;
453 }
454 }
455
456 resolv->current_index = resolv->current_id = 0;
457 resolv->done_head = resolv->done_tail = NULL;
458 resolv->n_queries = 0;
459
460 fd_nonblock(resolv->fds[RESPONSE_RECV_FD], true);
461
462 return resolv;
463
464 fail:
465 if (resolv)
466 sd_resolv_free(resolv);
467
468 return NULL;
469 }
470
471 void sd_resolv_free(sd_resolv_t *resolv) {
472 int i;
473 int saved_errno = errno;
474 unsigned p;
475
476 assert(resolv);
477
478 resolv->dead = 1;
479
480 if (resolv->fds[REQUEST_SEND_FD] >= 0) {
481 rheader_t req = {};
482
483 req.type = REQUEST_TERMINATE;
484 req.length = sizeof(req);
485 req.id = 0;
486
487 /* Send one termination packet for each worker */
488 for (p = 0; p < resolv->valid_workers; p++)
489 send(resolv->fds[REQUEST_SEND_FD], &req, req.length, MSG_NOSIGNAL);
490 }
491
492 /* Now terminate them and wait until they are gone. */
493 for (p = 0; p < resolv->valid_workers; p++) {
494 for (;;) {
495 if (pthread_join(resolv->workers[p], NULL) != EINTR)
496 break;
497 }
498 }
499
500 /* Close all communication channels */
501 for (i = 0; i < MESSAGE_FD_MAX; i++)
502 if (resolv->fds[i] >= 0)
503 close(resolv->fds[i]);
504
505 for (p = 0; p < MAX_QUERIES; p++)
506 if (resolv->queries[p])
507 sd_resolv_cancel(resolv, resolv->queries[p]);
508
509 free(resolv);
510
511 errno = saved_errno;
512 }
513
514 int sd_resolv_fd(sd_resolv_t *resolv) {
515 assert(resolv);
516
517 return resolv->fds[RESPONSE_RECV_FD];
518 }
519
520 static sd_resolv_query_t *lookup_query(sd_resolv_t *resolv, unsigned id) {
521 sd_resolv_query_t *q;
522 assert(resolv);
523
524 q = resolv->queries[id % MAX_QUERIES];
525 if (q)
526 if (q->id == id)
527 return q;
528
529 return NULL;
530 }
531
532 static void complete_query(sd_resolv_t *resolv, sd_resolv_query_t *q) {
533 assert(resolv);
534 assert(q);
535 assert(!q->done);
536
537 q->done = 1;
538
539 if ((q->done_prev = resolv->done_tail))
540 resolv->done_tail->done_next = q;
541 else
542 resolv->done_head = q;
543
544 resolv->done_tail = q;
545 q->done_next = NULL;
546 }
547
548 static const void *unserialize_addrinfo(const void *p, struct addrinfo **ret_ai, size_t *length) {
549 addrinfo_serialization_t s;
550 size_t l;
551 struct addrinfo *ai;
552 assert(p);
553 assert(ret_ai);
554 assert(length);
555
556 if (*length < sizeof(addrinfo_serialization_t))
557 return NULL;
558
559 memcpy(&s, p, sizeof(s));
560
561 l = sizeof(addrinfo_serialization_t) + s.ai_addrlen + s.canonname_len;
562 if (*length < l)
563 return NULL;
564
565 ai = malloc(sizeof(struct addrinfo));
566 if (!ai)
567 goto fail;
568
569 ai->ai_addr = NULL;
570 ai->ai_canonname = NULL;
571 ai->ai_next = NULL;
572
573 if (s.ai_addrlen && !(ai->ai_addr = malloc(s.ai_addrlen)))
574 goto fail;
575
576 if (s.canonname_len && !(ai->ai_canonname = malloc(s.canonname_len)))
577 goto fail;
578
579 ai->ai_flags = s.ai_flags;
580 ai->ai_family = s.ai_family;
581 ai->ai_socktype = s.ai_socktype;
582 ai->ai_protocol = s.ai_protocol;
583 ai->ai_addrlen = s.ai_addrlen;
584
585 if (ai->ai_addr)
586 memcpy(ai->ai_addr, (const uint8_t*) p + sizeof(addrinfo_serialization_t), s.ai_addrlen);
587
588 if (ai->ai_canonname)
589 memcpy(ai->ai_canonname, (const uint8_t*) p + sizeof(addrinfo_serialization_t) + s.ai_addrlen, s.canonname_len);
590
591 *length -= l;
592 *ret_ai = ai;
593
594 return (const uint8_t*) p + l;
595
596
597 fail:
598 if (ai)
599 sd_resolv_freeaddrinfo(ai);
600
601 return NULL;
602 }
603
604 static int handle_response(sd_resolv_t *resolv, const packet_t *packet, size_t length) {
605 const rheader_t *resp;
606 sd_resolv_query_t *q;
607
608 assert(resolv);
609
610 resp = &packet->rheader;
611 assert(resp);
612 assert(length >= sizeof(rheader_t));
613 assert(length == resp->length);
614
615 if (resp->type == RESPONSE_DIED) {
616 resolv->dead = 1;
617 return 0;
618 }
619
620 q = lookup_query(resolv, resp->id);
621 if (!q)
622 return 0;
623
624 switch (resp->type) {
625 case RESPONSE_ADDRINFO: {
626 const addrinfo_response_t *ai_resp = &packet->addrinfo_response;
627 const void *p;
628 size_t l;
629 struct addrinfo *prev = NULL;
630
631 assert(length >= sizeof(addrinfo_response_t));
632 assert(q->type == REQUEST_ADDRINFO);
633
634 q->ret = ai_resp->ret;
635 q->_errno = ai_resp->_errno;
636 q->_h_errno = ai_resp->_h_errno;
637 l = length - sizeof(addrinfo_response_t);
638 p = (const uint8_t*) resp + sizeof(addrinfo_response_t);
639
640 while (l > 0 && p) {
641 struct addrinfo *ai = NULL;
642 p = unserialize_addrinfo(p, &ai, &l);
643
644 if (!p || !ai) {
645 q->ret = EAI_MEMORY;
646 break;
647 }
648
649 if (prev)
650 prev->ai_next = ai;
651 else
652 q->addrinfo = ai;
653
654 prev = ai;
655 }
656
657 complete_query(resolv, q);
658 break;
659 }
660
661 case RESPONSE_NAMEINFO: {
662 const nameinfo_response_t *ni_resp = &packet->nameinfo_response;
663
664 assert(length >= sizeof(nameinfo_response_t));
665 assert(q->type == REQUEST_NAMEINFO);
666
667 q->ret = ni_resp->ret;
668 q->_errno = ni_resp->_errno;
669 q->_h_errno = ni_resp->_h_errno;
670
671 if (ni_resp->hostlen)
672 if (!(q->host = strndup((const char*) ni_resp + sizeof(nameinfo_response_t), ni_resp->hostlen-1)))
673 q->ret = EAI_MEMORY;
674
675 if (ni_resp->servlen)
676 if (!(q->serv = strndup((const char*) ni_resp + sizeof(nameinfo_response_t) + ni_resp->hostlen, ni_resp->servlen-1)))
677 q->ret = EAI_MEMORY;
678
679 complete_query(resolv, q);
680 break;
681 }
682
683 case RESPONSE_RES: {
684 const res_response_t *res_resp = &packet->res_response;
685
686 assert(length >= sizeof(res_response_t));
687 assert(q->type == REQUEST_RES_QUERY || q->type == REQUEST_RES_SEARCH);
688
689 q->ret = res_resp->ret;
690 q->_errno = res_resp->_errno;
691 q->_h_errno = res_resp->_h_errno;
692
693 if (res_resp->ret >= 0) {
694 if (!(q->serv = malloc(res_resp->ret))) {
695 q->ret = -1;
696 q->_errno = ENOMEM;
697 } else
698 memcpy(q->serv, (const char *)resp + sizeof(res_response_t), res_resp->ret);
699 }
700
701 complete_query(resolv, q);
702 break;
703 }
704
705 default:
706 ;
707 }
708
709 return 0;
710 }
711
712 int sd_resolv_wait(sd_resolv_t *resolv, int block) {
713 int handled = 0;
714 assert(resolv);
715
716 for (;;) {
717 packet_t buf[BUFSIZE/sizeof(packet_t) + 1];
718 ssize_t l;
719
720 if (resolv->dead) {
721 errno = ECHILD;
722 return -1;
723 }
724
725 l = recv(resolv->fds[RESPONSE_RECV_FD], buf, sizeof(buf), 0);
726 if (l < 0) {
727 fd_set fds;
728
729 if (errno != EAGAIN)
730 return -1;
731
732 if (!block || handled)
733 return 0;
734
735 FD_ZERO(&fds);
736 FD_SET(resolv->fds[RESPONSE_RECV_FD], &fds);
737
738 if (select(resolv->fds[RESPONSE_RECV_FD]+1, &fds, NULL, NULL, NULL) < 0)
739 return -1;
740
741 continue;
742 }
743
744 if (handle_response(resolv, buf, (size_t) l) < 0)
745 return -1;
746
747 handled = 1;
748 }
749 }
750
751 static sd_resolv_query_t *alloc_query(sd_resolv_t *resolv) {
752 sd_resolv_query_t *q;
753 assert(resolv);
754
755 if (resolv->n_queries >= MAX_QUERIES) {
756 errno = ENOMEM;
757 return NULL;
758 }
759
760 while (resolv->queries[resolv->current_index]) {
761 resolv->current_index++;
762 resolv->current_id++;
763
764 while (resolv->current_index >= MAX_QUERIES)
765 resolv->current_index -= MAX_QUERIES;
766 }
767
768 q = resolv->queries[resolv->current_index] = malloc(sizeof(sd_resolv_query_t));
769 if (!q) {
770 errno = ENOMEM;
771 return NULL;
772 }
773
774 resolv->n_queries++;
775
776 q->resolv = resolv;
777 q->done = 0;
778 q->id = resolv->current_id;
779 q->done_next = q->done_prev = NULL;
780 q->ret = 0;
781 q->_errno = 0;
782 q->_h_errno = 0;
783 q->addrinfo = NULL;
784 q->userdata = NULL;
785 q->host = q->serv = NULL;
786
787 return q;
788 }
789
790 sd_resolv_query_t* sd_resolv_getaddrinfo(sd_resolv_t *resolv, const char *node, const char *service, const struct addrinfo *hints) {
791 addrinfo_request_t data[BUFSIZE/sizeof(addrinfo_request_t) + 1] = {};
792 addrinfo_request_t *req = data;
793 sd_resolv_query_t *q;
794 assert(resolv);
795 assert(node || service);
796
797 if (resolv->dead) {
798 errno = ECHILD;
799 return NULL;
800 }
801
802 q = alloc_query(resolv);
803 if (!q)
804 return NULL;
805
806 req->node_len = node ? strlen(node)+1 : 0;
807 req->service_len = service ? strlen(service)+1 : 0;
808
809 req->header.id = q->id;
810 req->header.type = q->type = REQUEST_ADDRINFO;
811 req->header.length = sizeof(addrinfo_request_t) + req->node_len + req->service_len;
812
813 if (req->header.length > BUFSIZE) {
814 errno = ENOMEM;
815 goto fail;
816 }
817
818 if (!(req->hints_is_null = !hints)) {
819 req->ai_flags = hints->ai_flags;
820 req->ai_family = hints->ai_family;
821 req->ai_socktype = hints->ai_socktype;
822 req->ai_protocol = hints->ai_protocol;
823 }
824
825 if (node)
826 strcpy((char*) req + sizeof(addrinfo_request_t), node);
827
828 if (service)
829 strcpy((char*) req + sizeof(addrinfo_request_t) + req->node_len, service);
830
831 if (send(resolv->fds[REQUEST_SEND_FD], req, req->header.length, MSG_NOSIGNAL) < 0)
832 goto fail;
833
834 return q;
835
836 fail:
837 if (q)
838 sd_resolv_cancel(resolv, q);
839
840 return NULL;
841 }
842
843 int sd_resolv_getaddrinfo_done(sd_resolv_t *resolv, sd_resolv_query_t* q, struct addrinfo **ret_res) {
844 int ret;
845 assert(resolv);
846 assert(q);
847 assert(q->resolv == resolv);
848 assert(q->type == REQUEST_ADDRINFO);
849
850 if (resolv->dead) {
851 errno = ECHILD;
852 return EAI_SYSTEM;
853 }
854
855 if (!q->done)
856 return EAI_AGAIN;
857
858 *ret_res = q->addrinfo;
859 q->addrinfo = NULL;
860
861 ret = q->ret;
862
863 if (ret == EAI_SYSTEM)
864 errno = q->_errno;
865
866 if (ret != 0)
867 h_errno = q->_h_errno;
868
869 sd_resolv_cancel(resolv, q);
870
871 return ret;
872 }
873
874 sd_resolv_query_t* sd_resolv_getnameinfo(sd_resolv_t *resolv, const struct sockaddr *sa, socklen_t salen, int flags, int gethost, int getserv) {
875 nameinfo_request_t data[BUFSIZE/sizeof(nameinfo_request_t) + 1] = {};
876 nameinfo_request_t *req = data;
877 sd_resolv_query_t *q;
878
879 assert(resolv);
880 assert(sa);
881 assert(salen > 0);
882
883 if (resolv->dead) {
884 errno = ECHILD;
885 return NULL;
886 }
887
888 q = alloc_query(resolv);
889 if (!q)
890 return NULL;
891
892 req->header.id = q->id;
893 req->header.type = q->type = REQUEST_NAMEINFO;
894 req->header.length = sizeof(nameinfo_request_t) + salen;
895
896 if (req->header.length > BUFSIZE) {
897 errno = ENOMEM;
898 goto fail;
899 }
900
901 req->flags = flags;
902 req->sockaddr_len = salen;
903 req->gethost = gethost;
904 req->getserv = getserv;
905
906 memcpy((uint8_t*) req + sizeof(nameinfo_request_t), sa, salen);
907
908 if (send(resolv->fds[REQUEST_SEND_FD], req, req->header.length, MSG_NOSIGNAL) < 0)
909 goto fail;
910
911 return q;
912
913 fail:
914 if (q)
915 sd_resolv_cancel(resolv, q);
916
917 return NULL;
918 }
919
920 int sd_resolv_getnameinfo_done(sd_resolv_t *resolv, sd_resolv_query_t* q, char *ret_host, size_t hostlen, char *ret_serv, size_t servlen) {
921 int ret;
922 assert(resolv);
923 assert(q);
924 assert(q->resolv == resolv);
925 assert(q->type == REQUEST_NAMEINFO);
926 assert(!ret_host || hostlen);
927 assert(!ret_serv || servlen);
928
929 if (resolv->dead) {
930 errno = ECHILD;
931 return EAI_SYSTEM;
932 }
933
934 if (!q->done)
935 return EAI_AGAIN;
936
937 if (ret_host && q->host) {
938 strncpy(ret_host, q->host, hostlen);
939 ret_host[hostlen-1] = 0;
940 }
941
942 if (ret_serv && q->serv) {
943 strncpy(ret_serv, q->serv, servlen);
944 ret_serv[servlen-1] = 0;
945 }
946
947 ret = q->ret;
948
949 if (ret == EAI_SYSTEM)
950 errno = q->_errno;
951
952 if (ret != 0)
953 h_errno = q->_h_errno;
954
955 sd_resolv_cancel(resolv, q);
956
957 return ret;
958 }
959
960 static sd_resolv_query_t * resolv_res(sd_resolv_t *resolv, query_type_t qtype, const char *dname, int class, int type) {
961 res_request_t data[BUFSIZE/sizeof(res_request_t) + 1];
962 res_request_t *req = data;
963 sd_resolv_query_t *q;
964
965 assert(resolv);
966 assert(dname);
967
968 if (resolv->dead) {
969 errno = ECHILD;
970 return NULL;
971 }
972
973 q = alloc_query(resolv);
974 if (!q)
975 return NULL;
976
977 req->dname_len = strlen(dname) + 1;
978
979 req->header.id = q->id;
980 req->header.type = q->type = qtype;
981 req->header.length = sizeof(res_request_t) + req->dname_len;
982
983 if (req->header.length > BUFSIZE) {
984 errno = ENOMEM;
985 goto fail;
986 }
987
988 req->class = class;
989 req->type = type;
990
991 strcpy((char*) req + sizeof(res_request_t), dname);
992
993 if (send(resolv->fds[REQUEST_SEND_FD], req, req->header.length, MSG_NOSIGNAL) < 0)
994 goto fail;
995
996 return q;
997
998 fail:
999 if (q)
1000 sd_resolv_cancel(resolv, q);
1001
1002 return NULL;
1003 }
1004
1005 sd_resolv_query_t* sd_resolv_res_query(sd_resolv_t *resolv, const char *dname, int class, int type) {
1006 return resolv_res(resolv, REQUEST_RES_QUERY, dname, class, type);
1007 }
1008
1009 sd_resolv_query_t* sd_resolv_res_search(sd_resolv_t *resolv, const char *dname, int class, int type) {
1010 return resolv_res(resolv, REQUEST_RES_SEARCH, dname, class, type);
1011 }
1012
1013 int sd_resolv_res_done(sd_resolv_t *resolv, sd_resolv_query_t* q, unsigned char **answer) {
1014 int ret;
1015 assert(resolv);
1016 assert(q);
1017 assert(q->resolv == resolv);
1018 assert(q->type == REQUEST_RES_QUERY || q->type == REQUEST_RES_SEARCH);
1019 assert(answer);
1020
1021 if (resolv->dead) {
1022 errno = ECHILD;
1023 return -ECHILD;
1024 }
1025
1026 if (!q->done) {
1027 errno = EAGAIN;
1028 return -EAGAIN;
1029 }
1030
1031 *answer = (unsigned char *)q->serv;
1032 q->serv = NULL;
1033
1034 ret = q->ret;
1035
1036 if (ret < 0) {
1037 errno = q->_errno;
1038 h_errno = q->_h_errno;
1039 }
1040
1041 sd_resolv_cancel(resolv, q);
1042
1043 return ret < 0 ? -errno : ret;
1044 }
1045
1046 sd_resolv_query_t* sd_resolv_getnext(sd_resolv_t *resolv) {
1047 assert(resolv);
1048 return resolv->done_head;
1049 }
1050
1051 int sd_resolv_getnqueries(sd_resolv_t *resolv) {
1052 assert(resolv);
1053 return resolv->n_queries;
1054 }
1055
1056 void sd_resolv_cancel(sd_resolv_t *resolv, sd_resolv_query_t* q) {
1057 int i;
1058 int saved_errno = errno;
1059
1060 assert(resolv);
1061 assert(q);
1062 assert(q->resolv == resolv);
1063 assert(resolv->n_queries > 0);
1064
1065 if (q->done) {
1066
1067 if (q->done_prev)
1068 q->done_prev->done_next = q->done_next;
1069 else
1070 resolv->done_head = q->done_next;
1071
1072 if (q->done_next)
1073 q->done_next->done_prev = q->done_prev;
1074 else
1075 resolv->done_tail = q->done_prev;
1076 }
1077
1078 i = q->id % MAX_QUERIES;
1079 assert(resolv->queries[i] == q);
1080 resolv->queries[i] = NULL;
1081
1082 sd_resolv_freeaddrinfo(q->addrinfo);
1083 free(q->host);
1084 free(q->serv);
1085
1086 resolv->n_queries--;
1087 free(q);
1088
1089 errno = saved_errno;
1090 }
1091
1092 void sd_resolv_freeaddrinfo(struct addrinfo *ai) {
1093 int saved_errno = errno;
1094
1095 while (ai) {
1096 struct addrinfo *next = ai->ai_next;
1097
1098 free(ai->ai_addr);
1099 free(ai->ai_canonname);
1100 free(ai);
1101
1102 ai = next;
1103 }
1104
1105 errno = saved_errno;
1106 }
1107
1108 void sd_resolv_freeanswer(unsigned char *answer) {
1109 int saved_errno = errno;
1110
1111 if (!answer)
1112 return;
1113
1114 free(answer);
1115
1116 errno = saved_errno;
1117 }
1118
1119 int sd_resolv_isdone(sd_resolv_t *resolv, sd_resolv_query_t*q) {
1120 assert(resolv);
1121 assert(q);
1122 assert(q->resolv == resolv);
1123
1124 return q->done;
1125 }
1126
1127 void sd_resolv_setuserdata(sd_resolv_t *resolv, sd_resolv_query_t *q, void *userdata) {
1128 assert(q);
1129 assert(resolv);
1130 assert(q->resolv = resolv);
1131
1132 q->userdata = userdata;
1133 }
1134
1135 void* sd_resolv_getuserdata(sd_resolv_t *resolv, sd_resolv_query_t *q) {
1136 assert(q);
1137 assert(resolv);
1138 assert(q->resolv = resolv);
1139
1140 return q->userdata;
1141 }