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* query_array[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;
100 LIST_HEAD(sd_resolve_query, queries);
103 struct sd_resolve_query {
116 struct addrinfo *addrinfo;
118 unsigned char *answer;
121 sd_resolve_getaddrinfo_handler_t getaddrinfo_handler;
122 sd_resolve_getnameinfo_handler_t getnameinfo_handler;
123 sd_resolve_res_handler_t res_handler;
128 LIST_FIELDS(sd_resolve_query, queries);
131 typedef struct RHeader {
137 typedef struct AddrInfoRequest {
138 struct RHeader header;
144 size_t node_len, service_len;
147 typedef struct AddrInfoResponse {
148 struct RHeader header;
152 /* followed by addrinfo_serialization[] */
155 typedef struct AddrInfoSerialization {
161 size_t canonname_len;
162 /* Followed by ai_addr amd ai_canonname with variable lengths */
163 } AddrInfoSerialization;
165 typedef struct NameInfoRequest {
166 struct RHeader header;
168 socklen_t sockaddr_len;
169 bool gethost:1, getserv:1;
172 typedef struct NameInfoResponse {
173 struct RHeader header;
174 size_t hostlen, servlen;
180 typedef struct ResRequest {
181 struct RHeader header;
187 typedef struct ResResponse {
188 struct RHeader header;
194 typedef union Packet {
196 AddrInfoRequest addrinfo_request;
197 AddrInfoResponse addrinfo_response;
198 NameInfoRequest nameinfo_request;
199 NameInfoResponse nameinfo_response;
200 ResRequest res_request;
201 ResResponse res_response;
204 static int getaddrinfo_done(sd_resolve_query* q);
205 static int getnameinfo_done(sd_resolve_query *q);
206 static int res_query_done(sd_resolve_query* q);
208 static void resolve_query_disconnect(sd_resolve_query *q);
210 #define RESOLVE_DONT_DESTROY(resolve) \
211 _cleanup_resolve_unref_ _unused_ sd_resolve *_dont_destroy_##resolve = sd_resolve_ref(resolve)
213 static int send_died(int out_fd) {
216 .type = RESPONSE_DIED,
217 .length = sizeof(RHeader),
222 if (send(out_fd, &rh, rh.length, MSG_NOSIGNAL) < 0)
228 static void *serialize_addrinfo(void *p, const struct addrinfo *ai, size_t *length, size_t maxlength) {
229 AddrInfoSerialization s;
235 assert(*length <= maxlength);
237 cnl = ai->ai_canonname ? strlen(ai->ai_canonname)+1 : 0;
238 l = sizeof(AddrInfoSerialization) + ai->ai_addrlen + cnl;
240 if (*length + l > maxlength)
243 s.ai_flags = ai->ai_flags;
244 s.ai_family = ai->ai_family;
245 s.ai_socktype = ai->ai_socktype;
246 s.ai_protocol = ai->ai_protocol;
247 s.ai_addrlen = ai->ai_addrlen;
248 s.canonname_len = cnl;
250 memcpy((uint8_t*) p, &s, sizeof(AddrInfoSerialization));
251 memcpy((uint8_t*) p + sizeof(AddrInfoSerialization), ai->ai_addr, ai->ai_addrlen);
253 if (ai->ai_canonname)
254 memcpy((char*) p + sizeof(AddrInfoSerialization) + ai->ai_addrlen, ai->ai_canonname, cnl);
257 return (uint8_t*) p + l;
260 static int send_addrinfo_reply(
268 AddrInfoResponse resp = {
269 .header.type = RESPONSE_ADDRINFO,
271 .header.length = sizeof(AddrInfoResponse),
274 ._h_errno = _h_errno,
277 struct msghdr mh = {};
280 AddrInfoSerialization ais;
281 uint8_t space[BUFSIZE];
286 if (ret == 0 && ai) {
290 for (k = ai; k; k = k->ai_next) {
291 p = serialize_addrinfo(p, k, &resp.header.length, (uint8_t*) &buffer + BUFSIZE - (uint8_t*) p);
302 iov[0] = (struct iovec) { .iov_base = &resp, .iov_len = sizeof(AddrInfoResponse) };
303 iov[1] = (struct iovec) { .iov_base = &buffer, .iov_len = resp.header.length - sizeof(AddrInfoResponse) };
306 mh.msg_iovlen = ELEMENTSOF(iov);
308 if (sendmsg(out_fd, &mh, MSG_NOSIGNAL) < 0)
314 static int send_nameinfo_reply(
323 NameInfoResponse resp = {
324 .header.type = RESPONSE_NAMEINFO,
328 ._h_errno = _h_errno,
331 struct msghdr mh = {};
337 sl = serv ? strlen(serv)+1 : 0;
338 hl = host ? strlen(host)+1 : 0;
340 resp.header.length = sizeof(NameInfoResponse) + hl + sl;
344 iov[0] = (struct iovec) { .iov_base = &resp, .iov_len = sizeof(NameInfoResponse) };
345 iov[1] = (struct iovec) { .iov_base = (void*) host, .iov_len = hl };
346 iov[2] = (struct iovec) { .iov_base = (void*) serv, .iov_len = sl };
349 mh.msg_iovlen = ELEMENTSOF(iov);
351 if (sendmsg(out_fd, &mh, MSG_NOSIGNAL) < 0)
357 static int send_res_reply(int out_fd, unsigned id, const unsigned char *answer, int ret, int _errno, int _h_errno) {
360 .header.type = RESPONSE_RES,
364 ._h_errno = _h_errno,
367 struct msghdr mh = {};
373 l = ret > 0 ? (size_t) ret : 0;
375 resp.header.length = sizeof(ResResponse) + l;
377 iov[0] = (struct iovec) { .iov_base = &resp, .iov_len = sizeof(ResResponse) };
378 iov[1] = (struct iovec) { .iov_base = (void*) answer, .iov_len = l };
381 mh.msg_iovlen = ELEMENTSOF(iov);
383 if (sendmsg(out_fd, &mh, MSG_NOSIGNAL) < 0)
389 static int handle_request(int out_fd, const Packet *packet, size_t length) {
395 req = &packet->rheader;
397 assert(length >= sizeof(RHeader));
398 assert(length == req->length);
402 case REQUEST_ADDRINFO: {
403 const AddrInfoRequest *ai_req = &packet->addrinfo_request;
404 struct addrinfo hints = {}, *result = NULL;
405 const char *node, *service;
408 assert(length >= sizeof(AddrInfoRequest));
409 assert(length == sizeof(AddrInfoRequest) + ai_req->node_len + ai_req->service_len);
411 hints.ai_flags = ai_req->ai_flags;
412 hints.ai_family = ai_req->ai_family;
413 hints.ai_socktype = ai_req->ai_socktype;
414 hints.ai_protocol = ai_req->ai_protocol;
416 node = ai_req->node_len ? (const char*) ai_req + sizeof(AddrInfoRequest) : NULL;
417 service = ai_req->service_len ? (const char*) ai_req + sizeof(AddrInfoRequest) + ai_req->node_len : NULL;
421 ai_req->hints_valid ? &hints : NULL,
424 /* send_addrinfo_reply() frees result */
425 return send_addrinfo_reply(out_fd, req->id, ret, result, errno, h_errno);
428 case REQUEST_NAMEINFO: {
429 const NameInfoRequest *ni_req = &packet->nameinfo_request;
430 char hostbuf[NI_MAXHOST], servbuf[NI_MAXSERV];
431 union sockaddr_union sa;
434 assert(length >= sizeof(NameInfoRequest));
435 assert(length == sizeof(NameInfoRequest) + ni_req->sockaddr_len);
436 assert(sizeof(sa) >= ni_req->sockaddr_len);
438 memcpy(&sa, (const uint8_t *) ni_req + sizeof(NameInfoRequest), ni_req->sockaddr_len);
440 ret = getnameinfo(&sa.sa, ni_req->sockaddr_len,
441 ni_req->gethost ? hostbuf : NULL, ni_req->gethost ? sizeof(hostbuf) : 0,
442 ni_req->getserv ? servbuf : NULL, ni_req->getserv ? sizeof(servbuf) : 0,
445 return send_nameinfo_reply(out_fd, req->id, ret,
446 ret == 0 && ni_req->gethost ? hostbuf : NULL,
447 ret == 0 && ni_req->getserv ? servbuf : NULL,
451 case REQUEST_RES_QUERY:
452 case REQUEST_RES_SEARCH: {
453 const ResRequest *res_req = &packet->res_request;
456 uint8_t space[BUFSIZE];
461 assert(length >= sizeof(ResRequest));
462 assert(length == sizeof(ResRequest) + res_req->dname_len);
464 dname = (const char *) req + sizeof(ResRequest);
466 if (req->type == REQUEST_RES_QUERY)
467 ret = res_query(dname, res_req->class, res_req->type, (unsigned char *) &answer, BUFSIZE);
469 ret = res_search(dname, res_req->class, res_req->type, (unsigned char *) &answer, BUFSIZE);
471 return send_res_reply(out_fd, req->id, (unsigned char *) &answer, ret, errno, h_errno);
474 case REQUEST_TERMINATE:
479 assert_not_reached("Unknown request");
485 static void* thread_worker(void *p) {
486 sd_resolve *resolve = p;
489 /* No signals in this thread please */
490 assert_se(sigfillset(&fullset) == 0);
491 assert_se(pthread_sigmask(SIG_BLOCK, &fullset, NULL) == 0);
493 /* Assign a pretty name to this thread */
494 prctl(PR_SET_NAME, (unsigned long) "sd-resolve");
496 while (!resolve->dead) {
499 uint8_t space[BUFSIZE];
503 length = recv(resolve->fds[REQUEST_RECV_FD], &buf, sizeof(buf), 0);
516 if (handle_request(resolve->fds[RESPONSE_SEND_FD], &buf.packet, (size_t) length) < 0)
520 send_died(resolve->fds[RESPONSE_SEND_FD]);
525 static int start_threads(sd_resolve *resolve, unsigned extra) {
529 n = resolve->n_queries + extra - resolve->n_done;
530 n = CLAMP(n, WORKERS_MIN, WORKERS_MAX);
532 while (resolve->n_valid_workers < n) {
534 r = pthread_create(&resolve->workers[resolve->n_valid_workers], NULL, thread_worker, resolve);
538 resolve->n_valid_workers ++;
544 static bool resolve_pid_changed(sd_resolve *r) {
547 /* We don't support people creating a resolver and keeping it
548 * around after fork(). Let's complain. */
550 return r->original_pid != getpid();
553 _public_ int sd_resolve_new(sd_resolve **ret) {
554 sd_resolve *resolve = NULL;
557 assert_return(ret, -EINVAL);
559 resolve = new0(sd_resolve, 1);
564 resolve->original_pid = getpid();
566 for (i = 0; i < _FD_MAX; i++)
567 resolve->fds[i] = -1;
569 r = socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds + REQUEST_RECV_FD);
575 r = socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds + RESPONSE_RECV_FD);
581 fd_inc_sndbuf(resolve->fds[REQUEST_SEND_FD], QUERIES_MAX * BUFSIZE);
582 fd_inc_rcvbuf(resolve->fds[REQUEST_RECV_FD], QUERIES_MAX * BUFSIZE);
583 fd_inc_sndbuf(resolve->fds[RESPONSE_SEND_FD], QUERIES_MAX * BUFSIZE);
584 fd_inc_rcvbuf(resolve->fds[RESPONSE_RECV_FD], QUERIES_MAX * BUFSIZE);
586 fd_nonblock(resolve->fds[RESPONSE_RECV_FD], true);
592 sd_resolve_unref(resolve);
596 _public_ int sd_resolve_default(sd_resolve **ret) {
598 static thread_local sd_resolve *default_resolve = NULL;
599 sd_resolve *e = NULL;
603 return !!default_resolve;
605 if (default_resolve) {
606 *ret = sd_resolve_ref(default_resolve);
610 r = sd_resolve_new(&e);
614 e->default_resolve_ptr = &default_resolve;
622 _public_ int sd_resolve_get_tid(sd_resolve *resolve, pid_t *tid) {
623 assert_return(resolve, -EINVAL);
624 assert_return(tid, -EINVAL);
625 assert_return(!resolve_pid_changed(resolve), -ECHILD);
627 if (resolve->tid != 0) {
633 return sd_event_get_tid(resolve->event, tid);
638 static void resolve_free(sd_resolve *resolve) {
645 while ((q = resolve->queries)) {
647 resolve_query_disconnect(q);
648 sd_resolve_query_unref(q);
651 if (resolve->default_resolve_ptr)
652 *(resolve->default_resolve_ptr) = NULL;
654 resolve->dead = true;
656 sd_resolve_detach_event(resolve);
658 if (resolve->fds[REQUEST_SEND_FD] >= 0) {
661 .type = REQUEST_TERMINATE,
662 .length = sizeof(req)
665 /* Send one termination packet for each worker */
666 for (i = 0; i < resolve->n_valid_workers; i++)
667 send(resolve->fds[REQUEST_SEND_FD], &req, req.length, MSG_NOSIGNAL);
670 /* Now terminate them and wait until they are gone. */
671 for (i = 0; i < resolve->n_valid_workers; i++) {
673 if (pthread_join(resolve->workers[i], NULL) != EINTR)
678 /* Close all communication channels */
679 for (i = 0; i < _FD_MAX; i++)
680 safe_close(resolve->fds[i]);
685 _public_ sd_resolve* sd_resolve_ref(sd_resolve *resolve) {
686 assert_return(resolve, NULL);
688 assert(resolve->n_ref >= 1);
694 _public_ sd_resolve* sd_resolve_unref(sd_resolve *resolve) {
699 assert(resolve->n_ref >= 1);
702 if (resolve->n_ref <= 0)
703 resolve_free(resolve);
708 _public_ int sd_resolve_get_fd(sd_resolve *resolve) {
709 assert_return(resolve, -EINVAL);
710 assert_return(!resolve_pid_changed(resolve), -ECHILD);
712 return resolve->fds[RESPONSE_RECV_FD];
715 _public_ int sd_resolve_get_events(sd_resolve *resolve) {
716 assert_return(resolve, -EINVAL);
717 assert_return(!resolve_pid_changed(resolve), -ECHILD);
719 return resolve->n_queries > resolve->n_done ? POLLIN : 0;
722 _public_ int sd_resolve_get_timeout(sd_resolve *resolve, uint64_t *usec) {
723 assert_return(resolve, -EINVAL);
724 assert_return(usec, -EINVAL);
725 assert_return(!resolve_pid_changed(resolve), -ECHILD);
727 *usec = (uint64_t) -1;
731 static sd_resolve_query *lookup_query(sd_resolve *resolve, unsigned id) {
736 q = resolve->query_array[id % QUERIES_MAX];
744 static int complete_query(sd_resolve *resolve, sd_resolve_query *q) {
749 assert(q->resolve == resolve);
754 resolve->current = sd_resolve_query_ref(q);
758 case REQUEST_ADDRINFO:
759 r = getaddrinfo_done(q);
762 case REQUEST_NAMEINFO:
763 r = getnameinfo_done(q);
766 case REQUEST_RES_QUERY:
767 case REQUEST_RES_SEARCH:
768 r = res_query_done(q);
772 assert_not_reached("Cannot complete unknown query type");
775 resolve->current = sd_resolve_query_unref(q);
778 resolve_query_disconnect(q);
779 sd_resolve_query_unref(q);
785 static int unserialize_addrinfo(const void **p, size_t *length, struct addrinfo **ret_ai) {
786 AddrInfoSerialization s;
795 if (*length < sizeof(AddrInfoSerialization))
798 memcpy(&s, *p, sizeof(s));
800 l = sizeof(AddrInfoSerialization) + s.ai_addrlen + s.canonname_len;
804 ai = new0(struct addrinfo, 1);
808 ai->ai_flags = s.ai_flags;
809 ai->ai_family = s.ai_family;
810 ai->ai_socktype = s.ai_socktype;
811 ai->ai_protocol = s.ai_protocol;
812 ai->ai_addrlen = s.ai_addrlen;
814 if (s.ai_addrlen > 0) {
815 ai->ai_addr = memdup((const uint8_t*) *p + sizeof(AddrInfoSerialization), s.ai_addrlen);
822 if (s.canonname_len > 0) {
823 ai->ai_canonname = memdup((const uint8_t*) *p + sizeof(AddrInfoSerialization) + s.ai_addrlen, s.canonname_len);
824 if (!ai->ai_canonname) {
833 *p = ((const uint8_t*) *p) + l;
838 static int handle_response(sd_resolve *resolve, const Packet *packet, size_t length) {
845 resp = &packet->rheader;
847 assert(length >= sizeof(RHeader));
848 assert(length == resp->length);
850 if (resp->type == RESPONSE_DIED) {
851 resolve->dead = true;
855 q = lookup_query(resolve, resp->id);
859 switch (resp->type) {
861 case RESPONSE_ADDRINFO: {
862 const AddrInfoResponse *ai_resp = &packet->addrinfo_response;
865 struct addrinfo *prev = NULL;
867 assert(length >= sizeof(AddrInfoResponse));
868 assert(q->type == REQUEST_ADDRINFO);
870 q->ret = ai_resp->ret;
871 q->_errno = ai_resp->_errno;
872 q->_h_errno = ai_resp->_h_errno;
874 l = length - sizeof(AddrInfoResponse);
875 p = (const uint8_t*) resp + sizeof(AddrInfoResponse);
878 struct addrinfo *ai = NULL;
880 r = unserialize_addrinfo(&p, &l, &ai);
885 freeaddrinfo(q->addrinfo);
898 return complete_query(resolve, q);
901 case RESPONSE_NAMEINFO: {
902 const NameInfoResponse *ni_resp = &packet->nameinfo_response;
904 assert(length >= sizeof(NameInfoResponse));
905 assert(q->type == REQUEST_NAMEINFO);
907 q->ret = ni_resp->ret;
908 q->_errno = ni_resp->_errno;
909 q->_h_errno = ni_resp->_h_errno;
911 if (ni_resp->hostlen > 0) {
912 q->host = strndup((const char*) ni_resp + sizeof(NameInfoResponse), ni_resp->hostlen-1);
920 if (ni_resp->servlen > 0) {
921 q->serv = strndup((const char*) ni_resp + sizeof(NameInfoResponse) + ni_resp->hostlen, ni_resp->servlen-1);
929 return complete_query(resolve, q);
933 const ResResponse *res_resp = &packet->res_response;
935 assert(length >= sizeof(ResResponse));
936 assert(q->type == REQUEST_RES_QUERY || q->type == REQUEST_RES_SEARCH);
938 q->ret = res_resp->ret;
939 q->_errno = res_resp->_errno;
940 q->_h_errno = res_resp->_h_errno;
942 if (res_resp->ret >= 0) {
943 q->answer = memdup((const char *)resp + sizeof(ResResponse), res_resp->ret);
951 return complete_query(resolve, q);
959 _public_ int sd_resolve_process(sd_resolve *resolve) {
960 RESOLVE_DONT_DESTROY(resolve);
964 uint8_t space[BUFSIZE];
969 assert_return(resolve, -EINVAL);
970 assert_return(!resolve_pid_changed(resolve), -ECHILD);
972 /* We don't allow recursively invoking sd_resolve_process(). */
973 assert_return(!resolve->current, -EBUSY);
975 l = recv(resolve->fds[RESPONSE_RECV_FD], &buf, sizeof(buf), 0);
983 return -ECONNREFUSED;
985 r = handle_response(resolve, &buf.packet, (size_t) l);
992 _public_ int sd_resolve_wait(sd_resolve *resolve, uint64_t timeout_usec) {
995 assert_return(resolve, -EINVAL);
996 assert_return(!resolve_pid_changed(resolve), -ECHILD);
998 if (resolve->n_done >= resolve->n_queries)
1002 r = fd_wait_for_event(resolve->fds[RESPONSE_RECV_FD], POLLIN, timeout_usec);
1003 } while (r == -EINTR);
1008 return sd_resolve_process(resolve);
1011 static int alloc_query(sd_resolve *resolve, bool floating, sd_resolve_query **_q) {
1012 sd_resolve_query *q;
1018 if (resolve->n_queries >= QUERIES_MAX)
1021 r = start_threads(resolve, 1);
1025 while (resolve->query_array[resolve->current_index]) {
1026 resolve->current_index++;
1027 resolve->current_id++;
1029 resolve->current_index %= QUERIES_MAX;
1032 q = resolve->query_array[resolve->current_index] = new0(sd_resolve_query, 1);
1037 q->resolve = resolve;
1038 q->floating = floating;
1039 q->id = resolve->current_id;
1042 sd_resolve_ref(resolve);
1044 LIST_PREPEND(queries, resolve->queries, q);
1045 resolve->n_queries++;
1051 _public_ int sd_resolve_getaddrinfo(
1052 sd_resolve *resolve,
1053 sd_resolve_query **_q,
1054 const char *node, const char *service,
1055 const struct addrinfo *hints,
1056 sd_resolve_getaddrinfo_handler_t callback, void *userdata) {
1058 AddrInfoRequest req = {};
1059 struct msghdr mh = {};
1060 struct iovec iov[3];
1061 sd_resolve_query *q;
1064 assert_return(resolve, -EINVAL);
1065 assert_return(node || service, -EINVAL);
1066 assert_return(callback, -EINVAL);
1067 assert_return(!resolve_pid_changed(resolve), -ECHILD);
1069 r = alloc_query(resolve, !_q, &q);
1073 q->type = REQUEST_ADDRINFO;
1074 q->getaddrinfo_handler = callback;
1075 q->userdata = userdata;
1077 req.node_len = node ? strlen(node)+1 : 0;
1078 req.service_len = service ? strlen(service)+1 : 0;
1080 req.header.id = q->id;
1081 req.header.type = REQUEST_ADDRINFO;
1082 req.header.length = sizeof(AddrInfoRequest) + req.node_len + req.service_len;
1085 req.hints_valid = true;
1086 req.ai_flags = hints->ai_flags;
1087 req.ai_family = hints->ai_family;
1088 req.ai_socktype = hints->ai_socktype;
1089 req.ai_protocol = hints->ai_protocol;
1092 iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(AddrInfoRequest) };
1094 iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = (void*) node, .iov_len = req.node_len };
1096 iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = (void*) service, .iov_len = req.service_len };
1099 if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) {
1100 sd_resolve_query_unref(q);
1110 static int getaddrinfo_done(sd_resolve_query* q) {
1113 assert(q->getaddrinfo_handler);
1116 h_errno = q->_h_errno;
1118 return q->getaddrinfo_handler(q, q->ret, q->addrinfo, q->userdata);
1121 _public_ int sd_resolve_getnameinfo(
1122 sd_resolve *resolve,
1123 sd_resolve_query**_q,
1124 const struct sockaddr *sa, socklen_t salen,
1127 sd_resolve_getnameinfo_handler_t callback,
1130 NameInfoRequest req = {};
1131 struct msghdr mh = {};
1132 struct iovec iov[2];
1133 sd_resolve_query *q;
1136 assert_return(resolve, -EINVAL);
1137 assert_return(sa, -EINVAL);
1138 assert_return(salen >= sizeof(struct sockaddr), -EINVAL);
1139 assert_return(salen <= sizeof(union sockaddr_union), -EINVAL);
1140 assert_return((get & ~SD_RESOLVE_GET_BOTH) == 0, -EINVAL);
1141 assert_return(callback, -EINVAL);
1142 assert_return(!resolve_pid_changed(resolve), -ECHILD);
1144 r = alloc_query(resolve, !_q, &q);
1148 q->type = REQUEST_NAMEINFO;
1149 q->getnameinfo_handler = callback;
1150 q->userdata = userdata;
1152 req.header.id = q->id;
1153 req.header.type = REQUEST_NAMEINFO;
1154 req.header.length = sizeof(NameInfoRequest) + salen;
1157 req.sockaddr_len = salen;
1158 req.gethost = !!(get & SD_RESOLVE_GET_HOST);
1159 req.getserv = !!(get & SD_RESOLVE_GET_SERVICE);
1161 iov[0] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(NameInfoRequest) };
1162 iov[1] = (struct iovec) { .iov_base = (void*) sa, .iov_len = salen };
1167 if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) {
1168 sd_resolve_query_unref(q);
1178 static int getnameinfo_done(sd_resolve_query *q) {
1182 assert(q->getnameinfo_handler);
1185 h_errno= q->_h_errno;
1187 return q->getnameinfo_handler(q, q->ret, q->host, q->serv, q->userdata);
1190 static int resolve_res(
1191 sd_resolve *resolve,
1192 sd_resolve_query **_q,
1195 int class, int type,
1196 sd_resolve_res_handler_t callback, void *userdata) {
1198 struct msghdr mh = {};
1199 struct iovec iov[2];
1200 ResRequest req = {};
1201 sd_resolve_query *q;
1204 assert_return(resolve, -EINVAL);
1205 assert_return(dname, -EINVAL);
1206 assert_return(callback, -EINVAL);
1207 assert_return(!resolve_pid_changed(resolve), -ECHILD);
1209 r = alloc_query(resolve, !_q, &q);
1214 q->res_handler = callback;
1215 q->userdata = userdata;
1217 req.dname_len = strlen(dname) + 1;
1221 req.header.id = q->id;
1222 req.header.type = qtype;
1223 req.header.length = sizeof(ResRequest) + req.dname_len;
1225 iov[0] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(ResRequest) };
1226 iov[1] = (struct iovec) { .iov_base = (void*) dname, .iov_len = req.dname_len };
1231 if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) {
1232 sd_resolve_query_unref(q);
1242 _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) {
1243 return resolve_res(resolve, q, REQUEST_RES_QUERY, dname, class, type, callback, userdata);
1246 _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) {
1247 return resolve_res(resolve, q, REQUEST_RES_SEARCH, dname, class, type, callback, userdata);
1250 static int res_query_done(sd_resolve_query* q) {
1253 assert(q->res_handler);
1256 h_errno = q->_h_errno;
1258 return q->res_handler(q, q->ret, q->answer, q->userdata);
1261 _public_ sd_resolve_query* sd_resolve_query_ref(sd_resolve_query *q) {
1262 assert_return(q, NULL);
1264 assert(q->n_ref >= 1);
1270 static void resolve_freeaddrinfo(struct addrinfo *ai) {
1272 struct addrinfo *next = ai->ai_next;
1275 free(ai->ai_canonname);
1281 static void resolve_query_disconnect(sd_resolve_query *q) {
1282 sd_resolve *resolve;
1290 resolve = q->resolve;
1291 assert(resolve->n_queries > 0);
1294 assert(resolve->n_done > 0);
1298 i = q->id % QUERIES_MAX;
1299 assert(resolve->query_array[i] == q);
1300 resolve->query_array[i] = NULL;
1301 LIST_REMOVE(queries, resolve->queries, q);
1302 resolve->n_queries--;
1306 sd_resolve_unref(resolve);
1309 static void resolve_query_free(sd_resolve_query *q) {
1312 resolve_query_disconnect(q);
1314 resolve_freeaddrinfo(q->addrinfo);
1321 _public_ sd_resolve_query* sd_resolve_query_unref(sd_resolve_query* q) {
1325 assert(q->n_ref >= 1);
1329 resolve_query_free(q);
1334 _public_ int sd_resolve_query_is_done(sd_resolve_query *q) {
1335 assert_return(q, -EINVAL);
1336 assert_return(!resolve_pid_changed(q->resolve), -ECHILD);
1341 _public_ void* sd_resolve_query_set_userdata(sd_resolve_query *q, void *userdata) {
1344 assert_return(q, NULL);
1345 assert_return(!resolve_pid_changed(q->resolve), NULL);
1348 q->userdata = userdata;
1353 _public_ void* sd_resolve_query_get_userdata(sd_resolve_query *q) {
1354 assert_return(q, NULL);
1355 assert_return(!resolve_pid_changed(q->resolve), NULL);
1360 _public_ sd_resolve *sd_resolve_query_get_resolve(sd_resolve_query *q) {
1361 assert_return(q, NULL);
1362 assert_return(!resolve_pid_changed(q->resolve), NULL);
1367 static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
1368 sd_resolve *resolve = userdata;
1373 r = sd_resolve_process(resolve);
1380 _public_ int sd_resolve_attach_event(sd_resolve *resolve, sd_event *event, int priority) {
1383 assert_return(resolve, -EINVAL);
1384 assert_return(!resolve->event, -EBUSY);
1386 assert(!resolve->event_source);
1389 resolve->event = sd_event_ref(event);
1391 r = sd_event_default(&resolve->event);
1396 r = sd_event_add_io(resolve->event, &resolve->event_source, resolve->fds[RESPONSE_RECV_FD], POLLIN, io_callback, resolve);
1400 r = sd_event_source_set_priority(resolve->event_source, priority);
1407 sd_resolve_detach_event(resolve);
1411 _public_ int sd_resolve_detach_event(sd_resolve *resolve) {
1412 assert_return(resolve, -EINVAL);
1414 if (!resolve->event)
1417 if (resolve->event_source) {
1418 sd_event_source_set_enabled(resolve->event_source, SD_EVENT_OFF);
1419 resolve->event_source = sd_event_source_unref(resolve->event_source);
1422 resolve->event = sd_event_unref(resolve->event);
1426 _public_ sd_event *sd_resolve_get_event(sd_resolve *resolve) {
1427 assert_return(resolve, NULL);
1429 return resolve->event;