1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2005-2008 Lennart Poettering
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.
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.
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/>.
26 #include <sys/select.h>
32 #include <sys/types.h>
34 #include <netinet/in.h>
35 #include <arpa/nameser.h>
39 #include <sys/resource.h>
42 #include <sys/prctl.h>
44 #include "sd-resolv.h"
47 #define MAX_WORKERS 16
48 #define MAX_QUERIES 256
49 #define BUFSIZE (10240)
72 int fds
[MESSAGE_FD_MAX
];
74 pthread_t workers
[MAX_WORKERS
];
75 unsigned valid_workers
;
77 unsigned current_id
, current_index
;
78 sd_resolv_query_t
* queries
[MAX_QUERIES
];
80 sd_resolv_query_t
*done_head
, *done_tail
;
86 struct sd_resolv_query
{
91 sd_resolv_query_t
*done_next
, *done_prev
;
95 struct addrinfo
*addrinfo
;
100 typedef struct rheader
{
106 typedef struct addrinfo_request
{
107 struct rheader header
;
113 size_t node_len
, service_len
;
114 } addrinfo_request_t
;
116 typedef struct addrinfo_response
{
117 struct rheader header
;
121 /* followed by addrinfo_serialization[] */
122 } addrinfo_response_t
;
124 typedef struct addrinfo_serialization
{
130 size_t canonname_len
;
131 /* Followed by ai_addr amd ai_canonname with variable lengths */
132 } addrinfo_serialization_t
;
134 typedef struct nameinfo_request
{
135 struct rheader header
;
137 socklen_t sockaddr_len
;
138 int gethost
, getserv
;
139 } nameinfo_request_t
;
141 typedef struct nameinfo_response
{
142 struct rheader header
;
143 size_t hostlen
, servlen
;
147 } nameinfo_response_t
;
149 typedef struct res_request
{
150 struct rheader header
;
156 typedef struct res_response
{
157 struct rheader header
;
163 typedef union packet
{
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
;
173 static int send_died(int out_fd
) {
177 rh
.type
= RESPONSE_DIED
;
179 rh
.length
= sizeof(rh
);
181 return send(out_fd
, &rh
, rh
.length
, MSG_NOSIGNAL
);
184 static void *serialize_addrinfo(void *p
, const struct addrinfo
*ai
, size_t *length
, size_t maxlength
) {
185 addrinfo_serialization_t s
;
190 assert(*length
<= maxlength
);
192 cnl
= (ai
->ai_canonname
? strlen(ai
->ai_canonname
)+1 : 0);
193 l
= sizeof(addrinfo_serialization_t
) + ai
->ai_addrlen
+ cnl
;
195 if (*length
+ l
> maxlength
)
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
;
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
);
208 if (ai
->ai_canonname
)
209 strcpy((char*) p
+ sizeof(addrinfo_serialization_t
) + ai
->ai_addrlen
, ai
->ai_canonname
);
212 return (uint8_t*) p
+ l
;
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
;
220 resp
->header
.type
= RESPONSE_ADDRINFO
;
221 resp
->header
.id
= id
;
222 resp
->header
.length
= sizeof(addrinfo_response_t
);
224 resp
->_errno
= _errno
;
225 resp
->_h_errno
= _h_errno
;
227 if (ret
== 0 && ai
) {
231 for (k
= ai
; k
; k
= k
->ai_next
) {
232 p
= serialize_addrinfo(p
, k
, &resp
->header
.length
, (char*) data
+ BUFSIZE
- (char*) p
);
234 resp
->ret
= EAI_MEMORY
;
243 return send(out_fd
, resp
, resp
->header
.length
, MSG_NOSIGNAL
);
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] = {};
249 nameinfo_response_t
*resp
= data
;
253 sl
= serv
? strlen(serv
)+1 : 0;
254 hl
= host
? strlen(host
)+1 : 0;
256 resp
->header
.type
= RESPONSE_NAMEINFO
;
257 resp
->header
.id
= id
;
258 resp
->header
.length
= sizeof(nameinfo_response_t
) + hl
+ sl
;
260 resp
->_errno
= _errno
;
261 resp
->_h_errno
= _h_errno
;
265 assert(sizeof(data
) >= resp
->header
.length
);
268 memcpy((uint8_t *)data
+ sizeof(nameinfo_response_t
), host
, hl
);
271 memcpy((uint8_t *)data
+ sizeof(nameinfo_response_t
) + hl
, serv
, sl
);
273 return send(out_fd
, resp
, resp
->header
.length
, MSG_NOSIGNAL
);
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
;
282 resp
->header
.type
= RESPONSE_RES
;
283 resp
->header
.id
= id
;
284 resp
->header
.length
= sizeof(res_response_t
) + (ret
< 0 ? 0 : ret
);
286 resp
->_errno
= _errno
;
287 resp
->_h_errno
= _h_errno
;
289 assert(sizeof(data
) >= resp
->header
.length
);
292 memcpy((uint8_t *)data
+ sizeof(res_response_t
), answer
, ret
);
294 return send(out_fd
, resp
, resp
->header
.length
, MSG_NOSIGNAL
);
297 static int handle_request(int out_fd
, const packet_t
*packet
, size_t length
) {
298 const rheader_t
*req
;
301 req
= &packet
->rheader
;
303 assert(length
>= sizeof(rheader_t
));
304 assert(length
== req
->length
);
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
;
313 assert(length
>= sizeof(addrinfo_request_t
));
314 assert(length
== sizeof(addrinfo_request_t
) + ai_req
->node_len
+ ai_req
->service_len
);
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
;
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
;
324 ret
= getaddrinfo(node
, service
,
325 ai_req
->hints_is_null
? NULL
: &ai
,
328 /* send_addrinfo_reply() frees result */
329 return send_addrinfo_reply(out_fd
, req
->id
, ret
, result
, errno
, h_errno
);
332 case REQUEST_NAMEINFO
: {
334 const nameinfo_request_t
*ni_req
= &packet
->nameinfo_request
;
335 char hostbuf
[NI_MAXHOST
], servbuf
[NI_MAXSERV
];
336 struct sockaddr_storage sa
;
338 assert(length
>= sizeof(nameinfo_request_t
));
339 assert(length
== sizeof(nameinfo_request_t
) + ni_req
->sockaddr_len
);
341 memcpy(&sa
, (const uint8_t *) ni_req
+ sizeof(nameinfo_request_t
), ni_req
->sockaddr_len
);
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,
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
,
354 case REQUEST_RES_QUERY
:
355 case REQUEST_RES_SEARCH
: {
357 HEADER answer
[BUFSIZE
/sizeof(HEADER
) + 1];
358 const res_request_t
*res_req
= &packet
->res_request
;
361 assert(length
>= sizeof(res_request_t
));
362 assert(length
== sizeof(res_request_t
) + res_req
->dname_len
);
364 dname
= (const char *) req
+ sizeof(res_request_t
);
366 if (req
->type
== REQUEST_RES_QUERY
)
367 ret
= res_query(dname
, res_req
->class, res_req
->type
, (unsigned char *) answer
, BUFSIZE
);
369 ret
= res_search(dname
, res_req
->class, res_req
->type
, (unsigned char *) answer
, BUFSIZE
);
371 return send_res_reply(out_fd
, req
->id
, (unsigned char *) answer
, ret
, errno
, h_errno
);
374 case REQUEST_TERMINATE
:
385 static void* thread_worker(void *p
) {
386 sd_resolv_t
*resolv
= p
;
389 /* No signals in this thread please */
390 sigfillset(&fullset
);
391 pthread_sigmask(SIG_BLOCK
, &fullset
, NULL
);
393 while (!resolv
->dead
) {
394 packet_t buf
[BUFSIZE
/sizeof(packet_t
) + 1];
397 length
= recv(resolv
->fds
[REQUEST_RECV_FD
], buf
, sizeof(buf
), 0);
400 if (length
< 0 && (errno
== EAGAIN
|| errno
== EINTR
))
408 if (handle_request(resolv
->fds
[RESPONSE_SEND_FD
], buf
, (size_t) length
) < 0)
412 send_died(resolv
->fds
[RESPONSE_SEND_FD
]);
417 sd_resolv_t
* sd_resolv_new(unsigned n_proc
) {
418 sd_resolv_t
*resolv
= NULL
;
423 if (n_proc
> MAX_WORKERS
)
424 n_proc
= MAX_WORKERS
;
426 resolv
= malloc(sizeof(sd_resolv_t
));
433 resolv
->valid_workers
= 0;
435 for (i
= 0; i
< MESSAGE_FD_MAX
; i
++)
438 memset(resolv
->queries
, 0, sizeof(resolv
->queries
));
440 r
= socketpair(PF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0, resolv
->fds
);
444 r
= socketpair(PF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0, resolv
->fds
+2);
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
);
456 resolv
->current_index
= resolv
->current_id
= 0;
457 resolv
->done_head
= resolv
->done_tail
= NULL
;
458 resolv
->n_queries
= 0;
460 fd_nonblock(resolv
->fds
[RESPONSE_RECV_FD
], true);
466 sd_resolv_free(resolv
);
471 void sd_resolv_free(sd_resolv_t
*resolv
) {
473 int saved_errno
= errno
;
480 if (resolv
->fds
[REQUEST_SEND_FD
] >= 0) {
483 req
.type
= REQUEST_TERMINATE
;
484 req
.length
= sizeof(req
);
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
);
492 /* Now terminate them and wait until they are gone. */
493 for (p
= 0; p
< resolv
->valid_workers
; p
++) {
495 if (pthread_join(resolv
->workers
[p
], NULL
) != EINTR
)
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
]);
505 for (p
= 0; p
< MAX_QUERIES
; p
++)
506 if (resolv
->queries
[p
])
507 sd_resolv_cancel(resolv
, resolv
->queries
[p
]);
514 int sd_resolv_fd(sd_resolv_t
*resolv
) {
517 return resolv
->fds
[RESPONSE_RECV_FD
];
520 static sd_resolv_query_t
*lookup_query(sd_resolv_t
*resolv
, unsigned id
) {
521 sd_resolv_query_t
*q
;
524 q
= resolv
->queries
[id
% MAX_QUERIES
];
532 static void complete_query(sd_resolv_t
*resolv
, sd_resolv_query_t
*q
) {
539 if ((q
->done_prev
= resolv
->done_tail
))
540 resolv
->done_tail
->done_next
= q
;
542 resolv
->done_head
= q
;
544 resolv
->done_tail
= q
;
548 static const void *unserialize_addrinfo(const void *p
, struct addrinfo
**ret_ai
, size_t *length
) {
549 addrinfo_serialization_t s
;
556 if (*length
< sizeof(addrinfo_serialization_t
))
559 memcpy(&s
, p
, sizeof(s
));
561 l
= sizeof(addrinfo_serialization_t
) + s
.ai_addrlen
+ s
.canonname_len
;
565 ai
= malloc(sizeof(struct addrinfo
));
570 ai
->ai_canonname
= NULL
;
573 if (s
.ai_addrlen
&& !(ai
->ai_addr
= malloc(s
.ai_addrlen
)))
576 if (s
.canonname_len
&& !(ai
->ai_canonname
= malloc(s
.canonname_len
)))
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
;
586 memcpy(ai
->ai_addr
, (const uint8_t*) p
+ sizeof(addrinfo_serialization_t
), s
.ai_addrlen
);
588 if (ai
->ai_canonname
)
589 memcpy(ai
->ai_canonname
, (const uint8_t*) p
+ sizeof(addrinfo_serialization_t
) + s
.ai_addrlen
, s
.canonname_len
);
594 return (const uint8_t*) p
+ l
;
599 sd_resolv_freeaddrinfo(ai
);
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
;
610 resp
= &packet
->rheader
;
612 assert(length
>= sizeof(rheader_t
));
613 assert(length
== resp
->length
);
615 if (resp
->type
== RESPONSE_DIED
) {
620 q
= lookup_query(resolv
, resp
->id
);
624 switch (resp
->type
) {
625 case RESPONSE_ADDRINFO
: {
626 const addrinfo_response_t
*ai_resp
= &packet
->addrinfo_response
;
629 struct addrinfo
*prev
= NULL
;
631 assert(length
>= sizeof(addrinfo_response_t
));
632 assert(q
->type
== REQUEST_ADDRINFO
);
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
);
641 struct addrinfo
*ai
= NULL
;
642 p
= unserialize_addrinfo(p
, &ai
, &l
);
657 complete_query(resolv
, q
);
661 case RESPONSE_NAMEINFO
: {
662 const nameinfo_response_t
*ni_resp
= &packet
->nameinfo_response
;
664 assert(length
>= sizeof(nameinfo_response_t
));
665 assert(q
->type
== REQUEST_NAMEINFO
);
667 q
->ret
= ni_resp
->ret
;
668 q
->_errno
= ni_resp
->_errno
;
669 q
->_h_errno
= ni_resp
->_h_errno
;
671 if (ni_resp
->hostlen
)
672 if (!(q
->host
= strndup((const char*) ni_resp
+ sizeof(nameinfo_response_t
), ni_resp
->hostlen
-1)))
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)))
679 complete_query(resolv
, q
);
684 const res_response_t
*res_resp
= &packet
->res_response
;
686 assert(length
>= sizeof(res_response_t
));
687 assert(q
->type
== REQUEST_RES_QUERY
|| q
->type
== REQUEST_RES_SEARCH
);
689 q
->ret
= res_resp
->ret
;
690 q
->_errno
= res_resp
->_errno
;
691 q
->_h_errno
= res_resp
->_h_errno
;
693 if (res_resp
->ret
>= 0) {
694 if (!(q
->serv
= malloc(res_resp
->ret
))) {
698 memcpy(q
->serv
, (const char *)resp
+ sizeof(res_response_t
), res_resp
->ret
);
701 complete_query(resolv
, q
);
712 int sd_resolv_wait(sd_resolv_t
*resolv
, int block
) {
717 packet_t buf
[BUFSIZE
/sizeof(packet_t
) + 1];
725 l
= recv(resolv
->fds
[RESPONSE_RECV_FD
], buf
, sizeof(buf
), 0);
732 if (!block
|| handled
)
736 FD_SET(resolv
->fds
[RESPONSE_RECV_FD
], &fds
);
738 if (select(resolv
->fds
[RESPONSE_RECV_FD
]+1, &fds
, NULL
, NULL
, NULL
) < 0)
744 if (handle_response(resolv
, buf
, (size_t) l
) < 0)
751 static sd_resolv_query_t
*alloc_query(sd_resolv_t
*resolv
) {
752 sd_resolv_query_t
*q
;
755 if (resolv
->n_queries
>= MAX_QUERIES
) {
760 while (resolv
->queries
[resolv
->current_index
]) {
761 resolv
->current_index
++;
762 resolv
->current_id
++;
764 while (resolv
->current_index
>= MAX_QUERIES
)
765 resolv
->current_index
-= MAX_QUERIES
;
768 q
= resolv
->queries
[resolv
->current_index
] = malloc(sizeof(sd_resolv_query_t
));
778 q
->id
= resolv
->current_id
;
779 q
->done_next
= q
->done_prev
= NULL
;
785 q
->host
= q
->serv
= NULL
;
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
;
795 assert(node
|| service
);
802 q
= alloc_query(resolv
);
806 req
->node_len
= node
? strlen(node
)+1 : 0;
807 req
->service_len
= service
? strlen(service
)+1 : 0;
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
;
813 if (req
->header
.length
> BUFSIZE
) {
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
;
826 strcpy((char*) req
+ sizeof(addrinfo_request_t
), node
);
829 strcpy((char*) req
+ sizeof(addrinfo_request_t
) + req
->node_len
, service
);
831 if (send(resolv
->fds
[REQUEST_SEND_FD
], req
, req
->header
.length
, MSG_NOSIGNAL
) < 0)
838 sd_resolv_cancel(resolv
, q
);
843 int sd_resolv_getaddrinfo_done(sd_resolv_t
*resolv
, sd_resolv_query_t
* q
, struct addrinfo
**ret_res
) {
847 assert(q
->resolv
== resolv
);
848 assert(q
->type
== REQUEST_ADDRINFO
);
858 *ret_res
= q
->addrinfo
;
863 if (ret
== EAI_SYSTEM
)
867 h_errno
= q
->_h_errno
;
869 sd_resolv_cancel(resolv
, q
);
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
;
888 q
= alloc_query(resolv
);
892 req
->header
.id
= q
->id
;
893 req
->header
.type
= q
->type
= REQUEST_NAMEINFO
;
894 req
->header
.length
= sizeof(nameinfo_request_t
) + salen
;
896 if (req
->header
.length
> BUFSIZE
) {
902 req
->sockaddr_len
= salen
;
903 req
->gethost
= gethost
;
904 req
->getserv
= getserv
;
906 memcpy((uint8_t*) req
+ sizeof(nameinfo_request_t
), sa
, salen
);
908 if (send(resolv
->fds
[REQUEST_SEND_FD
], req
, req
->header
.length
, MSG_NOSIGNAL
) < 0)
915 sd_resolv_cancel(resolv
, q
);
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
) {
924 assert(q
->resolv
== resolv
);
925 assert(q
->type
== REQUEST_NAMEINFO
);
926 assert(!ret_host
|| hostlen
);
927 assert(!ret_serv
|| servlen
);
937 if (ret_host
&& q
->host
) {
938 strncpy(ret_host
, q
->host
, hostlen
);
939 ret_host
[hostlen
-1] = 0;
942 if (ret_serv
&& q
->serv
) {
943 strncpy(ret_serv
, q
->serv
, servlen
);
944 ret_serv
[servlen
-1] = 0;
949 if (ret
== EAI_SYSTEM
)
953 h_errno
= q
->_h_errno
;
955 sd_resolv_cancel(resolv
, q
);
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
;
973 q
= alloc_query(resolv
);
977 req
->dname_len
= strlen(dname
) + 1;
979 req
->header
.id
= q
->id
;
980 req
->header
.type
= q
->type
= qtype
;
981 req
->header
.length
= sizeof(res_request_t
) + req
->dname_len
;
983 if (req
->header
.length
> BUFSIZE
) {
991 strcpy((char*) req
+ sizeof(res_request_t
), dname
);
993 if (send(resolv
->fds
[REQUEST_SEND_FD
], req
, req
->header
.length
, MSG_NOSIGNAL
) < 0)
1000 sd_resolv_cancel(resolv
, q
);
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
);
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
);
1013 int sd_resolv_res_done(sd_resolv_t
*resolv
, sd_resolv_query_t
* q
, unsigned char **answer
) {
1017 assert(q
->resolv
== resolv
);
1018 assert(q
->type
== REQUEST_RES_QUERY
|| q
->type
== REQUEST_RES_SEARCH
);
1031 *answer
= (unsigned char *)q
->serv
;
1038 h_errno
= q
->_h_errno
;
1041 sd_resolv_cancel(resolv
, q
);
1043 return ret
< 0 ? -errno
: ret
;
1046 sd_resolv_query_t
* sd_resolv_getnext(sd_resolv_t
*resolv
) {
1048 return resolv
->done_head
;
1051 int sd_resolv_getnqueries(sd_resolv_t
*resolv
) {
1053 return resolv
->n_queries
;
1056 void sd_resolv_cancel(sd_resolv_t
*resolv
, sd_resolv_query_t
* q
) {
1058 int saved_errno
= errno
;
1062 assert(q
->resolv
== resolv
);
1063 assert(resolv
->n_queries
> 0);
1068 q
->done_prev
->done_next
= q
->done_next
;
1070 resolv
->done_head
= q
->done_next
;
1073 q
->done_next
->done_prev
= q
->done_prev
;
1075 resolv
->done_tail
= q
->done_prev
;
1078 i
= q
->id
% MAX_QUERIES
;
1079 assert(resolv
->queries
[i
] == q
);
1080 resolv
->queries
[i
] = NULL
;
1082 sd_resolv_freeaddrinfo(q
->addrinfo
);
1086 resolv
->n_queries
--;
1089 errno
= saved_errno
;
1092 void sd_resolv_freeaddrinfo(struct addrinfo
*ai
) {
1093 int saved_errno
= errno
;
1096 struct addrinfo
*next
= ai
->ai_next
;
1099 free(ai
->ai_canonname
);
1105 errno
= saved_errno
;
1108 void sd_resolv_freeanswer(unsigned char *answer
) {
1109 int saved_errno
= errno
;
1116 errno
= saved_errno
;
1119 int sd_resolv_isdone(sd_resolv_t
*resolv
, sd_resolv_query_t
*q
) {
1122 assert(q
->resolv
== resolv
);
1127 void sd_resolv_setuserdata(sd_resolv_t
*resolv
, sd_resolv_query_t
*q
, void *userdata
) {
1130 assert(q
->resolv
= resolv
);
1132 q
->userdata
= userdata
;
1135 void* sd_resolv_getuserdata(sd_resolv_t
*resolv
, sd_resolv_query_t
*q
) {
1138 assert(q
->resolv
= resolv
);