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;
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 = 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 q = lookup_query(resolve, resp->id);
861 switch (resp->type) {
863 case RESPONSE_ADDRINFO: {
864 const AddrInfoResponse *ai_resp = &packet->addrinfo_response;
867 struct addrinfo *prev = NULL;
869 assert(length >= sizeof(AddrInfoResponse));
870 assert(q->type == REQUEST_ADDRINFO);
872 q->ret = ai_resp->ret;
873 q->_errno = ai_resp->_errno;
874 q->_h_errno = ai_resp->_h_errno;
876 l = length - sizeof(AddrInfoResponse);
877 p = (const uint8_t*) resp + sizeof(AddrInfoResponse);
880 struct addrinfo *ai = NULL;
882 r = unserialize_addrinfo(&p, &l, &ai);
887 freeaddrinfo(q->addrinfo);
900 return complete_query(resolve, q);
903 case RESPONSE_NAMEINFO: {
904 const NameInfoResponse *ni_resp = &packet->nameinfo_response;
906 assert(length >= sizeof(NameInfoResponse));
907 assert(q->type == REQUEST_NAMEINFO);
909 q->ret = ni_resp->ret;
910 q->_errno = ni_resp->_errno;
911 q->_h_errno = ni_resp->_h_errno;
913 if (ni_resp->hostlen > 0) {
914 q->host = strndup((const char*) ni_resp + sizeof(NameInfoResponse), ni_resp->hostlen-1);
922 if (ni_resp->servlen > 0) {
923 q->serv = strndup((const char*) ni_resp + sizeof(NameInfoResponse) + ni_resp->hostlen, ni_resp->servlen-1);
931 return complete_query(resolve, q);
935 const ResResponse *res_resp = &packet->res_response;
937 assert(length >= sizeof(ResResponse));
938 assert(q->type == REQUEST_RES_QUERY || q->type == REQUEST_RES_SEARCH);
940 q->ret = res_resp->ret;
941 q->_errno = res_resp->_errno;
942 q->_h_errno = res_resp->_h_errno;
944 if (res_resp->ret >= 0) {
945 q->answer = memdup((const char *)resp + sizeof(ResResponse), res_resp->ret);
953 return complete_query(resolve, q);
961 _public_ int sd_resolve_process(sd_resolve *resolve) {
962 RESOLVE_DONT_DESTROY(resolve);
966 uint8_t space[BUFSIZE];
971 assert_return(resolve, -EINVAL);
972 assert_return(!resolve_pid_changed(resolve), -ECHILD);
974 /* We don't allow recursively invoking sd_resolve_process(). */
975 assert_return(!resolve->current, -EBUSY);
977 l = recv(resolve->fds[RESPONSE_RECV_FD], &buf, sizeof(buf), 0);
985 return -ECONNREFUSED;
987 r = handle_response(resolve, &buf.packet, (size_t) l);
994 _public_ int sd_resolve_wait(sd_resolve *resolve, uint64_t timeout_usec) {
997 assert_return(resolve, -EINVAL);
998 assert_return(!resolve_pid_changed(resolve), -ECHILD);
1000 if (resolve->n_done >= resolve->n_queries)
1004 r = fd_wait_for_event(resolve->fds[RESPONSE_RECV_FD], POLLIN, timeout_usec);
1005 } while (r == -EINTR);
1010 return sd_resolve_process(resolve);
1013 static int alloc_query(sd_resolve *resolve, bool floating, sd_resolve_query **_q) {
1014 sd_resolve_query *q;
1020 if (resolve->n_queries >= QUERIES_MAX)
1023 r = start_threads(resolve, 1);
1027 while (resolve->query_array[resolve->current_id % QUERIES_MAX])
1028 resolve->current_id++;
1030 q = resolve->query_array[resolve->current_id % QUERIES_MAX] = new0(sd_resolve_query, 1);
1035 q->resolve = resolve;
1036 q->floating = floating;
1037 q->id = resolve->current_id++;
1040 sd_resolve_ref(resolve);
1042 LIST_PREPEND(queries, resolve->queries, q);
1043 resolve->n_queries++;
1049 _public_ int sd_resolve_getaddrinfo(
1050 sd_resolve *resolve,
1051 sd_resolve_query **_q,
1052 const char *node, const char *service,
1053 const struct addrinfo *hints,
1054 sd_resolve_getaddrinfo_handler_t callback, void *userdata) {
1056 AddrInfoRequest req = {};
1057 struct msghdr mh = {};
1058 struct iovec iov[3];
1059 sd_resolve_query *q;
1062 assert_return(resolve, -EINVAL);
1063 assert_return(node || service, -EINVAL);
1064 assert_return(callback, -EINVAL);
1065 assert_return(!resolve_pid_changed(resolve), -ECHILD);
1067 r = alloc_query(resolve, !_q, &q);
1071 q->type = REQUEST_ADDRINFO;
1072 q->getaddrinfo_handler = callback;
1073 q->userdata = userdata;
1075 req.node_len = node ? strlen(node)+1 : 0;
1076 req.service_len = service ? strlen(service)+1 : 0;
1078 req.header.id = q->id;
1079 req.header.type = REQUEST_ADDRINFO;
1080 req.header.length = sizeof(AddrInfoRequest) + req.node_len + req.service_len;
1083 req.hints_valid = true;
1084 req.ai_flags = hints->ai_flags;
1085 req.ai_family = hints->ai_family;
1086 req.ai_socktype = hints->ai_socktype;
1087 req.ai_protocol = hints->ai_protocol;
1090 iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(AddrInfoRequest) };
1092 iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = (void*) node, .iov_len = req.node_len };
1094 iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = (void*) service, .iov_len = req.service_len };
1097 if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) {
1098 sd_resolve_query_unref(q);
1108 static int getaddrinfo_done(sd_resolve_query* q) {
1111 assert(q->getaddrinfo_handler);
1114 h_errno = q->_h_errno;
1116 return q->getaddrinfo_handler(q, q->ret, q->addrinfo, q->userdata);
1119 _public_ int sd_resolve_getnameinfo(
1120 sd_resolve *resolve,
1121 sd_resolve_query**_q,
1122 const struct sockaddr *sa, socklen_t salen,
1125 sd_resolve_getnameinfo_handler_t callback,
1128 NameInfoRequest req = {};
1129 struct msghdr mh = {};
1130 struct iovec iov[2];
1131 sd_resolve_query *q;
1134 assert_return(resolve, -EINVAL);
1135 assert_return(sa, -EINVAL);
1136 assert_return(salen >= sizeof(struct sockaddr), -EINVAL);
1137 assert_return(salen <= sizeof(union sockaddr_union), -EINVAL);
1138 assert_return((get & ~SD_RESOLVE_GET_BOTH) == 0, -EINVAL);
1139 assert_return(callback, -EINVAL);
1140 assert_return(!resolve_pid_changed(resolve), -ECHILD);
1142 r = alloc_query(resolve, !_q, &q);
1146 q->type = REQUEST_NAMEINFO;
1147 q->getnameinfo_handler = callback;
1148 q->userdata = userdata;
1150 req.header.id = q->id;
1151 req.header.type = REQUEST_NAMEINFO;
1152 req.header.length = sizeof(NameInfoRequest) + salen;
1155 req.sockaddr_len = salen;
1156 req.gethost = !!(get & SD_RESOLVE_GET_HOST);
1157 req.getserv = !!(get & SD_RESOLVE_GET_SERVICE);
1159 iov[0] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(NameInfoRequest) };
1160 iov[1] = (struct iovec) { .iov_base = (void*) sa, .iov_len = salen };
1165 if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) {
1166 sd_resolve_query_unref(q);
1176 static int getnameinfo_done(sd_resolve_query *q) {
1180 assert(q->getnameinfo_handler);
1183 h_errno= q->_h_errno;
1185 return q->getnameinfo_handler(q, q->ret, q->host, q->serv, q->userdata);
1188 static int resolve_res(
1189 sd_resolve *resolve,
1190 sd_resolve_query **_q,
1193 int class, int type,
1194 sd_resolve_res_handler_t callback, void *userdata) {
1196 struct msghdr mh = {};
1197 struct iovec iov[2];
1198 ResRequest req = {};
1199 sd_resolve_query *q;
1202 assert_return(resolve, -EINVAL);
1203 assert_return(dname, -EINVAL);
1204 assert_return(callback, -EINVAL);
1205 assert_return(!resolve_pid_changed(resolve), -ECHILD);
1207 r = alloc_query(resolve, !_q, &q);
1212 q->res_handler = callback;
1213 q->userdata = userdata;
1215 req.dname_len = strlen(dname) + 1;
1219 req.header.id = q->id;
1220 req.header.type = qtype;
1221 req.header.length = sizeof(ResRequest) + req.dname_len;
1223 iov[0] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(ResRequest) };
1224 iov[1] = (struct iovec) { .iov_base = (void*) dname, .iov_len = req.dname_len };
1229 if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) {
1230 sd_resolve_query_unref(q);
1240 _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) {
1241 return resolve_res(resolve, q, REQUEST_RES_QUERY, dname, class, type, callback, userdata);
1244 _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) {
1245 return resolve_res(resolve, q, REQUEST_RES_SEARCH, dname, class, type, callback, userdata);
1248 static int res_query_done(sd_resolve_query* q) {
1251 assert(q->res_handler);
1254 h_errno = q->_h_errno;
1256 return q->res_handler(q, q->ret, q->answer, q->userdata);
1259 _public_ sd_resolve_query* sd_resolve_query_ref(sd_resolve_query *q) {
1260 assert_return(q, NULL);
1262 assert(q->n_ref >= 1);
1268 static void resolve_freeaddrinfo(struct addrinfo *ai) {
1270 struct addrinfo *next = ai->ai_next;
1273 free(ai->ai_canonname);
1279 static void resolve_query_disconnect(sd_resolve_query *q) {
1280 sd_resolve *resolve;
1288 resolve = q->resolve;
1289 assert(resolve->n_queries > 0);
1292 assert(resolve->n_done > 0);
1296 i = q->id % QUERIES_MAX;
1297 assert(resolve->query_array[i] == q);
1298 resolve->query_array[i] = NULL;
1299 LIST_REMOVE(queries, resolve->queries, q);
1300 resolve->n_queries--;
1304 sd_resolve_unref(resolve);
1307 static void resolve_query_free(sd_resolve_query *q) {
1310 resolve_query_disconnect(q);
1312 resolve_freeaddrinfo(q->addrinfo);
1319 _public_ sd_resolve_query* sd_resolve_query_unref(sd_resolve_query* q) {
1323 assert(q->n_ref >= 1);
1327 resolve_query_free(q);
1332 _public_ int sd_resolve_query_is_done(sd_resolve_query *q) {
1333 assert_return(q, -EINVAL);
1334 assert_return(!resolve_pid_changed(q->resolve), -ECHILD);
1339 _public_ void* sd_resolve_query_set_userdata(sd_resolve_query *q, void *userdata) {
1342 assert_return(q, NULL);
1343 assert_return(!resolve_pid_changed(q->resolve), NULL);
1346 q->userdata = userdata;
1351 _public_ void* sd_resolve_query_get_userdata(sd_resolve_query *q) {
1352 assert_return(q, NULL);
1353 assert_return(!resolve_pid_changed(q->resolve), NULL);
1358 _public_ sd_resolve *sd_resolve_query_get_resolve(sd_resolve_query *q) {
1359 assert_return(q, NULL);
1360 assert_return(!resolve_pid_changed(q->resolve), NULL);
1365 static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
1366 sd_resolve *resolve = userdata;
1371 r = sd_resolve_process(resolve);
1378 _public_ int sd_resolve_attach_event(sd_resolve *resolve, sd_event *event, int priority) {
1381 assert_return(resolve, -EINVAL);
1382 assert_return(!resolve->event, -EBUSY);
1384 assert(!resolve->event_source);
1387 resolve->event = sd_event_ref(event);
1389 r = sd_event_default(&resolve->event);
1394 r = sd_event_add_io(resolve->event, &resolve->event_source, resolve->fds[RESPONSE_RECV_FD], POLLIN, io_callback, resolve);
1398 r = sd_event_source_set_priority(resolve->event_source, priority);
1405 sd_resolve_detach_event(resolve);
1409 _public_ int sd_resolve_detach_event(sd_resolve *resolve) {
1410 assert_return(resolve, -EINVAL);
1412 if (!resolve->event)
1415 if (resolve->event_source) {
1416 sd_event_source_set_enabled(resolve->event_source, SD_EVENT_OFF);
1417 resolve->event_source = sd_event_source_unref(resolve->event_source);
1420 resolve->event = sd_event_unref(resolve->event);
1424 _public_ sd_event *sd_resolve_get_event(sd_resolve *resolve) {
1425 assert_return(resolve, NULL);
1427 return resolve->event;