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>
47 #include "socket-util.h"
48 #include "sd-resolve.h"
51 #define WORKERS_MAX 16
52 #define QUERIES_MAX 256
81 pthread_t workers[WORKERS_MAX];
82 unsigned n_valid_workers;
84 unsigned current_id, current_index;
85 sd_resolve_query* queries[QUERIES_MAX];
88 LIST_HEAD(sd_resolve_query, done);
89 sd_resolve_query *done_tail;
93 struct sd_resolve_query {
102 struct addrinfo *addrinfo;
107 LIST_FIELDS(sd_resolve_query, done);
110 typedef struct RHeader {
116 typedef struct AddrInfoRequest {
117 struct RHeader header;
123 size_t node_len, service_len;
126 typedef struct AddrInfoResponse {
127 struct RHeader header;
131 /* followed by addrinfo_serialization[] */
134 typedef struct AddrInfoSerialization {
140 size_t canonname_len;
141 /* Followed by ai_addr amd ai_canonname with variable lengths */
142 } AddrInfoSerialization;
144 typedef struct NameInfoRequest {
145 struct RHeader header;
147 socklen_t sockaddr_len;
148 bool gethost:1, getserv:1;
151 typedef struct NameInfoResponse {
152 struct RHeader header;
153 size_t hostlen, servlen;
159 typedef struct ResRequest {
160 struct RHeader header;
166 typedef struct ResResponse {
167 struct RHeader header;
173 typedef union Packet {
175 AddrInfoRequest addrinfo_request;
176 AddrInfoResponse addrinfo_response;
177 NameInfoRequest nameinfo_request;
178 NameInfoResponse nameinfo_response;
179 ResRequest res_request;
180 ResResponse res_response;
183 static int send_died(int out_fd) {
188 rh.type = RESPONSE_DIED;
189 rh.length = sizeof(rh);
191 if (send(out_fd, &rh, rh.length, MSG_NOSIGNAL) < 0)
197 static void *serialize_addrinfo(void *p, const struct addrinfo *ai, size_t *length, size_t maxlength) {
198 AddrInfoSerialization s;
204 assert(*length <= maxlength);
206 cnl = ai->ai_canonname ? strlen(ai->ai_canonname)+1 : 0;
207 l = sizeof(AddrInfoSerialization) + ai->ai_addrlen + cnl;
209 if (*length + l > maxlength)
212 s.ai_flags = ai->ai_flags;
213 s.ai_family = ai->ai_family;
214 s.ai_socktype = ai->ai_socktype;
215 s.ai_protocol = ai->ai_protocol;
216 s.ai_addrlen = ai->ai_addrlen;
217 s.canonname_len = cnl;
219 memcpy((uint8_t*) p, &s, sizeof(AddrInfoSerialization));
220 memcpy((uint8_t*) p + sizeof(AddrInfoSerialization), ai->ai_addr, ai->ai_addrlen);
222 if (ai->ai_canonname)
223 memcpy((char*) p + sizeof(AddrInfoSerialization) + ai->ai_addrlen, ai->ai_canonname, cnl);
226 return (uint8_t*) p + l;
229 static int send_addrinfo_reply(
237 AddrInfoResponse resp = {};
238 struct msghdr mh = {};
241 AddrInfoSerialization ais;
242 uint8_t space[BUFSIZE];
247 resp.header.type = RESPONSE_ADDRINFO;
249 resp.header.length = sizeof(AddrInfoResponse);
251 resp._errno = _errno;
252 resp._h_errno = _h_errno;
254 if (ret == 0 && ai) {
258 for (k = ai; k; k = k->ai_next) {
259 p = serialize_addrinfo(p, k, &resp.header.length, (uint8_t*) &buffer + BUFSIZE - (uint8_t*) p);
270 iov[0] = (struct iovec) { .iov_base = &resp, .iov_len = sizeof(AddrInfoResponse) };
271 iov[1] = (struct iovec) { .iov_base = &buffer, .iov_len = resp.header.length - sizeof(AddrInfoResponse) };
274 mh.msg_iovlen = ELEMENTSOF(iov);
276 if (sendmsg(out_fd, &mh, MSG_NOSIGNAL) < 0)
282 static int send_nameinfo_reply(
291 NameInfoResponse resp = {};
292 struct msghdr mh = {};
298 sl = serv ? strlen(serv)+1 : 0;
299 hl = host ? strlen(host)+1 : 0;
301 resp.header.type = RESPONSE_NAMEINFO;
303 resp.header.length = sizeof(NameInfoResponse) + hl + sl;
305 resp._errno = _errno;
306 resp._h_errno = _h_errno;
310 iov[0] = (struct iovec) { .iov_base = &resp, .iov_len = sizeof(NameInfoResponse) };
311 iov[1] = (struct iovec) { .iov_base = (void*) host, .iov_len = hl };
312 iov[2] = (struct iovec) { .iov_base = (void*) serv, .iov_len = sl };
315 mh.msg_iovlen = ELEMENTSOF(iov);
317 if (sendmsg(out_fd, &mh, MSG_NOSIGNAL) < 0)
323 static int send_res_reply(int out_fd, unsigned id, const unsigned char *answer, int ret, int _errno, int _h_errno) {
324 struct msghdr mh = {};
326 ResResponse resp = {};
331 l = ret > 0 ? (size_t) ret : 0;
333 resp.header.type = RESPONSE_RES;
335 resp.header.length = sizeof(ResResponse) + l;
337 resp._errno = _errno;
338 resp._h_errno = _h_errno;
340 iov[0] = (struct iovec) { .iov_base = &resp, .iov_len = sizeof(ResResponse) };
341 iov[1] = (struct iovec) { .iov_base = (void*) answer, .iov_len = l };
344 mh.msg_iovlen = ELEMENTSOF(iov);
346 if (sendmsg(out_fd, &mh, MSG_NOSIGNAL) < 0)
352 static int handle_request(int out_fd, const Packet *packet, size_t length) {
358 req = &packet->rheader;
360 assert(length >= sizeof(RHeader));
361 assert(length == req->length);
365 case REQUEST_ADDRINFO: {
366 const AddrInfoRequest *ai_req = &packet->addrinfo_request;
367 struct addrinfo hints = {}, *result = NULL;
368 const char *node, *service;
371 assert(length >= sizeof(AddrInfoRequest));
372 assert(length == sizeof(AddrInfoRequest) + ai_req->node_len + ai_req->service_len);
374 hints.ai_flags = ai_req->ai_flags;
375 hints.ai_family = ai_req->ai_family;
376 hints.ai_socktype = ai_req->ai_socktype;
377 hints.ai_protocol = ai_req->ai_protocol;
379 node = ai_req->node_len ? (const char*) ai_req + sizeof(AddrInfoRequest) : NULL;
380 service = ai_req->service_len ? (const char*) ai_req + sizeof(AddrInfoRequest) + ai_req->node_len : NULL;
384 ai_req->hints_valid ? &hints : NULL,
387 /* send_addrinfo_reply() frees result */
388 return send_addrinfo_reply(out_fd, req->id, ret, result, errno, h_errno);
391 case REQUEST_NAMEINFO: {
392 const NameInfoRequest *ni_req = &packet->nameinfo_request;
393 char hostbuf[NI_MAXHOST], servbuf[NI_MAXSERV];
394 union sockaddr_union sa;
397 assert(length >= sizeof(NameInfoRequest));
398 assert(length == sizeof(NameInfoRequest) + ni_req->sockaddr_len);
399 assert(sizeof(sa) >= ni_req->sockaddr_len);
401 memcpy(&sa, (const uint8_t *) ni_req + sizeof(NameInfoRequest), ni_req->sockaddr_len);
403 ret = getnameinfo(&sa.sa, ni_req->sockaddr_len,
404 ni_req->gethost ? hostbuf : NULL, ni_req->gethost ? sizeof(hostbuf) : 0,
405 ni_req->getserv ? servbuf : NULL, ni_req->getserv ? sizeof(servbuf) : 0,
408 return send_nameinfo_reply(out_fd, req->id, ret,
409 ret == 0 && ni_req->gethost ? hostbuf : NULL,
410 ret == 0 && ni_req->getserv ? servbuf : NULL,
414 case REQUEST_RES_QUERY:
415 case REQUEST_RES_SEARCH: {
416 const ResRequest *res_req = &packet->res_request;
419 uint8_t space[BUFSIZE];
424 assert(length >= sizeof(ResRequest));
425 assert(length == sizeof(ResRequest) + res_req->dname_len);
427 dname = (const char *) req + sizeof(ResRequest);
429 if (req->type == REQUEST_RES_QUERY)
430 ret = res_query(dname, res_req->class, res_req->type, (unsigned char *) &answer, BUFSIZE);
432 ret = res_search(dname, res_req->class, res_req->type, (unsigned char *) &answer, BUFSIZE);
434 return send_res_reply(out_fd, req->id, (unsigned char *) &answer, ret, errno, h_errno);
437 case REQUEST_TERMINATE:
442 assert_not_reached("Unknown request");
448 static void* thread_worker(void *p) {
449 sd_resolve *resolve = p;
452 /* No signals in this thread please */
453 assert_se(sigfillset(&fullset) == 0);
454 assert_se(pthread_sigmask(SIG_BLOCK, &fullset, NULL) == 0);
456 /* Assign a pretty name to this thread */
457 prctl(PR_SET_NAME, (unsigned long) "sd-resolve");
459 while (!resolve->dead) {
462 uint8_t space[BUFSIZE];
466 length = recv(resolve->fds[REQUEST_RECV_FD], &buf, sizeof(buf), 0);
479 if (handle_request(resolve->fds[RESPONSE_SEND_FD], &buf.packet, (size_t) length) < 0)
483 send_died(resolve->fds[RESPONSE_SEND_FD]);
488 static int start_threads(sd_resolve *resolve, unsigned extra) {
492 n = resolve->n_queries - resolve->n_done + extra;
499 while (resolve->n_valid_workers < n) {
501 r = pthread_create(&resolve->workers[resolve->n_valid_workers], NULL, thread_worker, resolve);
505 resolve->n_valid_workers ++;
511 static bool resolve_pid_changed(sd_resolve *r) {
514 /* We don't support people creating a resolver and keeping it
515 * around after fork(). Let's complain. */
517 return r->original_pid != getpid();
520 _public_ int sd_resolve_new(sd_resolve **ret) {
521 sd_resolve *resolve = NULL;
524 assert_return(ret, -EINVAL);
526 resolve = new0(sd_resolve, 1);
530 for (i = 0; i < _FD_MAX; i++)
531 resolve->fds[i] = -1;
533 resolve->original_pid = getpid();
535 r = socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds + REQUEST_RECV_FD);
541 r = socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds + RESPONSE_RECV_FD);
547 fd_inc_sndbuf(resolve->fds[REQUEST_SEND_FD], QUERIES_MAX * BUFSIZE);
548 fd_inc_rcvbuf(resolve->fds[REQUEST_RECV_FD], QUERIES_MAX * BUFSIZE);
549 fd_inc_sndbuf(resolve->fds[RESPONSE_SEND_FD], QUERIES_MAX * BUFSIZE);
550 fd_inc_rcvbuf(resolve->fds[RESPONSE_RECV_FD], QUERIES_MAX * BUFSIZE);
552 fd_nonblock(resolve->fds[RESPONSE_RECV_FD], true);
559 sd_resolve_unref(resolve);
564 _public_ sd_resolve* sd_resolve_unref(sd_resolve *resolve) {
569 assert_return(resolve, NULL);
570 assert_return(!resolve_pid_changed(resolve), NULL);
572 resolve->dead = true;
574 if (resolve->fds[REQUEST_SEND_FD] >= 0) {
577 .type = REQUEST_TERMINATE,
578 .length = sizeof(req)
581 /* Send one termination packet for each worker */
582 for (i = 0; i < resolve->n_valid_workers; i++)
583 send(resolve->fds[REQUEST_SEND_FD], &req, req.length, MSG_NOSIGNAL);
586 /* Now terminate them and wait until they are gone. */
587 for (i = 0; i < resolve->n_valid_workers; i++) {
589 if (pthread_join(resolve->workers[i], NULL) != EINTR)
594 /* Close all communication channels */
595 for (i = 0; i < _FD_MAX; i++)
596 safe_close(resolve->fds[i]);
598 for (i = 0; i < QUERIES_MAX && resolve->n_queries > 0; i++)
599 if (resolve->queries[i])
600 sd_resolve_cancel(resolve->queries[i]);
606 _public_ int sd_resolve_get_fd(sd_resolve *resolve) {
607 assert_return(resolve, -EINVAL);
608 assert_return(!resolve_pid_changed(resolve), -ECHILD);
610 return resolve->fds[RESPONSE_RECV_FD];
613 _public_ int sd_resolve_get_events(sd_resolve *resolve) {
614 assert_return(resolve, -EINVAL);
615 assert_return(!resolve_pid_changed(resolve), -ECHILD);
617 return resolve->n_queries > resolve->n_done ? POLLIN : 0;
620 _public_ int sd_resolve_get_timeout(sd_resolve *resolve, uint64_t *usec) {
621 assert_return(resolve, -EINVAL);
622 assert_return(usec, -EINVAL);
623 assert_return(!resolve_pid_changed(resolve), -ECHILD);
625 *usec = (uint64_t) -1;
629 static sd_resolve_query *lookup_query(sd_resolve *resolve, unsigned id) {
634 q = resolve->queries[id % QUERIES_MAX];
642 static void complete_query(sd_resolve_query *q) {
647 LIST_PREPEND(done, q->resolve->done, q);
648 q->resolve->n_done ++;
651 static int unserialize_addrinfo(const void **p, size_t *length, struct addrinfo **ret_ai) {
652 AddrInfoSerialization s;
661 if (*length < sizeof(AddrInfoSerialization))
664 memcpy(&s, *p, sizeof(s));
666 l = sizeof(AddrInfoSerialization) + s.ai_addrlen + s.canonname_len;
670 ai = new0(struct addrinfo, 1);
674 ai->ai_flags = s.ai_flags;
675 ai->ai_family = s.ai_family;
676 ai->ai_socktype = s.ai_socktype;
677 ai->ai_protocol = s.ai_protocol;
678 ai->ai_addrlen = s.ai_addrlen;
680 if (s.ai_addrlen > 0) {
681 ai->ai_addr = memdup((const uint8_t*) *p + sizeof(AddrInfoSerialization), s.ai_addrlen);
688 if (s.canonname_len > 0) {
689 ai->ai_canonname = memdup((const uint8_t*) *p + sizeof(AddrInfoSerialization) + s.ai_addrlen, s.canonname_len);
690 if (!ai->ai_canonname) {
699 *p = ((const uint8_t*) *p) + l;
704 static int handle_response(sd_resolve *resolve, const Packet *packet, size_t length) {
711 resp = &packet->rheader;
713 assert(length >= sizeof(RHeader));
714 assert(length == resp->length);
716 if (resp->type == RESPONSE_DIED) {
717 resolve->dead = true;
721 q = lookup_query(resolve, resp->id);
725 switch (resp->type) {
727 case RESPONSE_ADDRINFO: {
728 const AddrInfoResponse *ai_resp = &packet->addrinfo_response;
731 struct addrinfo *prev = NULL;
733 assert(length >= sizeof(AddrInfoResponse));
734 assert(q->type == REQUEST_ADDRINFO);
736 q->ret = ai_resp->ret;
737 q->_errno = ai_resp->_errno;
738 q->_h_errno = ai_resp->_h_errno;
740 l = length - sizeof(AddrInfoResponse);
741 p = (const uint8_t*) resp + sizeof(AddrInfoResponse);
744 struct addrinfo *ai = NULL;
746 r = unserialize_addrinfo(&p, &l, &ai);
751 freeaddrinfo(q->addrinfo);
768 case RESPONSE_NAMEINFO: {
769 const NameInfoResponse *ni_resp = &packet->nameinfo_response;
771 assert(length >= sizeof(NameInfoResponse));
772 assert(q->type == REQUEST_NAMEINFO);
774 q->ret = ni_resp->ret;
775 q->_errno = ni_resp->_errno;
776 q->_h_errno = ni_resp->_h_errno;
778 if (ni_resp->hostlen > 0) {
779 q->host = strndup((const char*) ni_resp + sizeof(NameInfoResponse), ni_resp->hostlen-1);
787 if (ni_resp->servlen > 0) {
788 q->serv = strndup((const char*) ni_resp + sizeof(NameInfoResponse) + ni_resp->hostlen, ni_resp->servlen-1);
801 const ResResponse *res_resp = &packet->res_response;
803 assert(length >= sizeof(ResResponse));
804 assert(q->type == REQUEST_RES_QUERY || q->type == REQUEST_RES_SEARCH);
806 q->ret = res_resp->ret;
807 q->_errno = res_resp->_errno;
808 q->_h_errno = res_resp->_h_errno;
810 if (res_resp->ret >= 0) {
811 q->serv = memdup((const char *)resp + sizeof(ResResponse), res_resp->ret);
830 _public_ int sd_resolve_process(sd_resolve *resolve) {
831 int n_processed = 0, r;
833 assert_return(resolve, -EINVAL);
834 assert_return(!resolve_pid_changed(resolve), -ECHILD);
840 uint8_t space[BUFSIZE];
843 l = recv(resolve->fds[RESPONSE_RECV_FD], &buf, sizeof(buf), 0);
851 return -ECONNREFUSED;
853 r = handle_response(resolve, &buf.packet, (size_t) l);
861 _public_ int sd_resolve_wait(sd_resolve *resolve, uint64_t timeout_usec) {
864 assert_return(resolve, -EINVAL);
865 assert_return(!resolve_pid_changed(resolve), -ECHILD);
867 if (resolve->n_queries <= 0)
871 r = fd_wait_for_event(resolve->fds[RESPONSE_RECV_FD], POLLIN, timeout_usec);
872 } while (r == -EINTR);
877 return sd_resolve_process(resolve);
880 static int alloc_query(sd_resolve *resolve, sd_resolve_query **_q) {
887 if (resolve->n_queries >= QUERIES_MAX)
890 r = start_threads(resolve, 1);
894 while (resolve->queries[resolve->current_index]) {
895 resolve->current_index++;
896 resolve->current_id++;
898 resolve->current_index %= QUERIES_MAX;
901 q = resolve->queries[resolve->current_index] = new0(sd_resolve_query, 1);
905 resolve->n_queries++;
907 q->resolve = resolve;
908 q->id = resolve->current_id;
914 _public_ int sd_resolve_getaddrinfo(
916 sd_resolve_query **_q,
919 const struct addrinfo *hints) {
921 AddrInfoRequest req = {};
922 struct msghdr mh = {};
927 assert_return(resolve, -EINVAL);
928 assert_return(node || service, -EINVAL);
929 assert_return(_q, -EINVAL);
930 assert_return(!resolve_pid_changed(resolve), -ECHILD);
932 r = alloc_query(resolve, &q);
936 req.node_len = node ? strlen(node)+1 : 0;
937 req.service_len = service ? strlen(service)+1 : 0;
939 req.header.id = q->id;
940 req.header.type = q->type = REQUEST_ADDRINFO;
941 req.header.length = sizeof(AddrInfoRequest) + req.node_len + req.service_len;
944 req.hints_valid = true;
945 req.ai_flags = hints->ai_flags;
946 req.ai_family = hints->ai_family;
947 req.ai_socktype = hints->ai_socktype;
948 req.ai_protocol = hints->ai_protocol;
951 iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(AddrInfoRequest) };
954 iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = (void*) node, .iov_len = req.node_len };
957 iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = (void*) service, .iov_len = req.service_len };
961 if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) {
962 sd_resolve_cancel(q);
970 _public_ int sd_resolve_getaddrinfo_done(sd_resolve_query* q, struct addrinfo **ret_res) {
978 if (q->type != REQUEST_ADDRINFO) {
983 if (resolve_pid_changed(q->resolve)) {
991 *ret_res = q->addrinfo;
999 h_errno = q->_h_errno;
1002 sd_resolve_cancel(q);
1007 _public_ int sd_resolve_getnameinfo(
1008 sd_resolve *resolve,
1009 sd_resolve_query**_q,
1010 const struct sockaddr *sa, socklen_t salen,
1012 int gethost, int getserv) {
1014 NameInfoRequest req = {};
1015 struct msghdr mh = {};
1016 struct iovec iov[2];
1017 sd_resolve_query *q;
1020 assert_return(resolve, -EINVAL);
1021 assert_return(sa, -EINVAL);
1022 assert_return(salen >= sizeof(struct sockaddr), -EINVAL);
1023 assert_return(salen <= sizeof(union sockaddr_union), -EINVAL);
1024 assert_return(_q, -EINVAL);
1025 assert_return(!resolve_pid_changed(resolve), -ECHILD);
1027 r = alloc_query(resolve, &q);
1031 req.header.id = q->id;
1032 req.header.type = q->type = REQUEST_NAMEINFO;
1033 req.header.length = sizeof(NameInfoRequest) + salen;
1036 req.sockaddr_len = salen;
1037 req.gethost = !!gethost;
1038 req.getserv = !!getserv;
1040 iov[0] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(NameInfoRequest) };
1041 iov[1] = (struct iovec) { .iov_base = (void*) sa, .iov_len = salen };
1046 if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) {
1047 sd_resolve_cancel(q);
1055 _public_ int sd_resolve_getnameinfo_done(sd_resolve_query* q, char **ret_host, char **ret_serv) {
1063 if (q->type != REQUEST_NAMEINFO) {
1068 if (resolve_pid_changed(q->resolve)) {
1077 *ret_host = q->host;
1082 *ret_serv = q->serv;
1090 h_errno = q->_h_errno;
1093 sd_resolve_cancel(q);
1098 static int resolve_res(
1099 sd_resolve *resolve,
1100 sd_resolve_query **_q,
1103 int class, int type) {
1105 struct msghdr mh = {};
1106 struct iovec iov[2];
1107 ResRequest req = {};
1108 sd_resolve_query *q;
1111 assert_return(resolve, -EINVAL);
1112 assert_return(dname, -EINVAL);
1113 assert_return(_q, -EINVAL);
1114 assert_return(!resolve_pid_changed(resolve), -ECHILD);
1116 r = alloc_query(resolve, &q);
1120 req.dname_len = strlen(dname) + 1;
1124 req.header.id = q->id;
1125 req.header.type = q->type = qtype;
1126 req.header.length = sizeof(ResRequest) + req.dname_len;
1128 iov[0] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(ResRequest) };
1129 iov[1] = (struct iovec) { .iov_base = (void*) dname, .iov_len = req.dname_len };
1134 if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) {
1135 sd_resolve_cancel(q);
1143 _public_ int sd_resolve_res_query(sd_resolve *resolve, sd_resolve_query** q, const char *dname, int class, int type) {
1144 return resolve_res(resolve, q, REQUEST_RES_QUERY, dname, class, type);
1147 _public_ int sd_resolve_res_search(sd_resolve *resolve, sd_resolve_query** q, const char *dname, int class, int type) {
1148 return resolve_res(resolve, q, REQUEST_RES_SEARCH, dname, class, type);
1151 _public_ int sd_resolve_res_done(sd_resolve_query* q, unsigned char **answer) {
1154 assert_return(q, -EINVAL);
1155 assert_return(answer, -EINVAL);
1156 assert_return(q->type == REQUEST_RES_QUERY || q->type == REQUEST_RES_SEARCH, -ENOTTY);
1157 assert_return(!resolve_pid_changed(q->resolve), -ECHILD);
1162 *answer = (unsigned char *) q->serv;
1169 h_errno = q->_h_errno;
1172 sd_resolve_cancel(q);
1174 return ret < 0 ? -errno : ret;
1177 _public_ int sd_resolve_get_next(sd_resolve *resolve, sd_resolve_query **q) {
1178 assert_return(resolve, -EINVAL);
1179 assert_return(q, -EINVAL);
1180 assert_return(!resolve_pid_changed(resolve), -ECHILD);
1183 return !!resolve->done;
1186 _public_ int sd_resolve_get_n_queries(sd_resolve *resolve) {
1187 assert_return(resolve, -EINVAL);
1188 assert_return(!resolve_pid_changed(resolve), -ECHILD);
1190 return resolve->n_queries;
1193 _public_ int sd_resolve_cancel(sd_resolve_query* q) {
1200 assert_return(!resolve_pid_changed(q->resolve), -ECHILD);
1203 assert(q->resolve->n_queries > 0);
1206 LIST_REMOVE(done, q->resolve->done, q);
1207 q->resolve->n_done--;
1210 i = q->id % QUERIES_MAX;
1211 assert(q->resolve->queries[i] == q);
1212 q->resolve->queries[i] = NULL;
1213 q->resolve->n_queries--;
1215 sd_resolve_freeaddrinfo(q->addrinfo);
1223 _public_ void sd_resolve_freeaddrinfo(struct addrinfo *ai) {
1226 struct addrinfo *next = ai->ai_next;
1229 free(ai->ai_canonname);
1236 _public_ int sd_resolve_is_done(sd_resolve_query *q) {
1237 assert_return(q, -EINVAL);
1238 assert_return(!resolve_pid_changed(q->resolve), -ECHILD);
1243 _public_ void* sd_resolve_set_userdata(sd_resolve_query *q, void *userdata) {
1246 assert_return(q, NULL);
1247 assert_return(!resolve_pid_changed(q->resolve), NULL);
1250 q->userdata = userdata;
1255 _public_ void* sd_resolve_get_userdata(sd_resolve_query *q) {
1256 assert_return(q, NULL);
1257 assert_return(!resolve_pid_changed(q->resolve), NULL);