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"
49 #include "resolve-util.h"
50 #include "sd-resolve.h"
52 #define WORKERS_MIN 1U
53 #define WORKERS_MAX 16U
54 #define QUERIES_MAX 256U
55 #define BUFSIZE 10240U
85 pthread_t workers[WORKERS_MAX];
86 unsigned n_valid_workers;
88 unsigned current_id, current_index;
89 sd_resolve_query* queries[QUERIES_MAX];
90 unsigned n_queries, n_done;
92 sd_event_source *event_source;
95 sd_resolve_query *current;
97 sd_resolve **default_resolve_ptr;
101 struct sd_resolve_query {
113 struct addrinfo *addrinfo;
115 unsigned char *answer;
118 sd_resolve_getaddrinfo_handler_t getaddrinfo_handler;
119 sd_resolve_getnameinfo_handler_t getnameinfo_handler;
120 sd_resolve_res_handler_t res_handler;
126 typedef struct RHeader {
132 typedef struct AddrInfoRequest {
133 struct RHeader header;
139 size_t node_len, service_len;
142 typedef struct AddrInfoResponse {
143 struct RHeader header;
147 /* followed by addrinfo_serialization[] */
150 typedef struct AddrInfoSerialization {
156 size_t canonname_len;
157 /* Followed by ai_addr amd ai_canonname with variable lengths */
158 } AddrInfoSerialization;
160 typedef struct NameInfoRequest {
161 struct RHeader header;
163 socklen_t sockaddr_len;
164 bool gethost:1, getserv:1;
167 typedef struct NameInfoResponse {
168 struct RHeader header;
169 size_t hostlen, servlen;
175 typedef struct ResRequest {
176 struct RHeader header;
182 typedef struct ResResponse {
183 struct RHeader header;
189 typedef union Packet {
191 AddrInfoRequest addrinfo_request;
192 AddrInfoResponse addrinfo_response;
193 NameInfoRequest nameinfo_request;
194 NameInfoResponse nameinfo_response;
195 ResRequest res_request;
196 ResResponse res_response;
199 static int getaddrinfo_done(sd_resolve_query* q);
200 static int getnameinfo_done(sd_resolve_query *q);
201 static int res_query_done(sd_resolve_query* q);
203 #define RESOLVE_DONT_DESTROY(resolve) \
204 _cleanup_resolve_unref_ _unused_ sd_resolve *_dont_destroy_##resolve = sd_resolve_ref(resolve)
206 static int send_died(int out_fd) {
209 .type = RESPONSE_DIED,
210 .length = sizeof(RHeader),
215 if (send(out_fd, &rh, rh.length, MSG_NOSIGNAL) < 0)
221 static void *serialize_addrinfo(void *p, const struct addrinfo *ai, size_t *length, size_t maxlength) {
222 AddrInfoSerialization s;
228 assert(*length <= maxlength);
230 cnl = ai->ai_canonname ? strlen(ai->ai_canonname)+1 : 0;
231 l = sizeof(AddrInfoSerialization) + ai->ai_addrlen + cnl;
233 if (*length + l > maxlength)
236 s.ai_flags = ai->ai_flags;
237 s.ai_family = ai->ai_family;
238 s.ai_socktype = ai->ai_socktype;
239 s.ai_protocol = ai->ai_protocol;
240 s.ai_addrlen = ai->ai_addrlen;
241 s.canonname_len = cnl;
243 memcpy((uint8_t*) p, &s, sizeof(AddrInfoSerialization));
244 memcpy((uint8_t*) p + sizeof(AddrInfoSerialization), ai->ai_addr, ai->ai_addrlen);
246 if (ai->ai_canonname)
247 memcpy((char*) p + sizeof(AddrInfoSerialization) + ai->ai_addrlen, ai->ai_canonname, cnl);
250 return (uint8_t*) p + l;
253 static int send_addrinfo_reply(
261 AddrInfoResponse resp = {
262 .header.type = RESPONSE_ADDRINFO,
264 .header.length = sizeof(AddrInfoResponse),
267 ._h_errno = _h_errno,
270 struct msghdr mh = {};
273 AddrInfoSerialization ais;
274 uint8_t space[BUFSIZE];
279 if (ret == 0 && ai) {
283 for (k = ai; k; k = k->ai_next) {
284 p = serialize_addrinfo(p, k, &resp.header.length, (uint8_t*) &buffer + BUFSIZE - (uint8_t*) p);
295 iov[0] = (struct iovec) { .iov_base = &resp, .iov_len = sizeof(AddrInfoResponse) };
296 iov[1] = (struct iovec) { .iov_base = &buffer, .iov_len = resp.header.length - sizeof(AddrInfoResponse) };
299 mh.msg_iovlen = ELEMENTSOF(iov);
301 if (sendmsg(out_fd, &mh, MSG_NOSIGNAL) < 0)
307 static int send_nameinfo_reply(
316 NameInfoResponse resp = {
317 .header.type = RESPONSE_NAMEINFO,
321 ._h_errno = _h_errno,
324 struct msghdr mh = {};
330 sl = serv ? strlen(serv)+1 : 0;
331 hl = host ? strlen(host)+1 : 0;
333 resp.header.length = sizeof(NameInfoResponse) + hl + sl;
337 iov[0] = (struct iovec) { .iov_base = &resp, .iov_len = sizeof(NameInfoResponse) };
338 iov[1] = (struct iovec) { .iov_base = (void*) host, .iov_len = hl };
339 iov[2] = (struct iovec) { .iov_base = (void*) serv, .iov_len = sl };
342 mh.msg_iovlen = ELEMENTSOF(iov);
344 if (sendmsg(out_fd, &mh, MSG_NOSIGNAL) < 0)
350 static int send_res_reply(int out_fd, unsigned id, const unsigned char *answer, int ret, int _errno, int _h_errno) {
353 .header.type = RESPONSE_RES,
357 ._h_errno = _h_errno,
360 struct msghdr mh = {};
366 l = ret > 0 ? (size_t) ret : 0;
368 resp.header.length = sizeof(ResResponse) + l;
370 iov[0] = (struct iovec) { .iov_base = &resp, .iov_len = sizeof(ResResponse) };
371 iov[1] = (struct iovec) { .iov_base = (void*) answer, .iov_len = l };
374 mh.msg_iovlen = ELEMENTSOF(iov);
376 if (sendmsg(out_fd, &mh, MSG_NOSIGNAL) < 0)
382 static int handle_request(int out_fd, const Packet *packet, size_t length) {
388 req = &packet->rheader;
390 assert(length >= sizeof(RHeader));
391 assert(length == req->length);
395 case REQUEST_ADDRINFO: {
396 const AddrInfoRequest *ai_req = &packet->addrinfo_request;
397 struct addrinfo hints = {}, *result = NULL;
398 const char *node, *service;
401 assert(length >= sizeof(AddrInfoRequest));
402 assert(length == sizeof(AddrInfoRequest) + ai_req->node_len + ai_req->service_len);
404 hints.ai_flags = ai_req->ai_flags;
405 hints.ai_family = ai_req->ai_family;
406 hints.ai_socktype = ai_req->ai_socktype;
407 hints.ai_protocol = ai_req->ai_protocol;
409 node = ai_req->node_len ? (const char*) ai_req + sizeof(AddrInfoRequest) : NULL;
410 service = ai_req->service_len ? (const char*) ai_req + sizeof(AddrInfoRequest) + ai_req->node_len : NULL;
414 ai_req->hints_valid ? &hints : NULL,
417 /* send_addrinfo_reply() frees result */
418 return send_addrinfo_reply(out_fd, req->id, ret, result, errno, h_errno);
421 case REQUEST_NAMEINFO: {
422 const NameInfoRequest *ni_req = &packet->nameinfo_request;
423 char hostbuf[NI_MAXHOST], servbuf[NI_MAXSERV];
424 union sockaddr_union sa;
427 assert(length >= sizeof(NameInfoRequest));
428 assert(length == sizeof(NameInfoRequest) + ni_req->sockaddr_len);
429 assert(sizeof(sa) >= ni_req->sockaddr_len);
431 memcpy(&sa, (const uint8_t *) ni_req + sizeof(NameInfoRequest), ni_req->sockaddr_len);
433 ret = getnameinfo(&sa.sa, ni_req->sockaddr_len,
434 ni_req->gethost ? hostbuf : NULL, ni_req->gethost ? sizeof(hostbuf) : 0,
435 ni_req->getserv ? servbuf : NULL, ni_req->getserv ? sizeof(servbuf) : 0,
438 return send_nameinfo_reply(out_fd, req->id, ret,
439 ret == 0 && ni_req->gethost ? hostbuf : NULL,
440 ret == 0 && ni_req->getserv ? servbuf : NULL,
444 case REQUEST_RES_QUERY:
445 case REQUEST_RES_SEARCH: {
446 const ResRequest *res_req = &packet->res_request;
449 uint8_t space[BUFSIZE];
454 assert(length >= sizeof(ResRequest));
455 assert(length == sizeof(ResRequest) + res_req->dname_len);
457 dname = (const char *) req + sizeof(ResRequest);
459 if (req->type == REQUEST_RES_QUERY)
460 ret = res_query(dname, res_req->class, res_req->type, (unsigned char *) &answer, BUFSIZE);
462 ret = res_search(dname, res_req->class, res_req->type, (unsigned char *) &answer, BUFSIZE);
464 return send_res_reply(out_fd, req->id, (unsigned char *) &answer, ret, errno, h_errno);
467 case REQUEST_TERMINATE:
472 assert_not_reached("Unknown request");
478 static void* thread_worker(void *p) {
479 sd_resolve *resolve = p;
482 /* No signals in this thread please */
483 assert_se(sigfillset(&fullset) == 0);
484 assert_se(pthread_sigmask(SIG_BLOCK, &fullset, NULL) == 0);
486 /* Assign a pretty name to this thread */
487 prctl(PR_SET_NAME, (unsigned long) "sd-resolve");
489 while (!resolve->dead) {
492 uint8_t space[BUFSIZE];
496 length = recv(resolve->fds[REQUEST_RECV_FD], &buf, sizeof(buf), 0);
509 if (handle_request(resolve->fds[RESPONSE_SEND_FD], &buf.packet, (size_t) length) < 0)
513 send_died(resolve->fds[RESPONSE_SEND_FD]);
518 static int start_threads(sd_resolve *resolve, unsigned extra) {
522 n = resolve->n_queries + extra - resolve->n_done;
523 n = CLAMP(n, WORKERS_MIN, WORKERS_MAX);
525 while (resolve->n_valid_workers < n) {
527 r = pthread_create(&resolve->workers[resolve->n_valid_workers], NULL, thread_worker, resolve);
531 resolve->n_valid_workers ++;
537 static bool resolve_pid_changed(sd_resolve *r) {
540 /* We don't support people creating a resolver and keeping it
541 * around after fork(). Let's complain. */
543 return r->original_pid != getpid();
546 _public_ int sd_resolve_new(sd_resolve **ret) {
547 sd_resolve *resolve = NULL;
550 assert_return(ret, -EINVAL);
552 resolve = new0(sd_resolve, 1);
557 resolve->original_pid = getpid();
559 for (i = 0; i < _FD_MAX; i++)
560 resolve->fds[i] = -1;
562 r = socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds + REQUEST_RECV_FD);
568 r = socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds + RESPONSE_RECV_FD);
574 fd_inc_sndbuf(resolve->fds[REQUEST_SEND_FD], QUERIES_MAX * BUFSIZE);
575 fd_inc_rcvbuf(resolve->fds[REQUEST_RECV_FD], QUERIES_MAX * BUFSIZE);
576 fd_inc_sndbuf(resolve->fds[RESPONSE_SEND_FD], QUERIES_MAX * BUFSIZE);
577 fd_inc_rcvbuf(resolve->fds[RESPONSE_RECV_FD], QUERIES_MAX * BUFSIZE);
579 fd_nonblock(resolve->fds[RESPONSE_RECV_FD], true);
585 sd_resolve_unref(resolve);
589 _public_ int sd_resolve_default(sd_resolve **ret) {
591 static thread_local sd_resolve *default_resolve = NULL;
592 sd_resolve *e = NULL;
596 return !!default_resolve;
598 if (default_resolve) {
599 *ret = sd_resolve_ref(default_resolve);
603 r = sd_resolve_new(&e);
607 e->default_resolve_ptr = &default_resolve;
615 _public_ int sd_resolve_get_tid(sd_resolve *resolve, pid_t *tid) {
616 assert_return(resolve, -EINVAL);
617 assert_return(tid, -EINVAL);
618 assert_return(!resolve_pid_changed(resolve), -ECHILD);
620 if (resolve->tid != 0) {
626 return sd_event_get_tid(resolve->event, tid);
631 static void resolve_free(sd_resolve *resolve) {
637 if (resolve->default_resolve_ptr)
638 *(resolve->default_resolve_ptr) = NULL;
640 resolve->dead = true;
642 sd_resolve_detach_event(resolve);
644 if (resolve->fds[REQUEST_SEND_FD] >= 0) {
647 .type = REQUEST_TERMINATE,
648 .length = sizeof(req)
651 /* Send one termination packet for each worker */
652 for (i = 0; i < resolve->n_valid_workers; i++)
653 send(resolve->fds[REQUEST_SEND_FD], &req, req.length, MSG_NOSIGNAL);
656 /* Now terminate them and wait until they are gone. */
657 for (i = 0; i < resolve->n_valid_workers; i++) {
659 if (pthread_join(resolve->workers[i], NULL) != EINTR)
664 /* Close all communication channels */
665 for (i = 0; i < _FD_MAX; i++)
666 safe_close(resolve->fds[i]);
671 _public_ sd_resolve* sd_resolve_ref(sd_resolve *resolve) {
672 assert_return(resolve, NULL);
674 assert(resolve->n_ref >= 1);
680 _public_ sd_resolve* sd_resolve_unref(sd_resolve *resolve) {
685 assert(resolve->n_ref >= 1);
688 if (resolve->n_ref <= 0)
689 resolve_free(resolve);
694 _public_ int sd_resolve_get_fd(sd_resolve *resolve) {
695 assert_return(resolve, -EINVAL);
696 assert_return(!resolve_pid_changed(resolve), -ECHILD);
698 return resolve->fds[RESPONSE_RECV_FD];
701 _public_ int sd_resolve_get_events(sd_resolve *resolve) {
702 assert_return(resolve, -EINVAL);
703 assert_return(!resolve_pid_changed(resolve), -ECHILD);
705 return resolve->n_queries > resolve->n_done ? POLLIN : 0;
708 _public_ int sd_resolve_get_timeout(sd_resolve *resolve, uint64_t *usec) {
709 assert_return(resolve, -EINVAL);
710 assert_return(usec, -EINVAL);
711 assert_return(!resolve_pid_changed(resolve), -ECHILD);
713 *usec = (uint64_t) -1;
717 static sd_resolve_query *lookup_query(sd_resolve *resolve, unsigned id) {
722 q = resolve->queries[id % QUERIES_MAX];
730 static int complete_query(sd_resolve *resolve, sd_resolve_query *q) {
735 assert(q->resolve == resolve);
740 resolve->current = sd_resolve_query_ref(q);
744 case REQUEST_ADDRINFO:
745 r = getaddrinfo_done(q);
748 case REQUEST_NAMEINFO:
749 r = getnameinfo_done(q);
752 case REQUEST_RES_QUERY:
753 case REQUEST_RES_SEARCH:
754 r = res_query_done(q);
758 assert_not_reached("Cannot complete unknown query type");
761 resolve->current = sd_resolve_query_unref(q);
766 static int unserialize_addrinfo(const void **p, size_t *length, struct addrinfo **ret_ai) {
767 AddrInfoSerialization s;
776 if (*length < sizeof(AddrInfoSerialization))
779 memcpy(&s, *p, sizeof(s));
781 l = sizeof(AddrInfoSerialization) + s.ai_addrlen + s.canonname_len;
785 ai = new0(struct addrinfo, 1);
789 ai->ai_flags = s.ai_flags;
790 ai->ai_family = s.ai_family;
791 ai->ai_socktype = s.ai_socktype;
792 ai->ai_protocol = s.ai_protocol;
793 ai->ai_addrlen = s.ai_addrlen;
795 if (s.ai_addrlen > 0) {
796 ai->ai_addr = memdup((const uint8_t*) *p + sizeof(AddrInfoSerialization), s.ai_addrlen);
803 if (s.canonname_len > 0) {
804 ai->ai_canonname = memdup((const uint8_t*) *p + sizeof(AddrInfoSerialization) + s.ai_addrlen, s.canonname_len);
805 if (!ai->ai_canonname) {
814 *p = ((const uint8_t*) *p) + l;
819 static int handle_response(sd_resolve *resolve, const Packet *packet, size_t length) {
826 resp = &packet->rheader;
828 assert(length >= sizeof(RHeader));
829 assert(length == resp->length);
831 if (resp->type == RESPONSE_DIED) {
832 resolve->dead = true;
836 q = lookup_query(resolve, resp->id);
840 switch (resp->type) {
842 case RESPONSE_ADDRINFO: {
843 const AddrInfoResponse *ai_resp = &packet->addrinfo_response;
846 struct addrinfo *prev = NULL;
848 assert(length >= sizeof(AddrInfoResponse));
849 assert(q->type == REQUEST_ADDRINFO);
851 q->ret = ai_resp->ret;
852 q->_errno = ai_resp->_errno;
853 q->_h_errno = ai_resp->_h_errno;
855 l = length - sizeof(AddrInfoResponse);
856 p = (const uint8_t*) resp + sizeof(AddrInfoResponse);
859 struct addrinfo *ai = NULL;
861 r = unserialize_addrinfo(&p, &l, &ai);
866 freeaddrinfo(q->addrinfo);
879 return complete_query(resolve, q);
882 case RESPONSE_NAMEINFO: {
883 const NameInfoResponse *ni_resp = &packet->nameinfo_response;
885 assert(length >= sizeof(NameInfoResponse));
886 assert(q->type == REQUEST_NAMEINFO);
888 q->ret = ni_resp->ret;
889 q->_errno = ni_resp->_errno;
890 q->_h_errno = ni_resp->_h_errno;
892 if (ni_resp->hostlen > 0) {
893 q->host = strndup((const char*) ni_resp + sizeof(NameInfoResponse), ni_resp->hostlen-1);
901 if (ni_resp->servlen > 0) {
902 q->serv = strndup((const char*) ni_resp + sizeof(NameInfoResponse) + ni_resp->hostlen, ni_resp->servlen-1);
910 return complete_query(resolve, q);
914 const ResResponse *res_resp = &packet->res_response;
916 assert(length >= sizeof(ResResponse));
917 assert(q->type == REQUEST_RES_QUERY || q->type == REQUEST_RES_SEARCH);
919 q->ret = res_resp->ret;
920 q->_errno = res_resp->_errno;
921 q->_h_errno = res_resp->_h_errno;
923 if (res_resp->ret >= 0) {
924 q->answer = memdup((const char *)resp + sizeof(ResResponse), res_resp->ret);
932 return complete_query(resolve, q);
940 _public_ int sd_resolve_process(sd_resolve *resolve) {
941 RESOLVE_DONT_DESTROY(resolve);
945 uint8_t space[BUFSIZE];
950 assert_return(resolve, -EINVAL);
951 assert_return(!resolve_pid_changed(resolve), -ECHILD);
953 /* We don't allow recursively invoking sd_resolve_process(). */
954 assert_return(!resolve->current, -EBUSY);
956 l = recv(resolve->fds[RESPONSE_RECV_FD], &buf, sizeof(buf), 0);
964 return -ECONNREFUSED;
966 r = handle_response(resolve, &buf.packet, (size_t) l);
973 _public_ int sd_resolve_wait(sd_resolve *resolve, uint64_t timeout_usec) {
976 assert_return(resolve, -EINVAL);
977 assert_return(!resolve_pid_changed(resolve), -ECHILD);
979 if (resolve->n_done >= resolve->n_queries)
983 r = fd_wait_for_event(resolve->fds[RESPONSE_RECV_FD], POLLIN, timeout_usec);
984 } while (r == -EINTR);
989 return sd_resolve_process(resolve);
992 static int alloc_query(sd_resolve *resolve, sd_resolve_query **_q) {
999 if (resolve->n_queries >= QUERIES_MAX)
1002 r = start_threads(resolve, 1);
1006 while (resolve->queries[resolve->current_index]) {
1007 resolve->current_index++;
1008 resolve->current_id++;
1010 resolve->current_index %= QUERIES_MAX;
1013 q = resolve->queries[resolve->current_index] = new0(sd_resolve_query, 1);
1018 q->resolve = sd_resolve_ref(resolve);
1019 q->id = resolve->current_id;
1021 resolve->n_queries++;
1027 _public_ int sd_resolve_getaddrinfo(
1028 sd_resolve *resolve,
1029 sd_resolve_query **_q,
1030 const char *node, const char *service,
1031 const struct addrinfo *hints,
1032 sd_resolve_getaddrinfo_handler_t callback, void *userdata) {
1034 AddrInfoRequest req = {};
1035 struct msghdr mh = {};
1036 struct iovec iov[3];
1037 sd_resolve_query *q;
1040 assert_return(resolve, -EINVAL);
1041 assert_return(_q, -EINVAL);
1042 assert_return(node || service, -EINVAL);
1043 assert_return(callback, -EINVAL);
1044 assert_return(!resolve_pid_changed(resolve), -ECHILD);
1046 r = alloc_query(resolve, &q);
1050 q->type = REQUEST_ADDRINFO;
1051 q->getaddrinfo_handler = callback;
1052 q->userdata = userdata;
1054 req.node_len = node ? strlen(node)+1 : 0;
1055 req.service_len = service ? strlen(service)+1 : 0;
1057 req.header.id = q->id;
1058 req.header.type = REQUEST_ADDRINFO;
1059 req.header.length = sizeof(AddrInfoRequest) + req.node_len + req.service_len;
1062 req.hints_valid = true;
1063 req.ai_flags = hints->ai_flags;
1064 req.ai_family = hints->ai_family;
1065 req.ai_socktype = hints->ai_socktype;
1066 req.ai_protocol = hints->ai_protocol;
1069 iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(AddrInfoRequest) };
1071 iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = (void*) node, .iov_len = req.node_len };
1073 iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = (void*) service, .iov_len = req.service_len };
1076 if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) {
1077 sd_resolve_query_unref(q);
1085 static int getaddrinfo_done(sd_resolve_query* q) {
1088 assert(q->getaddrinfo_handler);
1091 h_errno = q->_h_errno;
1093 return q->getaddrinfo_handler(q, q->ret, q->addrinfo, q->userdata);
1096 _public_ int sd_resolve_getnameinfo(
1097 sd_resolve *resolve,
1098 sd_resolve_query**_q,
1099 const struct sockaddr *sa, socklen_t salen,
1102 sd_resolve_getnameinfo_handler_t callback,
1105 NameInfoRequest req = {};
1106 struct msghdr mh = {};
1107 struct iovec iov[2];
1108 sd_resolve_query *q;
1111 assert_return(resolve, -EINVAL);
1112 assert_return(_q, -EINVAL);
1113 assert_return(sa, -EINVAL);
1114 assert_return(salen >= sizeof(struct sockaddr), -EINVAL);
1115 assert_return(salen <= sizeof(union sockaddr_union), -EINVAL);
1116 assert_return((get & ~SD_RESOLVE_GET_BOTH) == 0, -EINVAL);
1117 assert_return(callback, -EINVAL);
1118 assert_return(!resolve_pid_changed(resolve), -ECHILD);
1120 r = alloc_query(resolve, &q);
1124 q->type = REQUEST_NAMEINFO;
1125 q->getnameinfo_handler = callback;
1126 q->userdata = userdata;
1128 req.header.id = q->id;
1129 req.header.type = REQUEST_NAMEINFO;
1130 req.header.length = sizeof(NameInfoRequest) + salen;
1133 req.sockaddr_len = salen;
1134 req.gethost = !!(get & SD_RESOLVE_GET_HOST);
1135 req.getserv = !!(get & SD_RESOLVE_GET_SERVICE);
1137 iov[0] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(NameInfoRequest) };
1138 iov[1] = (struct iovec) { .iov_base = (void*) sa, .iov_len = salen };
1143 if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) {
1144 sd_resolve_query_unref(q);
1152 static int getnameinfo_done(sd_resolve_query *q) {
1156 assert(q->getnameinfo_handler);
1159 h_errno= q->_h_errno;
1161 return q->getnameinfo_handler(q, q->ret, q->host, q->serv, q->userdata);
1164 static int resolve_res(
1165 sd_resolve *resolve,
1166 sd_resolve_query **_q,
1169 int class, int type,
1170 sd_resolve_res_handler_t callback, void *userdata) {
1172 struct msghdr mh = {};
1173 struct iovec iov[2];
1174 ResRequest req = {};
1175 sd_resolve_query *q;
1178 assert_return(resolve, -EINVAL);
1179 assert_return(_q, -EINVAL);
1180 assert_return(dname, -EINVAL);
1181 assert_return(callback, -EINVAL);
1182 assert_return(!resolve_pid_changed(resolve), -ECHILD);
1184 r = alloc_query(resolve, &q);
1189 q->res_handler = callback;
1190 q->userdata = userdata;
1192 req.dname_len = strlen(dname) + 1;
1196 req.header.id = q->id;
1197 req.header.type = qtype;
1198 req.header.length = sizeof(ResRequest) + req.dname_len;
1200 iov[0] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(ResRequest) };
1201 iov[1] = (struct iovec) { .iov_base = (void*) dname, .iov_len = req.dname_len };
1206 if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) {
1207 sd_resolve_query_unref(q);
1215 _public_ int sd_resolve_res_query(sd_resolve *resolve, sd_resolve_query** q, const char *dname, int class, int type, sd_resolve_res_handler_t callback, void *userdata) {
1216 return resolve_res(resolve, q, REQUEST_RES_QUERY, dname, class, type, callback, userdata);
1219 _public_ int sd_resolve_res_search(sd_resolve *resolve, sd_resolve_query** q, const char *dname, int class, int type, sd_resolve_res_handler_t callback, void *userdata) {
1220 return resolve_res(resolve, q, REQUEST_RES_SEARCH, dname, class, type, callback, userdata);
1223 static int res_query_done(sd_resolve_query* q) {
1226 assert(q->res_handler);
1229 h_errno = q->_h_errno;
1231 return q->res_handler(q, q->ret, q->answer, q->userdata);
1234 _public_ sd_resolve_query* sd_resolve_query_ref(sd_resolve_query *q) {
1235 assert_return(q, NULL);
1237 assert(q->n_ref >= 1);
1243 static void resolve_freeaddrinfo(struct addrinfo *ai) {
1245 struct addrinfo *next = ai->ai_next;
1248 free(ai->ai_canonname);
1254 static void resolve_query_free(sd_resolve_query *q) {
1259 assert(q->resolve->n_queries > 0);
1262 assert(q->resolve->n_done > 0);
1263 q->resolve->n_done--;
1266 i = q->id % QUERIES_MAX;
1267 assert(q->resolve->queries[i] == q);
1268 q->resolve->queries[i] = NULL;
1269 q->resolve->n_queries--;
1270 sd_resolve_unref(q->resolve);
1272 resolve_freeaddrinfo(q->addrinfo);
1279 _public_ sd_resolve_query* sd_resolve_query_unref(sd_resolve_query* q) {
1283 assert(q->n_ref >= 1);
1287 resolve_query_free(q);
1292 _public_ int sd_resolve_query_is_done(sd_resolve_query *q) {
1293 assert_return(q, -EINVAL);
1294 assert_return(!resolve_pid_changed(q->resolve), -ECHILD);
1299 _public_ void* sd_resolve_query_set_userdata(sd_resolve_query *q, void *userdata) {
1302 assert_return(q, NULL);
1303 assert_return(!resolve_pid_changed(q->resolve), NULL);
1306 q->userdata = userdata;
1311 _public_ void* sd_resolve_query_get_userdata(sd_resolve_query *q) {
1312 assert_return(q, NULL);
1313 assert_return(!resolve_pid_changed(q->resolve), NULL);
1318 _public_ sd_resolve *sd_resolve_query_get_resolve(sd_resolve_query *q) {
1319 assert_return(q, NULL);
1320 assert_return(!resolve_pid_changed(q->resolve), NULL);
1325 static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
1326 sd_resolve *resolve = userdata;
1331 r = sd_resolve_process(resolve);
1338 _public_ int sd_resolve_attach_event(sd_resolve *resolve, sd_event *event, int priority) {
1341 assert_return(resolve, -EINVAL);
1342 assert_return(!resolve->event, -EBUSY);
1344 assert(!resolve->event_source);
1347 resolve->event = sd_event_ref(event);
1349 r = sd_event_default(&resolve->event);
1354 r = sd_event_add_io(resolve->event, &resolve->event_source, resolve->fds[RESPONSE_RECV_FD], POLLIN, io_callback, resolve);
1358 r = sd_event_source_set_priority(resolve->event_source, priority);
1365 sd_resolve_detach_event(resolve);
1369 _public_ int sd_resolve_detach_event(sd_resolve *resolve) {
1370 assert_return(resolve, -EINVAL);
1372 if (!resolve->event)
1375 if (resolve->event_source) {
1376 sd_event_source_set_enabled(resolve->event_source, SD_EVENT_OFF);
1377 resolve->event_source = sd_event_source_unref(resolve->event_source);
1380 resolve->event = sd_event_unref(resolve->event);
1384 _public_ sd_event *sd_resolve_get_event(sd_resolve *resolve) {
1385 assert_return(resolve, NULL);
1387 return resolve->event;