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;
89 sd_resolve_query* query_array[QUERIES_MAX];
90 unsigned n_queries, n_done, n_outstanding;
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_outstanding + extra;
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 = NULL;
778 resolve_query_disconnect(q);
779 sd_resolve_query_unref(q);
782 sd_resolve_query_unref(q);
787 static int unserialize_addrinfo(const void **p, size_t *length, struct addrinfo **ret_ai) {
788 AddrInfoSerialization s;
797 if (*length < sizeof(AddrInfoSerialization))
800 memcpy(&s, *p, sizeof(s));
802 l = sizeof(AddrInfoSerialization) + s.ai_addrlen + s.canonname_len;
806 ai = new0(struct addrinfo, 1);
810 ai->ai_flags = s.ai_flags;
811 ai->ai_family = s.ai_family;
812 ai->ai_socktype = s.ai_socktype;
813 ai->ai_protocol = s.ai_protocol;
814 ai->ai_addrlen = s.ai_addrlen;
816 if (s.ai_addrlen > 0) {
817 ai->ai_addr = memdup((const uint8_t*) *p + sizeof(AddrInfoSerialization), s.ai_addrlen);
824 if (s.canonname_len > 0) {
825 ai->ai_canonname = memdup((const uint8_t*) *p + sizeof(AddrInfoSerialization) + s.ai_addrlen, s.canonname_len);
826 if (!ai->ai_canonname) {
835 *p = ((const uint8_t*) *p) + l;
840 static int handle_response(sd_resolve *resolve, const Packet *packet, size_t length) {
847 resp = &packet->rheader;
849 assert(length >= sizeof(RHeader));
850 assert(length == resp->length);
852 if (resp->type == RESPONSE_DIED) {
853 resolve->dead = true;
857 assert(resolve->n_outstanding > 0);
858 resolve->n_outstanding--;
860 q = lookup_query(resolve, resp->id);
864 switch (resp->type) {
866 case RESPONSE_ADDRINFO: {
867 const AddrInfoResponse *ai_resp = &packet->addrinfo_response;
870 struct addrinfo *prev = NULL;
872 assert(length >= sizeof(AddrInfoResponse));
873 assert(q->type == REQUEST_ADDRINFO);
875 q->ret = ai_resp->ret;
876 q->_errno = ai_resp->_errno;
877 q->_h_errno = ai_resp->_h_errno;
879 l = length - sizeof(AddrInfoResponse);
880 p = (const uint8_t*) resp + sizeof(AddrInfoResponse);
883 struct addrinfo *ai = NULL;
885 r = unserialize_addrinfo(&p, &l, &ai);
890 freeaddrinfo(q->addrinfo);
903 return complete_query(resolve, q);
906 case RESPONSE_NAMEINFO: {
907 const NameInfoResponse *ni_resp = &packet->nameinfo_response;
909 assert(length >= sizeof(NameInfoResponse));
910 assert(q->type == REQUEST_NAMEINFO);
912 q->ret = ni_resp->ret;
913 q->_errno = ni_resp->_errno;
914 q->_h_errno = ni_resp->_h_errno;
916 if (ni_resp->hostlen > 0) {
917 q->host = strndup((const char*) ni_resp + sizeof(NameInfoResponse), ni_resp->hostlen-1);
925 if (ni_resp->servlen > 0) {
926 q->serv = strndup((const char*) ni_resp + sizeof(NameInfoResponse) + ni_resp->hostlen, ni_resp->servlen-1);
934 return complete_query(resolve, q);
938 const ResResponse *res_resp = &packet->res_response;
940 assert(length >= sizeof(ResResponse));
941 assert(q->type == REQUEST_RES_QUERY || q->type == REQUEST_RES_SEARCH);
943 q->ret = res_resp->ret;
944 q->_errno = res_resp->_errno;
945 q->_h_errno = res_resp->_h_errno;
947 if (res_resp->ret >= 0) {
948 q->answer = memdup((const char *)resp + sizeof(ResResponse), res_resp->ret);
956 return complete_query(resolve, q);
964 _public_ int sd_resolve_process(sd_resolve *resolve) {
965 RESOLVE_DONT_DESTROY(resolve);
969 uint8_t space[BUFSIZE];
974 assert_return(resolve, -EINVAL);
975 assert_return(!resolve_pid_changed(resolve), -ECHILD);
977 /* We don't allow recursively invoking sd_resolve_process(). */
978 assert_return(!resolve->current, -EBUSY);
980 l = recv(resolve->fds[RESPONSE_RECV_FD], &buf, sizeof(buf), 0);
988 return -ECONNREFUSED;
990 r = handle_response(resolve, &buf.packet, (size_t) l);
997 _public_ int sd_resolve_wait(sd_resolve *resolve, uint64_t timeout_usec) {
1000 assert_return(resolve, -EINVAL);
1001 assert_return(!resolve_pid_changed(resolve), -ECHILD);
1003 if (resolve->n_done >= resolve->n_queries)
1007 r = fd_wait_for_event(resolve->fds[RESPONSE_RECV_FD], POLLIN, timeout_usec);
1008 } while (r == -EINTR);
1013 return sd_resolve_process(resolve);
1016 static int alloc_query(sd_resolve *resolve, bool floating, sd_resolve_query **_q) {
1017 sd_resolve_query *q;
1023 if (resolve->n_queries >= QUERIES_MAX)
1026 r = start_threads(resolve, 1);
1030 while (resolve->query_array[resolve->current_id % QUERIES_MAX])
1031 resolve->current_id++;
1033 q = resolve->query_array[resolve->current_id % QUERIES_MAX] = new0(sd_resolve_query, 1);
1038 q->resolve = resolve;
1039 q->floating = floating;
1040 q->id = resolve->current_id++;
1043 sd_resolve_ref(resolve);
1045 LIST_PREPEND(queries, resolve->queries, q);
1046 resolve->n_queries++;
1052 _public_ int sd_resolve_getaddrinfo(
1053 sd_resolve *resolve,
1054 sd_resolve_query **_q,
1055 const char *node, const char *service,
1056 const struct addrinfo *hints,
1057 sd_resolve_getaddrinfo_handler_t callback, void *userdata) {
1059 AddrInfoRequest req = {};
1060 struct msghdr mh = {};
1061 struct iovec iov[3];
1062 sd_resolve_query *q;
1065 assert_return(resolve, -EINVAL);
1066 assert_return(node || service, -EINVAL);
1067 assert_return(callback, -EINVAL);
1068 assert_return(!resolve_pid_changed(resolve), -ECHILD);
1070 r = alloc_query(resolve, !_q, &q);
1074 q->type = REQUEST_ADDRINFO;
1075 q->getaddrinfo_handler = callback;
1076 q->userdata = userdata;
1078 req.node_len = node ? strlen(node)+1 : 0;
1079 req.service_len = service ? strlen(service)+1 : 0;
1081 req.header.id = q->id;
1082 req.header.type = REQUEST_ADDRINFO;
1083 req.header.length = sizeof(AddrInfoRequest) + req.node_len + req.service_len;
1086 req.hints_valid = true;
1087 req.ai_flags = hints->ai_flags;
1088 req.ai_family = hints->ai_family;
1089 req.ai_socktype = hints->ai_socktype;
1090 req.ai_protocol = hints->ai_protocol;
1093 iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(AddrInfoRequest) };
1095 iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = (void*) node, .iov_len = req.node_len };
1097 iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = (void*) service, .iov_len = req.service_len };
1100 if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) {
1101 sd_resolve_query_unref(q);
1105 resolve->n_outstanding++;
1113 static int getaddrinfo_done(sd_resolve_query* q) {
1116 assert(q->getaddrinfo_handler);
1119 h_errno = q->_h_errno;
1121 return q->getaddrinfo_handler(q, q->ret, q->addrinfo, q->userdata);
1124 _public_ int sd_resolve_getnameinfo(
1125 sd_resolve *resolve,
1126 sd_resolve_query**_q,
1127 const struct sockaddr *sa, socklen_t salen,
1130 sd_resolve_getnameinfo_handler_t callback,
1133 NameInfoRequest req = {};
1134 struct msghdr mh = {};
1135 struct iovec iov[2];
1136 sd_resolve_query *q;
1139 assert_return(resolve, -EINVAL);
1140 assert_return(sa, -EINVAL);
1141 assert_return(salen >= sizeof(struct sockaddr), -EINVAL);
1142 assert_return(salen <= sizeof(union sockaddr_union), -EINVAL);
1143 assert_return((get & ~SD_RESOLVE_GET_BOTH) == 0, -EINVAL);
1144 assert_return(callback, -EINVAL);
1145 assert_return(!resolve_pid_changed(resolve), -ECHILD);
1147 r = alloc_query(resolve, !_q, &q);
1151 q->type = REQUEST_NAMEINFO;
1152 q->getnameinfo_handler = callback;
1153 q->userdata = userdata;
1155 req.header.id = q->id;
1156 req.header.type = REQUEST_NAMEINFO;
1157 req.header.length = sizeof(NameInfoRequest) + salen;
1160 req.sockaddr_len = salen;
1161 req.gethost = !!(get & SD_RESOLVE_GET_HOST);
1162 req.getserv = !!(get & SD_RESOLVE_GET_SERVICE);
1164 iov[0] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(NameInfoRequest) };
1165 iov[1] = (struct iovec) { .iov_base = (void*) sa, .iov_len = salen };
1170 if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) {
1171 sd_resolve_query_unref(q);
1175 resolve->n_outstanding++;
1183 static int getnameinfo_done(sd_resolve_query *q) {
1187 assert(q->getnameinfo_handler);
1190 h_errno= q->_h_errno;
1192 return q->getnameinfo_handler(q, q->ret, q->host, q->serv, q->userdata);
1195 static int resolve_res(
1196 sd_resolve *resolve,
1197 sd_resolve_query **_q,
1200 int class, int type,
1201 sd_resolve_res_handler_t callback, void *userdata) {
1203 struct msghdr mh = {};
1204 struct iovec iov[2];
1205 ResRequest req = {};
1206 sd_resolve_query *q;
1209 assert_return(resolve, -EINVAL);
1210 assert_return(dname, -EINVAL);
1211 assert_return(callback, -EINVAL);
1212 assert_return(!resolve_pid_changed(resolve), -ECHILD);
1214 r = alloc_query(resolve, !_q, &q);
1219 q->res_handler = callback;
1220 q->userdata = userdata;
1222 req.dname_len = strlen(dname) + 1;
1226 req.header.id = q->id;
1227 req.header.type = qtype;
1228 req.header.length = sizeof(ResRequest) + req.dname_len;
1230 iov[0] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(ResRequest) };
1231 iov[1] = (struct iovec) { .iov_base = (void*) dname, .iov_len = req.dname_len };
1236 if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) {
1237 sd_resolve_query_unref(q);
1241 resolve->n_outstanding++;
1249 _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) {
1250 return resolve_res(resolve, q, REQUEST_RES_QUERY, dname, class, type, callback, userdata);
1253 _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) {
1254 return resolve_res(resolve, q, REQUEST_RES_SEARCH, dname, class, type, callback, userdata);
1257 static int res_query_done(sd_resolve_query* q) {
1260 assert(q->res_handler);
1263 h_errno = q->_h_errno;
1265 return q->res_handler(q, q->ret, q->answer, q->userdata);
1268 _public_ sd_resolve_query* sd_resolve_query_ref(sd_resolve_query *q) {
1269 assert_return(q, NULL);
1271 assert(q->n_ref >= 1);
1277 static void resolve_freeaddrinfo(struct addrinfo *ai) {
1279 struct addrinfo *next = ai->ai_next;
1282 free(ai->ai_canonname);
1288 static void resolve_query_disconnect(sd_resolve_query *q) {
1289 sd_resolve *resolve;
1297 resolve = q->resolve;
1298 assert(resolve->n_queries > 0);
1301 assert(resolve->n_done > 0);
1305 i = q->id % QUERIES_MAX;
1306 assert(resolve->query_array[i] == q);
1307 resolve->query_array[i] = NULL;
1308 LIST_REMOVE(queries, resolve->queries, q);
1309 resolve->n_queries--;
1313 sd_resolve_unref(resolve);
1316 static void resolve_query_free(sd_resolve_query *q) {
1319 resolve_query_disconnect(q);
1321 resolve_freeaddrinfo(q->addrinfo);
1328 _public_ sd_resolve_query* sd_resolve_query_unref(sd_resolve_query* q) {
1332 assert(q->n_ref >= 1);
1336 resolve_query_free(q);
1341 _public_ int sd_resolve_query_is_done(sd_resolve_query *q) {
1342 assert_return(q, -EINVAL);
1343 assert_return(!resolve_pid_changed(q->resolve), -ECHILD);
1348 _public_ void* sd_resolve_query_set_userdata(sd_resolve_query *q, void *userdata) {
1351 assert_return(q, NULL);
1352 assert_return(!resolve_pid_changed(q->resolve), NULL);
1355 q->userdata = userdata;
1360 _public_ void* sd_resolve_query_get_userdata(sd_resolve_query *q) {
1361 assert_return(q, NULL);
1362 assert_return(!resolve_pid_changed(q->resolve), NULL);
1367 _public_ sd_resolve *sd_resolve_query_get_resolve(sd_resolve_query *q) {
1368 assert_return(q, NULL);
1369 assert_return(!resolve_pid_changed(q->resolve), NULL);
1374 static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
1375 sd_resolve *resolve = userdata;
1380 r = sd_resolve_process(resolve);
1387 _public_ int sd_resolve_attach_event(sd_resolve *resolve, sd_event *event, int priority) {
1390 assert_return(resolve, -EINVAL);
1391 assert_return(!resolve->event, -EBUSY);
1393 assert(!resolve->event_source);
1396 resolve->event = sd_event_ref(event);
1398 r = sd_event_default(&resolve->event);
1403 r = sd_event_add_io(resolve->event, &resolve->event_source, resolve->fds[RESPONSE_RECV_FD], POLLIN, io_callback, resolve);
1407 r = sd_event_source_set_priority(resolve->event_source, priority);
1414 sd_resolve_detach_event(resolve);
1418 _public_ int sd_resolve_detach_event(sd_resolve *resolve) {
1419 assert_return(resolve, -EINVAL);
1421 if (!resolve->event)
1424 if (resolve->event_source) {
1425 sd_event_source_set_enabled(resolve->event_source, SD_EVENT_OFF);
1426 resolve->event_source = sd_event_source_unref(resolve->event_source);
1429 resolve->event = sd_event_unref(resolve->event);
1433 _public_ sd_event *sd_resolve_get_event(sd_resolve *resolve) {
1434 assert_return(resolve, NULL);
1436 return resolve->event;