1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
12 #include <sys/prctl.h>
15 #include "sd-resolve.h"
17 #include "alloc-util.h"
19 #include "errno-util.h"
23 #include "memory-util.h"
24 #include "missing_syscall.h"
25 #include "missing_threads.h"
26 #include "process-util.h"
27 #include "resolve-private.h"
28 #include "socket-util.h"
30 #define WORKERS_MIN 1U
31 #define WORKERS_MAX 16U
32 #define QUERIES_MAX 256U
33 #define BUFSIZE 10240U
60 pthread_t workers
[WORKERS_MAX
];
61 unsigned n_valid_workers
;
64 sd_resolve_query
* query_array
[QUERIES_MAX
];
65 unsigned n_queries
, n_done
, n_outstanding
;
67 sd_event_source
*event_source
;
70 sd_resolve_query
*current
;
72 sd_resolve
**default_resolve_ptr
;
75 LIST_HEAD(sd_resolve_query
, queries
);
78 struct sd_resolve_query
{
91 struct addrinfo
*addrinfo
;
95 sd_resolve_getaddrinfo_handler_t getaddrinfo_handler
;
96 sd_resolve_getnameinfo_handler_t getnameinfo_handler
;
100 sd_resolve_destroy_t destroy_callback
;
102 LIST_FIELDS(sd_resolve_query
, queries
);
105 typedef struct RHeader
{
111 typedef struct AddrInfoRequest
{
112 struct RHeader header
;
118 size_t node_len
, service_len
;
121 typedef struct AddrInfoResponse
{
122 struct RHeader header
;
126 /* followed by addrinfo_serialization[] */
129 typedef struct AddrInfoSerialization
{
135 size_t canonname_len
;
136 /* Followed by ai_addr amd ai_canonname with variable lengths */
137 } AddrInfoSerialization
;
139 typedef struct NameInfoRequest
{
140 struct RHeader header
;
142 socklen_t sockaddr_len
;
143 bool gethost
:1, getserv
:1;
146 typedef struct NameInfoResponse
{
147 struct RHeader header
;
148 size_t hostlen
, servlen
;
154 typedef union Packet
{
156 AddrInfoRequest addrinfo_request
;
157 AddrInfoResponse addrinfo_response
;
158 NameInfoRequest nameinfo_request
;
159 NameInfoResponse nameinfo_response
;
162 static int getaddrinfo_done(sd_resolve_query
* q
);
163 static int getnameinfo_done(sd_resolve_query
*q
);
165 static void resolve_query_disconnect(sd_resolve_query
*q
);
167 #define RESOLVE_DONT_DESTROY(resolve) \
168 _cleanup_(sd_resolve_unrefp) _unused_ sd_resolve *_dont_destroy_##resolve = sd_resolve_ref(resolve)
170 static void query_assign_errno(sd_resolve_query
*q
, int ret
, int error
, int h_error
) {
174 q
->_errno
= abs(error
);
175 q
->_h_errno
= h_error
;
178 static int send_died(int out_fd
) {
180 .type
= RESPONSE_DIED
,
181 .length
= sizeof(RHeader
),
186 if (send(out_fd
, &rh
, rh
.length
, MSG_NOSIGNAL
) < 0)
192 static void *serialize_addrinfo(void *p
, const struct addrinfo
*ai
, size_t *length
, size_t maxlength
) {
193 AddrInfoSerialization s
;
199 assert(*length
<= maxlength
);
201 cnl
= ai
->ai_canonname
? strlen(ai
->ai_canonname
)+1 : 0;
202 l
= sizeof(AddrInfoSerialization
) + ai
->ai_addrlen
+ cnl
;
204 if (*length
+ l
> maxlength
)
207 s
= (AddrInfoSerialization
) {
208 .ai_flags
= ai
->ai_flags
,
209 .ai_family
= ai
->ai_family
,
210 .ai_socktype
= ai
->ai_socktype
,
211 .ai_protocol
= ai
->ai_protocol
,
212 .ai_addrlen
= ai
->ai_addrlen
,
213 .canonname_len
= cnl
,
216 memcpy((uint8_t*) p
, &s
, sizeof(AddrInfoSerialization
));
217 memcpy((uint8_t*) p
+ sizeof(AddrInfoSerialization
), ai
->ai_addr
, ai
->ai_addrlen
);
218 memcpy_safe((char*) p
+ sizeof(AddrInfoSerialization
) + ai
->ai_addrlen
,
219 ai
->ai_canonname
, cnl
);
222 return (uint8_t*) p
+ l
;
225 static int send_addrinfo_reply(
233 AddrInfoResponse resp
= {};
235 AddrInfoSerialization ais
;
236 uint8_t space
[BUFSIZE
];
243 resp
= (AddrInfoResponse
) {
244 .header
.type
= RESPONSE_ADDRINFO
,
246 .header
.length
= sizeof(AddrInfoResponse
),
249 ._h_errno
= _h_errno
,
252 msan_unpoison(&resp
, sizeof(resp
));
254 if (ret
== 0 && ai
) {
258 for (k
= ai
; k
; k
= k
->ai_next
) {
259 p
= serialize_addrinfo(p
, k
, &resp
.header
.length
, (uint8_t*) &buffer
+ BUFSIZE
- (uint8_t*) p
);
270 iov
[0] = IOVEC_MAKE(&resp
, sizeof(AddrInfoResponse
));
271 iov
[1] = IOVEC_MAKE(&buffer
, resp
.header
.length
- sizeof(AddrInfoResponse
));
273 mh
= (struct msghdr
) {
275 .msg_iovlen
= ELEMENTSOF(iov
)
278 if (sendmsg(out_fd
, &mh
, MSG_NOSIGNAL
) < 0)
284 static int send_nameinfo_reply(
293 NameInfoResponse resp
= {};
300 sl
= serv
? strlen(serv
)+1 : 0;
301 hl
= host
? strlen(host
)+1 : 0;
303 resp
= (NameInfoResponse
) {
304 .header
.type
= RESPONSE_NAMEINFO
,
306 .header
.length
= sizeof(NameInfoResponse
) + hl
+ sl
,
311 ._h_errno
= _h_errno
,
314 msan_unpoison(&resp
, sizeof(resp
));
316 iov
[0] = IOVEC_MAKE(&resp
, sizeof(NameInfoResponse
));
317 iov
[1] = IOVEC_MAKE((void*) host
, hl
);
318 iov
[2] = IOVEC_MAKE((void*) serv
, sl
);
320 mh
= (struct msghdr
) {
322 .msg_iovlen
= ELEMENTSOF(iov
)
325 if (sendmsg(out_fd
, &mh
, MSG_NOSIGNAL
) < 0)
331 static int handle_request(int out_fd
, const Packet
*packet
, size_t length
) {
337 req
= &packet
->rheader
;
339 assert_return(length
>= sizeof(RHeader
), -EIO
);
340 assert_return(length
== req
->length
, -EIO
);
344 case REQUEST_ADDRINFO
: {
345 const AddrInfoRequest
*ai_req
= &packet
->addrinfo_request
;
346 struct addrinfo hints
, *result
= NULL
;
347 const char *node
, *service
;
350 assert_return(length
>= sizeof(AddrInfoRequest
), -EBADMSG
);
351 assert_return(length
== sizeof(AddrInfoRequest
) + ai_req
->node_len
+ ai_req
->service_len
, -EBADMSG
);
353 hints
= (struct addrinfo
) {
354 .ai_flags
= ai_req
->ai_flags
,
355 .ai_family
= ai_req
->ai_family
,
356 .ai_socktype
= ai_req
->ai_socktype
,
357 .ai_protocol
= ai_req
->ai_protocol
,
360 msan_unpoison(&hints
, sizeof(hints
));
362 node
= ai_req
->node_len
? (const char*) ai_req
+ sizeof(AddrInfoRequest
) : NULL
;
363 service
= ai_req
->service_len
? (const char*) ai_req
+ sizeof(AddrInfoRequest
) + ai_req
->node_len
: NULL
;
365 ret
= getaddrinfo(node
, service
,
366 ai_req
->hints_valid
? &hints
: NULL
,
369 /* send_addrinfo_reply() frees result */
370 return send_addrinfo_reply(out_fd
, req
->id
, ret
, result
, errno
, h_errno
);
373 case REQUEST_NAMEINFO
: {
374 const NameInfoRequest
*ni_req
= &packet
->nameinfo_request
;
375 char hostbuf
[NI_MAXHOST
], servbuf
[NI_MAXSERV
];
376 union sockaddr_union sa
;
379 assert_return(length
>= sizeof(NameInfoRequest
), -EBADMSG
);
380 assert_return(length
== sizeof(NameInfoRequest
) + ni_req
->sockaddr_len
, -EBADMSG
);
381 assert_return(ni_req
->sockaddr_len
<= sizeof(sa
), -EBADMSG
);
383 memcpy(&sa
, (const uint8_t *) ni_req
+ sizeof(NameInfoRequest
), ni_req
->sockaddr_len
);
385 ret
= getnameinfo(&sa
.sa
, ni_req
->sockaddr_len
,
386 ni_req
->gethost
? hostbuf
: NULL
, ni_req
->gethost
? sizeof(hostbuf
) : 0,
387 ni_req
->getserv
? servbuf
: NULL
, ni_req
->getserv
? sizeof(servbuf
) : 0,
390 return send_nameinfo_reply(out_fd
, req
->id
, ret
,
391 ret
== 0 && ni_req
->gethost
? hostbuf
: NULL
,
392 ret
== 0 && ni_req
->getserv
? servbuf
: NULL
,
396 case REQUEST_TERMINATE
:
401 assert_not_reached();
407 static void* thread_worker(void *p
) {
408 sd_resolve
*resolve
= p
;
410 /* Assign a pretty name to this thread */
411 (void) pthread_setname_np(pthread_self(), "sd-resolve");
413 while (!resolve
->dead
) {
416 uint8_t space
[BUFSIZE
];
420 length
= recv(resolve
->fds
[REQUEST_RECV_FD
], &buf
, sizeof buf
, 0);
422 if (ERRNO_IS_TRANSIENT(errno
))
430 if (handle_request(resolve
->fds
[RESPONSE_SEND_FD
], &buf
.packet
, (size_t) length
) < 0)
434 send_died(resolve
->fds
[RESPONSE_SEND_FD
]);
439 static int start_threads(sd_resolve
*resolve
, unsigned extra
) {
440 sigset_t ss
, saved_ss
;
444 assert_se(sigfillset(&ss
) >= 0);
446 /* No signals in forked off threads please. We set the mask before forking, so that the threads never exist
447 * with a different mask than a fully blocked one */
448 r
= pthread_sigmask(SIG_BLOCK
, &ss
, &saved_ss
);
452 n
= resolve
->n_outstanding
+ extra
;
453 n
= CLAMP(n
, WORKERS_MIN
, WORKERS_MAX
);
455 while (resolve
->n_valid_workers
< n
) {
456 r
= pthread_create(&resolve
->workers
[resolve
->n_valid_workers
], NULL
, thread_worker
, resolve
);
462 resolve
->n_valid_workers
++;
468 k
= pthread_sigmask(SIG_SETMASK
, &saved_ss
, NULL
);
475 static bool resolve_pid_changed(sd_resolve
*r
) {
478 /* We don't support people creating a resolver and keeping it
479 * around after fork(). Let's complain. */
481 return r
->original_pid
!= getpid_cached();
484 int sd_resolve_new(sd_resolve
**ret
) {
485 _cleanup_(sd_resolve_unrefp
) sd_resolve
*resolve
= NULL
;
488 assert_return(ret
, -EINVAL
);
490 resolve
= new0(sd_resolve
, 1);
495 resolve
->original_pid
= getpid_cached();
497 for (i
= 0; i
< _FD_MAX
; i
++)
498 resolve
->fds
[i
] = -EBADF
;
500 if (socketpair(AF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0, resolve
->fds
+ REQUEST_RECV_FD
) < 0)
503 if (socketpair(AF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0, resolve
->fds
+ RESPONSE_RECV_FD
) < 0)
506 for (i
= 0; i
< _FD_MAX
; i
++)
507 resolve
->fds
[i
] = fd_move_above_stdio(resolve
->fds
[i
]);
509 (void) fd_inc_sndbuf(resolve
->fds
[REQUEST_SEND_FD
], QUERIES_MAX
* BUFSIZE
);
510 (void) fd_increase_rxbuf(resolve
->fds
[REQUEST_RECV_FD
], QUERIES_MAX
* BUFSIZE
);
511 (void) fd_inc_sndbuf(resolve
->fds
[RESPONSE_SEND_FD
], QUERIES_MAX
* BUFSIZE
);
512 (void) fd_increase_rxbuf(resolve
->fds
[RESPONSE_RECV_FD
], QUERIES_MAX
* BUFSIZE
);
514 (void) fd_nonblock(resolve
->fds
[RESPONSE_RECV_FD
], true);
516 *ret
= TAKE_PTR(resolve
);
520 int sd_resolve_default(sd_resolve
**ret
) {
521 static thread_local sd_resolve
*default_resolve
= NULL
;
522 sd_resolve
*e
= NULL
;
526 return !!default_resolve
;
528 if (default_resolve
) {
529 *ret
= sd_resolve_ref(default_resolve
);
533 r
= sd_resolve_new(&e
);
537 e
->default_resolve_ptr
= &default_resolve
;
545 int sd_resolve_get_tid(sd_resolve
*resolve
, pid_t
*tid
) {
546 assert_return(resolve
, -EINVAL
);
547 assert_return(tid
, -EINVAL
);
548 assert_return(!resolve_pid_changed(resolve
), -ECHILD
);
550 if (resolve
->tid
!= 0) {
556 return sd_event_get_tid(resolve
->event
, tid
);
561 static sd_resolve
*resolve_free(sd_resolve
*resolve
) {
568 while ((q
= resolve
->queries
)) {
570 resolve_query_disconnect(q
);
571 sd_resolve_query_unref(q
);
574 if (resolve
->default_resolve_ptr
)
575 *(resolve
->default_resolve_ptr
) = NULL
;
577 resolve
->dead
= true;
579 sd_resolve_detach_event(resolve
);
581 if (resolve
->fds
[REQUEST_SEND_FD
] >= 0) {
584 .type
= REQUEST_TERMINATE
,
585 .length
= sizeof req
,
588 /* Send one termination packet for each worker */
589 for (i
= 0; i
< resolve
->n_valid_workers
; i
++)
590 (void) send(resolve
->fds
[REQUEST_SEND_FD
], &req
, req
.length
, MSG_NOSIGNAL
);
593 /* Now terminate them and wait until they are gone.
594 If we get an error than most likely the thread already exited. */
595 for (i
= 0; i
< resolve
->n_valid_workers
; i
++)
596 (void) pthread_join(resolve
->workers
[i
], NULL
);
598 /* Close all communication channels */
599 close_many(resolve
->fds
, _FD_MAX
);
601 return mfree(resolve
);
604 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_resolve
, sd_resolve
, resolve_free
);
606 int sd_resolve_get_fd(sd_resolve
*resolve
) {
607 assert_return(resolve
, -EINVAL
);
608 assert_return(!resolve_pid_changed(resolve
), -ECHILD
);
610 return resolve
->fds
[RESPONSE_RECV_FD
];
613 int sd_resolve_get_events(sd_resolve
*resolve
) {
614 assert_return(resolve
, -EINVAL
);
615 assert_return(!resolve_pid_changed(resolve
), -ECHILD
);
617 return resolve
->n_queries
> resolve
->n_done
? POLLIN
: 0;
620 int sd_resolve_get_timeout(sd_resolve
*resolve
, uint64_t *usec
) {
621 assert_return(resolve
, -EINVAL
);
622 assert_return(usec
, -EINVAL
);
623 assert_return(!resolve_pid_changed(resolve
), -ECHILD
);
629 static sd_resolve_query
*lookup_query(sd_resolve
*resolve
, unsigned id
) {
634 q
= resolve
->query_array
[id
% QUERIES_MAX
];
642 static int complete_query(sd_resolve
*resolve
, sd_resolve_query
*q
) {
647 assert(q
->resolve
== resolve
);
652 resolve
->current
= sd_resolve_query_ref(q
);
656 case REQUEST_ADDRINFO
:
657 r
= getaddrinfo_done(q
);
660 case REQUEST_NAMEINFO
:
661 r
= getnameinfo_done(q
);
665 assert_not_reached();
668 resolve
->current
= NULL
;
671 resolve_query_disconnect(q
);
672 sd_resolve_query_unref(q
);
675 sd_resolve_query_unref(q
);
680 static int unserialize_addrinfo(const void **p
, size_t *length
, struct addrinfo
**ret_ai
) {
681 AddrInfoSerialization s
;
690 if (*length
< sizeof(AddrInfoSerialization
))
693 memcpy(&s
, *p
, sizeof(s
));
695 l
= sizeof(AddrInfoSerialization
) + s
.ai_addrlen
+ s
.canonname_len
;
699 ai
= new(struct addrinfo
, 1);
703 *ai
= (struct addrinfo
) {
704 .ai_flags
= s
.ai_flags
,
705 .ai_family
= s
.ai_family
,
706 .ai_socktype
= s
.ai_socktype
,
707 .ai_protocol
= s
.ai_protocol
,
708 .ai_addrlen
= s
.ai_addrlen
,
711 if (s
.ai_addrlen
> 0) {
712 ai
->ai_addr
= memdup((const uint8_t*) *p
+ sizeof(AddrInfoSerialization
), s
.ai_addrlen
);
719 if (s
.canonname_len
> 0) {
720 ai
->ai_canonname
= memdup((const uint8_t*) *p
+ sizeof(AddrInfoSerialization
) + s
.ai_addrlen
, s
.canonname_len
);
721 if (!ai
->ai_canonname
) {
730 *p
= ((const uint8_t*) *p
) + l
;
735 static int handle_response(sd_resolve
*resolve
, const Packet
*packet
, size_t length
) {
743 resp
= &packet
->rheader
;
744 assert_return(length
>= sizeof(RHeader
), -EIO
);
745 assert_return(length
== resp
->length
, -EIO
);
747 if (resp
->type
== RESPONSE_DIED
) {
748 resolve
->dead
= true;
752 assert(resolve
->n_outstanding
> 0);
753 resolve
->n_outstanding
--;
755 q
= lookup_query(resolve
, resp
->id
);
759 switch (resp
->type
) {
761 case RESPONSE_ADDRINFO
: {
762 const AddrInfoResponse
*ai_resp
= &packet
->addrinfo_response
;
765 struct addrinfo
*prev
= NULL
;
767 assert_return(length
>= sizeof(AddrInfoResponse
), -EBADMSG
);
768 assert_return(q
->type
== REQUEST_ADDRINFO
, -EBADMSG
);
770 query_assign_errno(q
, ai_resp
->ret
, ai_resp
->_errno
, ai_resp
->_h_errno
);
772 l
= length
- sizeof(AddrInfoResponse
);
773 p
= (const uint8_t*) resp
+ sizeof(AddrInfoResponse
);
776 struct addrinfo
*ai
= NULL
;
778 r
= unserialize_addrinfo(&p
, &l
, &ai
);
780 query_assign_errno(q
, EAI_SYSTEM
, r
, 0);
781 freeaddrinfo(q
->addrinfo
);
794 return complete_query(resolve
, q
);
797 case RESPONSE_NAMEINFO
: {
798 const NameInfoResponse
*ni_resp
= &packet
->nameinfo_response
;
800 assert_return(length
>= sizeof(NameInfoResponse
), -EBADMSG
);
801 assert_return(q
->type
== REQUEST_NAMEINFO
, -EBADMSG
);
803 if (ni_resp
->hostlen
> DNS_HOSTNAME_MAX
||
804 ni_resp
->servlen
> DNS_HOSTNAME_MAX
||
805 sizeof(NameInfoResponse
) + ni_resp
->hostlen
+ ni_resp
->servlen
> length
)
806 query_assign_errno(q
, EAI_SYSTEM
, EIO
, 0);
808 query_assign_errno(q
, ni_resp
->ret
, ni_resp
->_errno
, ni_resp
->_h_errno
);
810 if (ni_resp
->hostlen
> 0) {
811 q
->host
= strndup((const char*) ni_resp
+ sizeof(NameInfoResponse
),
814 query_assign_errno(q
, EAI_MEMORY
, ENOMEM
, 0);
817 if (ni_resp
->servlen
> 0) {
818 q
->serv
= strndup((const char*) ni_resp
+ sizeof(NameInfoResponse
) + ni_resp
->hostlen
,
821 query_assign_errno(q
, EAI_MEMORY
, ENOMEM
, 0);
825 return complete_query(resolve
, q
);
833 int sd_resolve_process(sd_resolve
*resolve
) {
834 RESOLVE_DONT_DESTROY(resolve
);
838 uint8_t space
[BUFSIZE
];
843 assert_return(resolve
, -EINVAL
);
844 assert_return(!resolve_pid_changed(resolve
), -ECHILD
);
846 /* We don't allow recursively invoking sd_resolve_process(). */
847 assert_return(!resolve
->current
, -EBUSY
);
849 l
= recv(resolve
->fds
[RESPONSE_RECV_FD
], &buf
, sizeof buf
, 0);
851 if (ERRNO_IS_TRANSIENT(errno
))
857 return -ECONNREFUSED
;
859 r
= handle_response(resolve
, &buf
.packet
, (size_t) l
);
866 int sd_resolve_wait(sd_resolve
*resolve
, uint64_t timeout_usec
) {
869 assert_return(resolve
, -EINVAL
);
870 assert_return(!resolve_pid_changed(resolve
), -ECHILD
);
872 if (resolve
->n_done
>= resolve
->n_queries
)
876 r
= fd_wait_for_event(resolve
->fds
[RESPONSE_RECV_FD
], POLLIN
, timeout_usec
);
877 } while (r
== -EINTR
);
884 return sd_resolve_process(resolve
);
887 static int alloc_query(sd_resolve
*resolve
, bool floating
, sd_resolve_query
**_q
) {
894 if (resolve
->n_queries
>= QUERIES_MAX
)
897 r
= start_threads(resolve
, 1);
901 while (resolve
->query_array
[resolve
->current_id
% QUERIES_MAX
])
902 resolve
->current_id
++;
904 q
= resolve
->query_array
[resolve
->current_id
% QUERIES_MAX
] = new0(sd_resolve_query
, 1);
909 q
->resolve
= resolve
;
910 q
->floating
= floating
;
911 q
->id
= resolve
->current_id
++;
914 sd_resolve_ref(resolve
);
916 LIST_PREPEND(queries
, resolve
->queries
, q
);
917 resolve
->n_queries
++;
923 int resolve_getaddrinfo_with_destroy_callback(
925 sd_resolve_query
**ret_query
,
926 const char *node
, const char *service
,
927 const struct addrinfo
*hints
,
928 sd_resolve_getaddrinfo_handler_t callback
,
929 sd_resolve_destroy_t destroy_callback
,
932 _cleanup_(sd_resolve_query_unrefp
) sd_resolve_query
*q
= NULL
;
933 size_t node_len
, service_len
;
934 AddrInfoRequest req
= {};
936 struct msghdr mh
= {};
939 assert_return(resolve
, -EINVAL
);
940 assert_return(node
|| service
, -EINVAL
);
941 assert_return(callback
, -EINVAL
);
942 assert_return(!resolve_pid_changed(resolve
), -ECHILD
);
944 r
= alloc_query(resolve
, !ret_query
, &q
);
948 q
->type
= REQUEST_ADDRINFO
;
949 q
->getaddrinfo_handler
= callback
;
950 q
->userdata
= userdata
;
952 node_len
= node
? strlen(node
) + 1 : 0;
953 service_len
= service
? strlen(service
) + 1 : 0;
955 req
= (AddrInfoRequest
) {
956 .node_len
= node_len
,
957 .service_len
= service_len
,
960 .header
.type
= REQUEST_ADDRINFO
,
961 .header
.length
= sizeof(AddrInfoRequest
) + node_len
+ service_len
,
963 .hints_valid
= hints
,
964 .ai_flags
= hints
? hints
->ai_flags
: 0,
965 .ai_family
= hints
? hints
->ai_family
: 0,
966 .ai_socktype
= hints
? hints
->ai_socktype
: 0,
967 .ai_protocol
= hints
? hints
->ai_protocol
: 0,
970 msan_unpoison(&req
, sizeof(req
));
972 iov
[mh
.msg_iovlen
++] = IOVEC_MAKE(&req
, sizeof(AddrInfoRequest
));
974 iov
[mh
.msg_iovlen
++] = IOVEC_MAKE((void*) node
, req
.node_len
);
976 iov
[mh
.msg_iovlen
++] = IOVEC_MAKE((void*) service
, req
.service_len
);
979 if (sendmsg(resolve
->fds
[REQUEST_SEND_FD
], &mh
, MSG_NOSIGNAL
) < 0)
982 resolve
->n_outstanding
++;
983 q
->destroy_callback
= destroy_callback
;
993 int sd_resolve_getaddrinfo(
995 sd_resolve_query
**ret_query
,
996 const char *node
, const char *service
,
997 const struct addrinfo
*hints
,
998 sd_resolve_getaddrinfo_handler_t callback
,
1001 return resolve_getaddrinfo_with_destroy_callback(resolve
, ret_query
, node
, service
, hints
, callback
, NULL
, userdata
);
1004 static int getaddrinfo_done(sd_resolve_query
* q
) {
1007 assert(q
->getaddrinfo_handler
);
1010 h_errno
= q
->_h_errno
;
1012 return q
->getaddrinfo_handler(q
, q
->ret
, q
->addrinfo
, q
->userdata
);
1015 int resolve_getnameinfo_with_destroy_callback(
1016 sd_resolve
*resolve
,
1017 sd_resolve_query
**ret_query
,
1018 const struct sockaddr
*sa
, socklen_t salen
,
1021 sd_resolve_getnameinfo_handler_t callback
,
1022 sd_resolve_destroy_t destroy_callback
,
1025 _cleanup_(sd_resolve_query_unrefp
) sd_resolve_query
*q
= NULL
;
1026 NameInfoRequest req
= {};
1027 struct iovec iov
[2];
1031 assert_return(resolve
, -EINVAL
);
1032 assert_return(sa
, -EINVAL
);
1033 assert_return(salen
>= sizeof(struct sockaddr
), -EINVAL
);
1034 assert_return(salen
<= sizeof(union sockaddr_union
), -EINVAL
);
1035 assert_return((get
& ~SD_RESOLVE_GET_BOTH
) == 0, -EINVAL
);
1036 assert_return(callback
, -EINVAL
);
1037 assert_return(!resolve_pid_changed(resolve
), -ECHILD
);
1039 r
= alloc_query(resolve
, !ret_query
, &q
);
1043 q
->type
= REQUEST_NAMEINFO
;
1044 q
->getnameinfo_handler
= callback
;
1045 q
->userdata
= userdata
;
1047 req
= (NameInfoRequest
) {
1049 .header
.type
= REQUEST_NAMEINFO
,
1050 .header
.length
= sizeof(NameInfoRequest
) + salen
,
1053 .sockaddr_len
= salen
,
1054 .gethost
= !!(get
& SD_RESOLVE_GET_HOST
),
1055 .getserv
= !!(get
& SD_RESOLVE_GET_SERVICE
),
1058 msan_unpoison(&req
, sizeof(req
));
1060 iov
[0] = IOVEC_MAKE(&req
, sizeof(NameInfoRequest
));
1061 iov
[1] = IOVEC_MAKE((void*) sa
, salen
);
1063 mh
= (struct msghdr
) {
1065 .msg_iovlen
= ELEMENTSOF(iov
)
1068 if (sendmsg(resolve
->fds
[REQUEST_SEND_FD
], &mh
, MSG_NOSIGNAL
) < 0)
1071 resolve
->n_outstanding
++;
1072 q
->destroy_callback
= destroy_callback
;
1082 int sd_resolve_getnameinfo(
1083 sd_resolve
*resolve
,
1084 sd_resolve_query
**ret_query
,
1085 const struct sockaddr
*sa
, socklen_t salen
,
1088 sd_resolve_getnameinfo_handler_t callback
,
1091 return resolve_getnameinfo_with_destroy_callback(resolve
, ret_query
, sa
, salen
, flags
, get
, callback
, NULL
, userdata
);
1094 static int getnameinfo_done(sd_resolve_query
*q
) {
1098 assert(q
->getnameinfo_handler
);
1101 h_errno
= q
->_h_errno
;
1103 return q
->getnameinfo_handler(q
, q
->ret
, q
->host
, q
->serv
, q
->userdata
);
1106 static void resolve_freeaddrinfo(struct addrinfo
*ai
) {
1108 struct addrinfo
*next
= ai
->ai_next
;
1111 free(ai
->ai_canonname
);
1117 static void resolve_query_disconnect(sd_resolve_query
*q
) {
1118 sd_resolve
*resolve
;
1126 resolve
= q
->resolve
;
1127 assert(resolve
->n_queries
> 0);
1130 assert(resolve
->n_done
> 0);
1134 i
= q
->id
% QUERIES_MAX
;
1135 assert(resolve
->query_array
[i
] == q
);
1136 resolve
->query_array
[i
] = NULL
;
1137 LIST_REMOVE(queries
, resolve
->queries
, q
);
1138 resolve
->n_queries
--;
1142 sd_resolve_unref(resolve
);
1145 static sd_resolve_query
*resolve_query_free(sd_resolve_query
*q
) {
1148 resolve_query_disconnect(q
);
1150 if (q
->destroy_callback
)
1151 q
->destroy_callback(q
->userdata
);
1153 resolve_freeaddrinfo(q
->addrinfo
);
1160 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_resolve_query
, sd_resolve_query
, resolve_query_free
);
1162 int sd_resolve_query_is_done(sd_resolve_query
*q
) {
1163 assert_return(q
, -EINVAL
);
1164 assert_return(!resolve_pid_changed(q
->resolve
), -ECHILD
);
1169 void* sd_resolve_query_set_userdata(sd_resolve_query
*q
, void *userdata
) {
1172 assert_return(q
, NULL
);
1173 assert_return(!resolve_pid_changed(q
->resolve
), NULL
);
1176 q
->userdata
= userdata
;
1181 void* sd_resolve_query_get_userdata(sd_resolve_query
*q
) {
1182 assert_return(q
, NULL
);
1183 assert_return(!resolve_pid_changed(q
->resolve
), NULL
);
1188 sd_resolve
*sd_resolve_query_get_resolve(sd_resolve_query
*q
) {
1189 assert_return(q
, NULL
);
1190 assert_return(!resolve_pid_changed(q
->resolve
), NULL
);
1195 int sd_resolve_query_get_destroy_callback(sd_resolve_query
*q
, sd_resolve_destroy_t
*destroy_callback
) {
1196 assert_return(q
, -EINVAL
);
1198 if (destroy_callback
)
1199 *destroy_callback
= q
->destroy_callback
;
1201 return !!q
->destroy_callback
;
1204 int sd_resolve_query_set_destroy_callback(sd_resolve_query
*q
, sd_resolve_destroy_t destroy_callback
) {
1205 assert_return(q
, -EINVAL
);
1207 q
->destroy_callback
= destroy_callback
;
1211 int sd_resolve_query_get_floating(sd_resolve_query
*q
) {
1212 assert_return(q
, -EINVAL
);
1217 int sd_resolve_query_set_floating(sd_resolve_query
*q
, int b
) {
1218 assert_return(q
, -EINVAL
);
1220 if (q
->floating
== !!b
)
1223 if (!q
->resolve
) /* Already disconnected */
1229 sd_resolve_query_ref(q
);
1230 sd_resolve_unref(q
->resolve
);
1232 sd_resolve_ref(q
->resolve
);
1233 sd_resolve_query_unref(q
);
1239 static int io_callback(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
1240 sd_resolve
*resolve
= ASSERT_PTR(userdata
);
1243 r
= sd_resolve_process(resolve
);
1250 int sd_resolve_attach_event(sd_resolve
*resolve
, sd_event
*event
, int64_t priority
) {
1253 assert_return(resolve
, -EINVAL
);
1254 assert_return(!resolve
->event
, -EBUSY
);
1256 assert(!resolve
->event_source
);
1259 resolve
->event
= sd_event_ref(event
);
1261 r
= sd_event_default(&resolve
->event
);
1266 r
= sd_event_add_io(resolve
->event
, &resolve
->event_source
, resolve
->fds
[RESPONSE_RECV_FD
], POLLIN
, io_callback
, resolve
);
1270 r
= sd_event_source_set_priority(resolve
->event_source
, priority
);
1277 sd_resolve_detach_event(resolve
);
1281 int sd_resolve_detach_event(sd_resolve
*resolve
) {
1282 assert_return(resolve
, -EINVAL
);
1284 if (!resolve
->event
)
1287 resolve
->event_source
= sd_event_source_disable_unref(resolve
->event_source
);
1288 resolve
->event
= sd_event_unref(resolve
->event
);
1292 sd_event
*sd_resolve_get_event(sd_resolve
*resolve
) {
1293 assert_return(resolve
, NULL
);
1295 return resolve
->event
;