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 = 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_index]) {
1028 resolve->current_index++;
1029 resolve->current_id++;
1031 resolve->current_index %= QUERIES_MAX;
1034 q = resolve->query_array[resolve->current_index] = new0(sd_resolve_query, 1);
1039 q->resolve = resolve;
1040 q->floating = floating;
1041 q->id = resolve->current_id;
1044 sd_resolve_ref(resolve);
1046 LIST_PREPEND(queries, resolve->queries, q);
1047 resolve->n_queries++;
1053 _public_ int sd_resolve_getaddrinfo(
1054 sd_resolve *resolve,
1055 sd_resolve_query **_q,
1056 const char *node, const char *service,
1057 const struct addrinfo *hints,
1058 sd_resolve_getaddrinfo_handler_t callback, void *userdata) {
1060 AddrInfoRequest req = {};
1061 struct msghdr mh = {};
1062 struct iovec iov[3];
1063 sd_resolve_query *q;
1066 assert_return(resolve, -EINVAL);
1067 assert_return(node || service, -EINVAL);
1068 assert_return(callback, -EINVAL);
1069 assert_return(!resolve_pid_changed(resolve), -ECHILD);
1071 r = alloc_query(resolve, !_q, &q);
1075 q->type = REQUEST_ADDRINFO;
1076 q->getaddrinfo_handler = callback;
1077 q->userdata = userdata;
1079 req.node_len = node ? strlen(node)+1 : 0;
1080 req.service_len = service ? strlen(service)+1 : 0;
1082 req.header.id = q->id;
1083 req.header.type = REQUEST_ADDRINFO;
1084 req.header.length = sizeof(AddrInfoRequest) + req.node_len + req.service_len;
1087 req.hints_valid = true;
1088 req.ai_flags = hints->ai_flags;
1089 req.ai_family = hints->ai_family;
1090 req.ai_socktype = hints->ai_socktype;
1091 req.ai_protocol = hints->ai_protocol;
1094 iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(AddrInfoRequest) };
1096 iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = (void*) node, .iov_len = req.node_len };
1098 iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = (void*) service, .iov_len = req.service_len };
1101 if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) {
1102 sd_resolve_query_unref(q);
1112 static int getaddrinfo_done(sd_resolve_query* q) {
1115 assert(q->getaddrinfo_handler);
1118 h_errno = q->_h_errno;
1120 return q->getaddrinfo_handler(q, q->ret, q->addrinfo, q->userdata);
1123 _public_ int sd_resolve_getnameinfo(
1124 sd_resolve *resolve,
1125 sd_resolve_query**_q,
1126 const struct sockaddr *sa, socklen_t salen,
1129 sd_resolve_getnameinfo_handler_t callback,
1132 NameInfoRequest req = {};
1133 struct msghdr mh = {};
1134 struct iovec iov[2];
1135 sd_resolve_query *q;
1138 assert_return(resolve, -EINVAL);
1139 assert_return(sa, -EINVAL);
1140 assert_return(salen >= sizeof(struct sockaddr), -EINVAL);
1141 assert_return(salen <= sizeof(union sockaddr_union), -EINVAL);
1142 assert_return((get & ~SD_RESOLVE_GET_BOTH) == 0, -EINVAL);
1143 assert_return(callback, -EINVAL);
1144 assert_return(!resolve_pid_changed(resolve), -ECHILD);
1146 r = alloc_query(resolve, !_q, &q);
1150 q->type = REQUEST_NAMEINFO;
1151 q->getnameinfo_handler = callback;
1152 q->userdata = userdata;
1154 req.header.id = q->id;
1155 req.header.type = REQUEST_NAMEINFO;
1156 req.header.length = sizeof(NameInfoRequest) + salen;
1159 req.sockaddr_len = salen;
1160 req.gethost = !!(get & SD_RESOLVE_GET_HOST);
1161 req.getserv = !!(get & SD_RESOLVE_GET_SERVICE);
1163 iov[0] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(NameInfoRequest) };
1164 iov[1] = (struct iovec) { .iov_base = (void*) sa, .iov_len = salen };
1169 if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) {
1170 sd_resolve_query_unref(q);
1180 static int getnameinfo_done(sd_resolve_query *q) {
1184 assert(q->getnameinfo_handler);
1187 h_errno= q->_h_errno;
1189 return q->getnameinfo_handler(q, q->ret, q->host, q->serv, q->userdata);
1192 static int resolve_res(
1193 sd_resolve *resolve,
1194 sd_resolve_query **_q,
1197 int class, int type,
1198 sd_resolve_res_handler_t callback, void *userdata) {
1200 struct msghdr mh = {};
1201 struct iovec iov[2];
1202 ResRequest req = {};
1203 sd_resolve_query *q;
1206 assert_return(resolve, -EINVAL);
1207 assert_return(dname, -EINVAL);
1208 assert_return(callback, -EINVAL);
1209 assert_return(!resolve_pid_changed(resolve), -ECHILD);
1211 r = alloc_query(resolve, !_q, &q);
1216 q->res_handler = callback;
1217 q->userdata = userdata;
1219 req.dname_len = strlen(dname) + 1;
1223 req.header.id = q->id;
1224 req.header.type = qtype;
1225 req.header.length = sizeof(ResRequest) + req.dname_len;
1227 iov[0] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(ResRequest) };
1228 iov[1] = (struct iovec) { .iov_base = (void*) dname, .iov_len = req.dname_len };
1233 if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) {
1234 sd_resolve_query_unref(q);
1244 _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) {
1245 return resolve_res(resolve, q, REQUEST_RES_QUERY, dname, class, type, callback, userdata);
1248 _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) {
1249 return resolve_res(resolve, q, REQUEST_RES_SEARCH, dname, class, type, callback, userdata);
1252 static int res_query_done(sd_resolve_query* q) {
1255 assert(q->res_handler);
1258 h_errno = q->_h_errno;
1260 return q->res_handler(q, q->ret, q->answer, q->userdata);
1263 _public_ sd_resolve_query* sd_resolve_query_ref(sd_resolve_query *q) {
1264 assert_return(q, NULL);
1266 assert(q->n_ref >= 1);
1272 static void resolve_freeaddrinfo(struct addrinfo *ai) {
1274 struct addrinfo *next = ai->ai_next;
1277 free(ai->ai_canonname);
1283 static void resolve_query_disconnect(sd_resolve_query *q) {
1284 sd_resolve *resolve;
1292 resolve = q->resolve;
1293 assert(resolve->n_queries > 0);
1296 assert(resolve->n_done > 0);
1300 i = q->id % QUERIES_MAX;
1301 assert(resolve->query_array[i] == q);
1302 resolve->query_array[i] = NULL;
1303 LIST_REMOVE(queries, resolve->queries, q);
1304 resolve->n_queries--;
1308 sd_resolve_unref(resolve);
1311 static void resolve_query_free(sd_resolve_query *q) {
1314 resolve_query_disconnect(q);
1316 resolve_freeaddrinfo(q->addrinfo);
1323 _public_ sd_resolve_query* sd_resolve_query_unref(sd_resolve_query* q) {
1327 assert(q->n_ref >= 1);
1331 resolve_query_free(q);
1336 _public_ int sd_resolve_query_is_done(sd_resolve_query *q) {
1337 assert_return(q, -EINVAL);
1338 assert_return(!resolve_pid_changed(q->resolve), -ECHILD);
1343 _public_ void* sd_resolve_query_set_userdata(sd_resolve_query *q, void *userdata) {
1346 assert_return(q, NULL);
1347 assert_return(!resolve_pid_changed(q->resolve), NULL);
1350 q->userdata = userdata;
1355 _public_ void* sd_resolve_query_get_userdata(sd_resolve_query *q) {
1356 assert_return(q, NULL);
1357 assert_return(!resolve_pid_changed(q->resolve), NULL);
1362 _public_ sd_resolve *sd_resolve_query_get_resolve(sd_resolve_query *q) {
1363 assert_return(q, NULL);
1364 assert_return(!resolve_pid_changed(q->resolve), NULL);
1369 static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
1370 sd_resolve *resolve = userdata;
1375 r = sd_resolve_process(resolve);
1382 _public_ int sd_resolve_attach_event(sd_resolve *resolve, sd_event *event, int priority) {
1385 assert_return(resolve, -EINVAL);
1386 assert_return(!resolve->event, -EBUSY);
1388 assert(!resolve->event_source);
1391 resolve->event = sd_event_ref(event);
1393 r = sd_event_default(&resolve->event);
1398 r = sd_event_add_io(resolve->event, &resolve->event_source, resolve->fds[RESPONSE_RECV_FD], POLLIN, io_callback, resolve);
1402 r = sd_event_source_set_priority(resolve->event_source, priority);
1409 sd_resolve_detach_event(resolve);
1413 _public_ int sd_resolve_detach_event(sd_resolve *resolve) {
1414 assert_return(resolve, -EINVAL);
1416 if (!resolve->event)
1419 if (resolve->event_source) {
1420 sd_event_source_set_enabled(resolve->event_source, SD_EVENT_OFF);
1421 resolve->event_source = sd_event_source_unref(resolve->event_source);
1424 resolve->event = sd_event_unref(resolve->event);
1428 _public_ sd_event *sd_resolve_get_event(sd_resolve *resolve) {
1429 assert_return(resolve, NULL);
1431 return resolve->event;