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 if (resolve->fds[i] >= 0)
597 close_nointr_nofail(resolve->fds[i]);
599 for (i = 0; i < QUERIES_MAX && resolve->n_queries > 0; i++)
600 if (resolve->queries[i])
601 sd_resolve_cancel(resolve->queries[i]);
607 _public_ int sd_resolve_get_fd(sd_resolve *resolve) {
608 assert_return(resolve, -EINVAL);
609 assert_return(!resolve_pid_changed(resolve), -ECHILD);
611 return resolve->fds[RESPONSE_RECV_FD];
614 _public_ int sd_resolve_get_events(sd_resolve *resolve) {
615 assert_return(resolve, -EINVAL);
616 assert_return(!resolve_pid_changed(resolve), -ECHILD);
618 return resolve->n_queries > resolve->n_done ? POLLIN : 0;
621 _public_ int sd_resolve_get_timeout(sd_resolve *resolve, uint64_t *usec) {
622 assert_return(resolve, -EINVAL);
623 assert_return(usec, -EINVAL);
624 assert_return(!resolve_pid_changed(resolve), -ECHILD);
626 *usec = (uint64_t) -1;
630 static sd_resolve_query *lookup_query(sd_resolve *resolve, unsigned id) {
635 q = resolve->queries[id % QUERIES_MAX];
643 static void complete_query(sd_resolve_query *q) {
648 LIST_PREPEND(done, q->resolve->done, q);
649 q->resolve->n_done ++;
652 static int unserialize_addrinfo(const void **p, size_t *length, struct addrinfo **ret_ai) {
653 AddrInfoSerialization s;
662 if (*length < sizeof(AddrInfoSerialization))
665 memcpy(&s, *p, sizeof(s));
667 l = sizeof(AddrInfoSerialization) + s.ai_addrlen + s.canonname_len;
671 ai = new0(struct addrinfo, 1);
675 ai->ai_flags = s.ai_flags;
676 ai->ai_family = s.ai_family;
677 ai->ai_socktype = s.ai_socktype;
678 ai->ai_protocol = s.ai_protocol;
679 ai->ai_addrlen = s.ai_addrlen;
681 if (s.ai_addrlen > 0) {
682 ai->ai_addr = memdup((const uint8_t*) *p + sizeof(AddrInfoSerialization), s.ai_addrlen);
689 if (s.canonname_len > 0) {
690 ai->ai_canonname = memdup((const uint8_t*) *p + sizeof(AddrInfoSerialization) + s.ai_addrlen, s.canonname_len);
691 if (!ai->ai_canonname) {
700 *p = ((const uint8_t*) *p) + l;
705 static int handle_response(sd_resolve *resolve, const Packet *packet, size_t length) {
712 resp = &packet->rheader;
714 assert(length >= sizeof(RHeader));
715 assert(length == resp->length);
717 if (resp->type == RESPONSE_DIED) {
718 resolve->dead = true;
722 q = lookup_query(resolve, resp->id);
726 switch (resp->type) {
728 case RESPONSE_ADDRINFO: {
729 const AddrInfoResponse *ai_resp = &packet->addrinfo_response;
732 struct addrinfo *prev = NULL;
734 assert(length >= sizeof(AddrInfoResponse));
735 assert(q->type == REQUEST_ADDRINFO);
737 q->ret = ai_resp->ret;
738 q->_errno = ai_resp->_errno;
739 q->_h_errno = ai_resp->_h_errno;
741 l = length - sizeof(AddrInfoResponse);
742 p = (const uint8_t*) resp + sizeof(AddrInfoResponse);
745 struct addrinfo *ai = NULL;
747 r = unserialize_addrinfo(&p, &l, &ai);
752 freeaddrinfo(q->addrinfo);
769 case RESPONSE_NAMEINFO: {
770 const NameInfoResponse *ni_resp = &packet->nameinfo_response;
772 assert(length >= sizeof(NameInfoResponse));
773 assert(q->type == REQUEST_NAMEINFO);
775 q->ret = ni_resp->ret;
776 q->_errno = ni_resp->_errno;
777 q->_h_errno = ni_resp->_h_errno;
779 if (ni_resp->hostlen > 0) {
780 q->host = strndup((const char*) ni_resp + sizeof(NameInfoResponse), ni_resp->hostlen-1);
788 if (ni_resp->servlen > 0) {
789 q->serv = strndup((const char*) ni_resp + sizeof(NameInfoResponse) + ni_resp->hostlen, ni_resp->servlen-1);
802 const ResResponse *res_resp = &packet->res_response;
804 assert(length >= sizeof(ResResponse));
805 assert(q->type == REQUEST_RES_QUERY || q->type == REQUEST_RES_SEARCH);
807 q->ret = res_resp->ret;
808 q->_errno = res_resp->_errno;
809 q->_h_errno = res_resp->_h_errno;
811 if (res_resp->ret >= 0) {
812 q->serv = memdup((const char *)resp + sizeof(ResResponse), res_resp->ret);
831 _public_ int sd_resolve_process(sd_resolve *resolve) {
832 int n_processed = 0, r;
834 assert_return(resolve, -EINVAL);
835 assert_return(!resolve_pid_changed(resolve), -ECHILD);
841 uint8_t space[BUFSIZE];
844 l = recv(resolve->fds[RESPONSE_RECV_FD], &buf, sizeof(buf), 0);
852 return -ECONNREFUSED;
854 r = handle_response(resolve, &buf.packet, (size_t) l);
862 _public_ int sd_resolve_wait(sd_resolve *resolve, uint64_t timeout_usec) {
865 assert_return(resolve, -EINVAL);
866 assert_return(!resolve_pid_changed(resolve), -ECHILD);
868 if (resolve->n_queries <= 0)
872 r = fd_wait_for_event(resolve->fds[RESPONSE_RECV_FD], POLLIN, timeout_usec);
873 } while (r == -EINTR);
878 return sd_resolve_process(resolve);
881 static int alloc_query(sd_resolve *resolve, sd_resolve_query **_q) {
888 if (resolve->n_queries >= QUERIES_MAX)
891 r = start_threads(resolve, 1);
895 while (resolve->queries[resolve->current_index]) {
896 resolve->current_index++;
897 resolve->current_id++;
899 resolve->current_index %= QUERIES_MAX;
902 q = resolve->queries[resolve->current_index] = new0(sd_resolve_query, 1);
906 resolve->n_queries++;
908 q->resolve = resolve;
909 q->id = resolve->current_id;
915 _public_ int sd_resolve_getaddrinfo(
919 const struct addrinfo *hints,
920 sd_resolve_query **_q) {
922 AddrInfoRequest req = {};
923 struct msghdr mh = {};
928 assert_return(resolve, -EINVAL);
929 assert_return(node || service, -EINVAL);
930 assert_return(_q, -EINVAL);
931 assert_return(!resolve_pid_changed(resolve), -ECHILD);
933 r = alloc_query(resolve, &q);
937 req.node_len = node ? strlen(node)+1 : 0;
938 req.service_len = service ? strlen(service)+1 : 0;
940 req.header.id = q->id;
941 req.header.type = q->type = REQUEST_ADDRINFO;
942 req.header.length = sizeof(AddrInfoRequest) + req.node_len + req.service_len;
945 req.hints_valid = true;
946 req.ai_flags = hints->ai_flags;
947 req.ai_family = hints->ai_family;
948 req.ai_socktype = hints->ai_socktype;
949 req.ai_protocol = hints->ai_protocol;
952 iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(AddrInfoRequest) };
955 iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = (void*) node, .iov_len = req.node_len };
958 iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = (void*) service, .iov_len = req.service_len };
962 if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) {
963 sd_resolve_cancel(q);
971 _public_ int sd_resolve_getaddrinfo_done(sd_resolve_query* q, struct addrinfo **ret_res) {
979 if (q->type != REQUEST_ADDRINFO) {
984 if (resolve_pid_changed(q->resolve)) {
992 *ret_res = q->addrinfo;
1000 h_errno = q->_h_errno;
1003 sd_resolve_cancel(q);
1008 _public_ int sd_resolve_getnameinfo(
1009 sd_resolve *resolve,
1010 const struct sockaddr *sa, socklen_t salen,
1012 int gethost, int getserv,
1013 sd_resolve_query**_q) {
1015 NameInfoRequest req = {};
1016 struct msghdr mh = {};
1017 struct iovec iov[2];
1018 sd_resolve_query *q;
1021 assert_return(resolve, -EINVAL);
1022 assert_return(sa, -EINVAL);
1023 assert_return(salen >= sizeof(struct sockaddr), -EINVAL);
1024 assert_return(salen <= sizeof(union sockaddr_union), -EINVAL);
1025 assert_return(_q, -EINVAL);
1026 assert_return(!resolve_pid_changed(resolve), -ECHILD);
1028 r = alloc_query(resolve, &q);
1032 req.header.id = q->id;
1033 req.header.type = q->type = REQUEST_NAMEINFO;
1034 req.header.length = sizeof(NameInfoRequest) + salen;
1037 req.sockaddr_len = salen;
1038 req.gethost = !!gethost;
1039 req.getserv = !!getserv;
1041 iov[0] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(NameInfoRequest) };
1042 iov[1] = (struct iovec) { .iov_base = (void*) sa, .iov_len = salen };
1047 if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) {
1048 sd_resolve_cancel(q);
1056 _public_ int sd_resolve_getnameinfo_done(sd_resolve_query* q, char **ret_host, char **ret_serv) {
1064 if (q->type != REQUEST_NAMEINFO) {
1069 if (resolve_pid_changed(q->resolve)) {
1078 *ret_host = q->host;
1083 *ret_serv = q->serv;
1091 h_errno = q->_h_errno;
1094 sd_resolve_cancel(q);
1099 static int resolve_res(
1100 sd_resolve *resolve,
1103 int class, int type,
1104 sd_resolve_query **_q) {
1106 struct msghdr mh = {};
1107 struct iovec iov[2];
1108 ResRequest req = {};
1109 sd_resolve_query *q;
1112 assert_return(resolve, -EINVAL);
1113 assert_return(dname, -EINVAL);
1114 assert_return(_q, -EINVAL);
1115 assert_return(!resolve_pid_changed(resolve), -ECHILD);
1117 r = alloc_query(resolve, &q);
1121 req.dname_len = strlen(dname) + 1;
1125 req.header.id = q->id;
1126 req.header.type = q->type = qtype;
1127 req.header.length = sizeof(ResRequest) + req.dname_len;
1129 iov[0] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(ResRequest) };
1130 iov[1] = (struct iovec) { .iov_base = (void*) dname, .iov_len = req.dname_len };
1135 if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) {
1136 sd_resolve_cancel(q);
1144 _public_ int sd_resolve_res_query(sd_resolve *resolve, const char *dname, int class, int type, sd_resolve_query** q) {
1145 return resolve_res(resolve, REQUEST_RES_QUERY, dname, class, type, q);
1148 _public_ int sd_resolve_res_search(sd_resolve *resolve, const char *dname, int class, int type, sd_resolve_query** q) {
1149 return resolve_res(resolve, REQUEST_RES_SEARCH, dname, class, type, q);
1152 _public_ int sd_resolve_res_done(sd_resolve_query* q, unsigned char **answer) {
1155 assert_return(q, -EINVAL);
1156 assert_return(answer, -EINVAL);
1157 assert_return(q->type == REQUEST_RES_QUERY || q->type == REQUEST_RES_SEARCH, -ENOTTY);
1158 assert_return(!resolve_pid_changed(q->resolve), -ECHILD);
1163 *answer = (unsigned char *) q->serv;
1170 h_errno = q->_h_errno;
1173 sd_resolve_cancel(q);
1175 return ret < 0 ? -errno : ret;
1178 _public_ int sd_resolve_get_next(sd_resolve *resolve, sd_resolve_query **q) {
1179 assert_return(resolve, -EINVAL);
1180 assert_return(q, -EINVAL);
1181 assert_return(!resolve_pid_changed(resolve), -ECHILD);
1184 return !!resolve->done;
1187 _public_ int sd_resolve_get_n_queries(sd_resolve *resolve) {
1188 assert_return(resolve, -EINVAL);
1189 assert_return(!resolve_pid_changed(resolve), -ECHILD);
1191 return resolve->n_queries;
1194 _public_ int sd_resolve_cancel(sd_resolve_query* q) {
1201 assert_return(!resolve_pid_changed(q->resolve), -ECHILD);
1204 assert(q->resolve->n_queries > 0);
1207 LIST_REMOVE(done, q->resolve->done, q);
1208 q->resolve->n_done--;
1211 i = q->id % QUERIES_MAX;
1212 assert(q->resolve->queries[i] == q);
1213 q->resolve->queries[i] = NULL;
1214 q->resolve->n_queries--;
1216 sd_resolve_freeaddrinfo(q->addrinfo);
1224 _public_ void sd_resolve_freeaddrinfo(struct addrinfo *ai) {
1227 struct addrinfo *next = ai->ai_next;
1230 free(ai->ai_canonname);
1237 _public_ int sd_resolve_is_done(sd_resolve_query *q) {
1238 assert_return(q, -EINVAL);
1239 assert_return(!resolve_pid_changed(q->resolve), -ECHILD);
1244 _public_ void* sd_resolve_set_userdata(sd_resolve_query *q, void *userdata) {
1247 assert_return(q, NULL);
1248 assert_return(!resolve_pid_changed(q->resolve), NULL);
1251 q->userdata = userdata;
1256 _public_ void* sd_resolve_get_userdata(sd_resolve_query *q) {
1257 assert_return(q, NULL);
1258 assert_return(!resolve_pid_changed(q->resolve), NULL);