1 /* SPDX-License-Identifier: LGPL-2.1+ */
12 #include <sys/prctl.h>
15 #include "sd-resolve.h"
17 #include "alloc-util.h"
18 #include "dns-domain.h"
23 #include "socket-util.h"
25 #include "process-util.h"
27 #define WORKERS_MIN 1U
28 #define WORKERS_MAX 16U
29 #define QUERIES_MAX 256U
30 #define BUFSIZE 10240U
57 pthread_t workers
[WORKERS_MAX
];
58 unsigned n_valid_workers
;
61 sd_resolve_query
* query_array
[QUERIES_MAX
];
62 unsigned n_queries
, n_done
, n_outstanding
;
64 sd_event_source
*event_source
;
67 sd_resolve_query
*current
;
69 sd_resolve
**default_resolve_ptr
;
72 LIST_HEAD(sd_resolve_query
, queries
);
75 struct sd_resolve_query
{
88 struct addrinfo
*addrinfo
;
92 sd_resolve_getaddrinfo_handler_t getaddrinfo_handler
;
93 sd_resolve_getnameinfo_handler_t getnameinfo_handler
;
98 LIST_FIELDS(sd_resolve_query
, queries
);
101 typedef struct RHeader
{
107 typedef struct AddrInfoRequest
{
108 struct RHeader header
;
114 size_t node_len
, service_len
;
117 typedef struct AddrInfoResponse
{
118 struct RHeader header
;
122 /* followed by addrinfo_serialization[] */
125 typedef struct AddrInfoSerialization
{
131 size_t canonname_len
;
132 /* Followed by ai_addr amd ai_canonname with variable lengths */
133 } AddrInfoSerialization
;
135 typedef struct NameInfoRequest
{
136 struct RHeader header
;
138 socklen_t sockaddr_len
;
139 bool gethost
:1, getserv
:1;
142 typedef struct NameInfoResponse
{
143 struct RHeader header
;
144 size_t hostlen
, servlen
;
150 typedef union Packet
{
152 AddrInfoRequest addrinfo_request
;
153 AddrInfoResponse addrinfo_response
;
154 NameInfoRequest nameinfo_request
;
155 NameInfoResponse nameinfo_response
;
158 static int getaddrinfo_done(sd_resolve_query
* q
);
159 static int getnameinfo_done(sd_resolve_query
*q
);
161 static void resolve_query_disconnect(sd_resolve_query
*q
);
163 #define RESOLVE_DONT_DESTROY(resolve) \
164 _cleanup_(sd_resolve_unrefp) _unused_ sd_resolve *_dont_destroy_##resolve = sd_resolve_ref(resolve)
166 static void query_assign_errno(sd_resolve_query
*q
, int ret
, int error
, int h_error
) {
170 q
->_errno
= abs(error
);
171 q
->_h_errno
= h_error
;
174 static int send_died(int out_fd
) {
176 .type
= RESPONSE_DIED
,
177 .length
= sizeof(RHeader
),
182 if (send(out_fd
, &rh
, rh
.length
, MSG_NOSIGNAL
) < 0)
188 static void *serialize_addrinfo(void *p
, const struct addrinfo
*ai
, size_t *length
, size_t maxlength
) {
189 AddrInfoSerialization s
;
195 assert(*length
<= maxlength
);
197 cnl
= ai
->ai_canonname
? strlen(ai
->ai_canonname
)+1 : 0;
198 l
= sizeof(AddrInfoSerialization
) + ai
->ai_addrlen
+ cnl
;
200 if (*length
+ l
> maxlength
)
203 s
= (AddrInfoSerialization
) {
204 .ai_flags
= ai
->ai_flags
,
205 .ai_family
= ai
->ai_family
,
206 .ai_socktype
= ai
->ai_socktype
,
207 .ai_protocol
= ai
->ai_protocol
,
208 .ai_addrlen
= ai
->ai_addrlen
,
209 .canonname_len
= cnl
,
212 memcpy((uint8_t*) p
, &s
, sizeof(AddrInfoSerialization
));
213 memcpy((uint8_t*) p
+ sizeof(AddrInfoSerialization
), ai
->ai_addr
, ai
->ai_addrlen
);
214 memcpy_safe((char*) p
+ sizeof(AddrInfoSerialization
) + ai
->ai_addrlen
,
215 ai
->ai_canonname
, cnl
);
218 return (uint8_t*) p
+ l
;
221 static int send_addrinfo_reply(
229 AddrInfoResponse resp
= {};
231 AddrInfoSerialization ais
;
232 uint8_t space
[BUFSIZE
];
239 resp
= (AddrInfoResponse
) {
240 .header
.type
= RESPONSE_ADDRINFO
,
242 .header
.length
= sizeof(AddrInfoResponse
),
245 ._h_errno
= _h_errno
,
248 if (ret
== 0 && ai
) {
252 for (k
= ai
; k
; k
= k
->ai_next
) {
253 p
= serialize_addrinfo(p
, k
, &resp
.header
.length
, (uint8_t*) &buffer
+ BUFSIZE
- (uint8_t*) p
);
264 iov
[0] = (struct iovec
) { .iov_base
= &resp
, .iov_len
= sizeof(AddrInfoResponse
) };
265 iov
[1] = (struct iovec
) { .iov_base
= &buffer
, .iov_len
= resp
.header
.length
- sizeof(AddrInfoResponse
) };
267 mh
= (struct msghdr
) { .msg_iov
= iov
, .msg_iovlen
= ELEMENTSOF(iov
) };
269 if (sendmsg(out_fd
, &mh
, MSG_NOSIGNAL
) < 0)
275 static int send_nameinfo_reply(
284 NameInfoResponse resp
= {};
291 sl
= serv
? strlen(serv
)+1 : 0;
292 hl
= host
? strlen(host
)+1 : 0;
294 resp
= (NameInfoResponse
) {
295 .header
.type
= RESPONSE_NAMEINFO
,
297 .header
.length
= sizeof(NameInfoResponse
) + hl
+ sl
,
302 ._h_errno
= _h_errno
,
305 iov
[0] = (struct iovec
) { .iov_base
= &resp
, .iov_len
= sizeof(NameInfoResponse
) };
306 iov
[1] = (struct iovec
) { .iov_base
= (void*) host
, .iov_len
= hl
};
307 iov
[2] = (struct iovec
) { .iov_base
= (void*) serv
, .iov_len
= sl
};
309 mh
= (struct msghdr
) { .msg_iov
= iov
, .msg_iovlen
= ELEMENTSOF(iov
) };
311 if (sendmsg(out_fd
, &mh
, MSG_NOSIGNAL
) < 0)
317 static int handle_request(int out_fd
, const Packet
*packet
, size_t length
) {
323 req
= &packet
->rheader
;
325 assert_return(length
>= sizeof(RHeader
), -EIO
);
326 assert_return(length
== req
->length
, -EIO
);
330 case REQUEST_ADDRINFO
: {
331 const AddrInfoRequest
*ai_req
= &packet
->addrinfo_request
;
332 struct addrinfo hints
, *result
= NULL
;
333 const char *node
, *service
;
336 assert_return(length
>= sizeof(AddrInfoRequest
), -EBADMSG
);
337 assert_return(length
== sizeof(AddrInfoRequest
) + ai_req
->node_len
+ ai_req
->service_len
, -EBADMSG
);
339 hints
= (struct addrinfo
) {
340 .ai_flags
= ai_req
->ai_flags
,
341 .ai_family
= ai_req
->ai_family
,
342 .ai_socktype
= ai_req
->ai_socktype
,
343 .ai_protocol
= ai_req
->ai_protocol
,
346 node
= ai_req
->node_len
? (const char*) ai_req
+ sizeof(AddrInfoRequest
) : NULL
;
347 service
= ai_req
->service_len
? (const char*) ai_req
+ sizeof(AddrInfoRequest
) + ai_req
->node_len
: NULL
;
349 ret
= getaddrinfo(node
, service
,
350 ai_req
->hints_valid
? &hints
: NULL
,
353 /* send_addrinfo_reply() frees result */
354 return send_addrinfo_reply(out_fd
, req
->id
, ret
, result
, errno
, h_errno
);
357 case REQUEST_NAMEINFO
: {
358 const NameInfoRequest
*ni_req
= &packet
->nameinfo_request
;
359 char hostbuf
[NI_MAXHOST
], servbuf
[NI_MAXSERV
];
360 union sockaddr_union sa
;
363 assert_return(length
>= sizeof(NameInfoRequest
), -EBADMSG
);
364 assert_return(length
== sizeof(NameInfoRequest
) + ni_req
->sockaddr_len
, -EBADMSG
);
365 assert_return(ni_req
->sockaddr_len
<= sizeof(sa
), -EBADMSG
);
367 memcpy(&sa
, (const uint8_t *) ni_req
+ sizeof(NameInfoRequest
), ni_req
->sockaddr_len
);
369 ret
= getnameinfo(&sa
.sa
, ni_req
->sockaddr_len
,
370 ni_req
->gethost
? hostbuf
: NULL
, ni_req
->gethost
? sizeof(hostbuf
) : 0,
371 ni_req
->getserv
? servbuf
: NULL
, ni_req
->getserv
? sizeof(servbuf
) : 0,
374 return send_nameinfo_reply(out_fd
, req
->id
, ret
,
375 ret
== 0 && ni_req
->gethost
? hostbuf
: NULL
,
376 ret
== 0 && ni_req
->getserv
? servbuf
: NULL
,
380 case REQUEST_TERMINATE
:
385 assert_not_reached("Unknown request");
391 static void* thread_worker(void *p
) {
392 sd_resolve
*resolve
= p
;
394 /* Assign a pretty name to this thread */
395 (void) pthread_setname_np(pthread_self(), "sd-resolve");
397 while (!resolve
->dead
) {
400 uint8_t space
[BUFSIZE
];
404 length
= recv(resolve
->fds
[REQUEST_RECV_FD
], &buf
, sizeof buf
, 0);
414 if (handle_request(resolve
->fds
[RESPONSE_SEND_FD
], &buf
.packet
, (size_t) length
) < 0)
418 send_died(resolve
->fds
[RESPONSE_SEND_FD
]);
423 static int start_threads(sd_resolve
*resolve
, unsigned extra
) {
424 sigset_t ss
, saved_ss
;
428 if (sigfillset(&ss
) < 0)
431 /* No signals in forked off threads please. We set the mask before forking, so that the threads never exist
432 * with a different mask than a fully blocked one */
433 r
= pthread_sigmask(SIG_BLOCK
, &ss
, &saved_ss
);
437 n
= resolve
->n_outstanding
+ extra
;
438 n
= CLAMP(n
, WORKERS_MIN
, WORKERS_MAX
);
440 while (resolve
->n_valid_workers
< n
) {
441 r
= pthread_create(&resolve
->workers
[resolve
->n_valid_workers
], NULL
, thread_worker
, resolve
);
447 resolve
->n_valid_workers
++;
453 k
= pthread_sigmask(SIG_SETMASK
, &saved_ss
, NULL
);
460 static bool resolve_pid_changed(sd_resolve
*r
) {
463 /* We don't support people creating a resolver and keeping it
464 * around after fork(). Let's complain. */
466 return r
->original_pid
!= getpid_cached();
469 _public_
int sd_resolve_new(sd_resolve
**ret
) {
470 _cleanup_(sd_resolve_unrefp
) sd_resolve
*resolve
= NULL
;
473 assert_return(ret
, -EINVAL
);
475 resolve
= new0(sd_resolve
, 1);
480 resolve
->original_pid
= getpid_cached();
482 for (i
= 0; i
< _FD_MAX
; i
++)
483 resolve
->fds
[i
] = -1;
485 if (socketpair(PF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0, resolve
->fds
+ REQUEST_RECV_FD
) < 0)
488 if (socketpair(PF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0, resolve
->fds
+ RESPONSE_RECV_FD
) < 0)
491 for (i
= 0; i
< _FD_MAX
; i
++)
492 resolve
->fds
[i
] = fd_move_above_stdio(resolve
->fds
[i
]);
494 (void) fd_inc_sndbuf(resolve
->fds
[REQUEST_SEND_FD
], QUERIES_MAX
* BUFSIZE
);
495 (void) fd_inc_rcvbuf(resolve
->fds
[REQUEST_RECV_FD
], QUERIES_MAX
* BUFSIZE
);
496 (void) fd_inc_sndbuf(resolve
->fds
[RESPONSE_SEND_FD
], QUERIES_MAX
* BUFSIZE
);
497 (void) fd_inc_rcvbuf(resolve
->fds
[RESPONSE_RECV_FD
], QUERIES_MAX
* BUFSIZE
);
499 (void) fd_nonblock(resolve
->fds
[RESPONSE_RECV_FD
], true);
501 *ret
= TAKE_PTR(resolve
);
505 _public_
int sd_resolve_default(sd_resolve
**ret
) {
506 static thread_local sd_resolve
*default_resolve
= NULL
;
507 sd_resolve
*e
= NULL
;
511 return !!default_resolve
;
513 if (default_resolve
) {
514 *ret
= sd_resolve_ref(default_resolve
);
518 r
= sd_resolve_new(&e
);
522 e
->default_resolve_ptr
= &default_resolve
;
530 _public_
int sd_resolve_get_tid(sd_resolve
*resolve
, pid_t
*tid
) {
531 assert_return(resolve
, -EINVAL
);
532 assert_return(tid
, -EINVAL
);
533 assert_return(!resolve_pid_changed(resolve
), -ECHILD
);
535 if (resolve
->tid
!= 0) {
541 return sd_event_get_tid(resolve
->event
, tid
);
546 static void resolve_free(sd_resolve
*resolve
) {
553 while ((q
= resolve
->queries
)) {
555 resolve_query_disconnect(q
);
556 sd_resolve_query_unref(q
);
559 if (resolve
->default_resolve_ptr
)
560 *(resolve
->default_resolve_ptr
) = NULL
;
562 resolve
->dead
= true;
564 sd_resolve_detach_event(resolve
);
566 if (resolve
->fds
[REQUEST_SEND_FD
] >= 0) {
569 .type
= REQUEST_TERMINATE
,
570 .length
= sizeof req
,
573 /* Send one termination packet for each worker */
574 for (i
= 0; i
< resolve
->n_valid_workers
; i
++)
575 (void) send(resolve
->fds
[REQUEST_SEND_FD
], &req
, req
.length
, MSG_NOSIGNAL
);
578 /* Now terminate them and wait until they are gone.
579 If we get an error than most likely the thread already exited. */
580 for (i
= 0; i
< resolve
->n_valid_workers
; i
++)
581 (void) pthread_join(resolve
->workers
[i
], NULL
);
583 /* Close all communication channels */
584 close_many(resolve
->fds
, _FD_MAX
);
588 _public_ sd_resolve
* sd_resolve_ref(sd_resolve
*resolve
) {
589 assert_return(resolve
, NULL
);
591 assert(resolve
->n_ref
>= 1);
597 _public_ sd_resolve
* sd_resolve_unref(sd_resolve
*resolve
) {
601 assert(resolve
->n_ref
>= 1);
604 if (resolve
->n_ref
<= 0)
605 resolve_free(resolve
);
610 _public_
int sd_resolve_get_fd(sd_resolve
*resolve
) {
611 assert_return(resolve
, -EINVAL
);
612 assert_return(!resolve_pid_changed(resolve
), -ECHILD
);
614 return resolve
->fds
[RESPONSE_RECV_FD
];
617 _public_
int sd_resolve_get_events(sd_resolve
*resolve
) {
618 assert_return(resolve
, -EINVAL
);
619 assert_return(!resolve_pid_changed(resolve
), -ECHILD
);
621 return resolve
->n_queries
> resolve
->n_done
? POLLIN
: 0;
624 _public_
int sd_resolve_get_timeout(sd_resolve
*resolve
, uint64_t *usec
) {
625 assert_return(resolve
, -EINVAL
);
626 assert_return(usec
, -EINVAL
);
627 assert_return(!resolve_pid_changed(resolve
), -ECHILD
);
629 *usec
= (uint64_t) -1;
633 static sd_resolve_query
*lookup_query(sd_resolve
*resolve
, unsigned id
) {
638 q
= resolve
->query_array
[id
% QUERIES_MAX
];
646 static int complete_query(sd_resolve
*resolve
, sd_resolve_query
*q
) {
651 assert(q
->resolve
== resolve
);
656 resolve
->current
= sd_resolve_query_ref(q
);
660 case REQUEST_ADDRINFO
:
661 r
= getaddrinfo_done(q
);
664 case REQUEST_NAMEINFO
:
665 r
= getnameinfo_done(q
);
669 assert_not_reached("Cannot complete unknown query type");
672 resolve
->current
= NULL
;
675 resolve_query_disconnect(q
);
676 sd_resolve_query_unref(q
);
679 sd_resolve_query_unref(q
);
684 static int unserialize_addrinfo(const void **p
, size_t *length
, struct addrinfo
**ret_ai
) {
685 AddrInfoSerialization s
;
694 if (*length
< sizeof(AddrInfoSerialization
))
697 memcpy(&s
, *p
, sizeof(s
));
699 l
= sizeof(AddrInfoSerialization
) + s
.ai_addrlen
+ s
.canonname_len
;
703 ai
= new(struct addrinfo
, 1);
707 *ai
= (struct addrinfo
) {
708 .ai_flags
= s
.ai_flags
,
709 .ai_family
= s
.ai_family
,
710 .ai_socktype
= s
.ai_socktype
,
711 .ai_protocol
= s
.ai_protocol
,
712 .ai_addrlen
= s
.ai_addrlen
,
715 if (s
.ai_addrlen
> 0) {
716 ai
->ai_addr
= memdup((const uint8_t*) *p
+ sizeof(AddrInfoSerialization
), s
.ai_addrlen
);
723 if (s
.canonname_len
> 0) {
724 ai
->ai_canonname
= memdup((const uint8_t*) *p
+ sizeof(AddrInfoSerialization
) + s
.ai_addrlen
, s
.canonname_len
);
725 if (!ai
->ai_canonname
) {
734 *p
= ((const uint8_t*) *p
) + l
;
739 static int handle_response(sd_resolve
*resolve
, const Packet
*packet
, size_t length
) {
747 resp
= &packet
->rheader
;
748 assert_return(length
>= sizeof(RHeader
), -EIO
);
749 assert_return(length
== resp
->length
, -EIO
);
751 if (resp
->type
== RESPONSE_DIED
) {
752 resolve
->dead
= true;
756 assert(resolve
->n_outstanding
> 0);
757 resolve
->n_outstanding
--;
759 q
= lookup_query(resolve
, resp
->id
);
763 switch (resp
->type
) {
765 case RESPONSE_ADDRINFO
: {
766 const AddrInfoResponse
*ai_resp
= &packet
->addrinfo_response
;
769 struct addrinfo
*prev
= NULL
;
771 assert_return(length
>= sizeof(AddrInfoResponse
), -EBADMSG
);
772 assert_return(q
->type
== REQUEST_ADDRINFO
, -EBADMSG
);
774 query_assign_errno(q
, ai_resp
->ret
, ai_resp
->_errno
, ai_resp
->_h_errno
);
776 l
= length
- sizeof(AddrInfoResponse
);
777 p
= (const uint8_t*) resp
+ sizeof(AddrInfoResponse
);
780 struct addrinfo
*ai
= NULL
;
782 r
= unserialize_addrinfo(&p
, &l
, &ai
);
784 query_assign_errno(q
, EAI_SYSTEM
, r
, 0);
785 freeaddrinfo(q
->addrinfo
);
798 return complete_query(resolve
, q
);
801 case RESPONSE_NAMEINFO
: {
802 const NameInfoResponse
*ni_resp
= &packet
->nameinfo_response
;
804 assert_return(length
>= sizeof(NameInfoResponse
), -EBADMSG
);
805 assert_return(q
->type
== REQUEST_NAMEINFO
, -EBADMSG
);
807 if (ni_resp
->hostlen
> DNS_HOSTNAME_MAX
||
808 ni_resp
->servlen
> DNS_HOSTNAME_MAX
||
809 sizeof(NameInfoResponse
) + ni_resp
->hostlen
+ ni_resp
->servlen
> length
)
810 query_assign_errno(q
, EAI_SYSTEM
, EIO
, 0);
812 query_assign_errno(q
, ni_resp
->ret
, ni_resp
->_errno
, ni_resp
->_h_errno
);
814 if (ni_resp
->hostlen
> 0) {
815 q
->host
= strndup((const char*) ni_resp
+ sizeof(NameInfoResponse
),
818 query_assign_errno(q
, EAI_MEMORY
, ENOMEM
, 0);
821 if (ni_resp
->servlen
> 0) {
822 q
->serv
= strndup((const char*) ni_resp
+ sizeof(NameInfoResponse
) + ni_resp
->hostlen
,
825 query_assign_errno(q
, EAI_MEMORY
, ENOMEM
, 0);
829 return complete_query(resolve
, q
);
837 _public_
int sd_resolve_process(sd_resolve
*resolve
) {
838 RESOLVE_DONT_DESTROY(resolve
);
842 uint8_t space
[BUFSIZE
];
847 assert_return(resolve
, -EINVAL
);
848 assert_return(!resolve_pid_changed(resolve
), -ECHILD
);
850 /* We don't allow recursively invoking sd_resolve_process(). */
851 assert_return(!resolve
->current
, -EBUSY
);
853 l
= recv(resolve
->fds
[RESPONSE_RECV_FD
], &buf
, sizeof buf
, 0);
861 return -ECONNREFUSED
;
863 r
= handle_response(resolve
, &buf
.packet
, (size_t) l
);
870 _public_
int sd_resolve_wait(sd_resolve
*resolve
, uint64_t timeout_usec
) {
873 assert_return(resolve
, -EINVAL
);
874 assert_return(!resolve_pid_changed(resolve
), -ECHILD
);
876 if (resolve
->n_done
>= resolve
->n_queries
)
880 r
= fd_wait_for_event(resolve
->fds
[RESPONSE_RECV_FD
], POLLIN
, timeout_usec
);
881 } while (r
== -EINTR
);
888 return sd_resolve_process(resolve
);
891 static int alloc_query(sd_resolve
*resolve
, bool floating
, sd_resolve_query
**_q
) {
898 if (resolve
->n_queries
>= QUERIES_MAX
)
901 r
= start_threads(resolve
, 1);
905 while (resolve
->query_array
[resolve
->current_id
% QUERIES_MAX
])
906 resolve
->current_id
++;
908 q
= resolve
->query_array
[resolve
->current_id
% QUERIES_MAX
] = new0(sd_resolve_query
, 1);
913 q
->resolve
= resolve
;
914 q
->floating
= floating
;
915 q
->id
= resolve
->current_id
++;
918 sd_resolve_ref(resolve
);
920 LIST_PREPEND(queries
, resolve
->queries
, q
);
921 resolve
->n_queries
++;
927 _public_
int sd_resolve_getaddrinfo(
929 sd_resolve_query
**_q
,
930 const char *node
, const char *service
,
931 const struct addrinfo
*hints
,
932 sd_resolve_getaddrinfo_handler_t callback
, void *userdata
) {
934 _cleanup_(sd_resolve_query_unrefp
) sd_resolve_query
*q
= NULL
;
935 AddrInfoRequest req
= {};
937 struct msghdr mh
= {};
939 size_t node_len
, service_len
;
941 assert_return(resolve
, -EINVAL
);
942 assert_return(node
|| service
, -EINVAL
);
943 assert_return(callback
, -EINVAL
);
944 assert_return(!resolve_pid_changed(resolve
), -ECHILD
);
946 r
= alloc_query(resolve
, !_q
, &q
);
950 q
->type
= REQUEST_ADDRINFO
;
951 q
->getaddrinfo_handler
= callback
;
952 q
->userdata
= userdata
;
954 node_len
= node
? strlen(node
) + 1 : 0;
955 service_len
= service
? strlen(service
) + 1 : 0;
957 req
= (AddrInfoRequest
) {
958 .node_len
= node_len
,
959 .service_len
= service_len
,
962 .header
.type
= REQUEST_ADDRINFO
,
963 .header
.length
= sizeof(AddrInfoRequest
) + node_len
+ service_len
,
965 .hints_valid
= hints
,
966 .ai_flags
= hints
? hints
->ai_flags
: 0,
967 .ai_family
= hints
? hints
->ai_family
: 0,
968 .ai_socktype
= hints
? hints
->ai_socktype
: 0,
969 .ai_protocol
= hints
? hints
->ai_protocol
: 0,
972 iov
[mh
.msg_iovlen
++] = (struct iovec
) { .iov_base
= &req
, .iov_len
= sizeof(AddrInfoRequest
) };
974 iov
[mh
.msg_iovlen
++] = (struct iovec
) { .iov_base
= (void*) node
, .iov_len
= req
.node_len
};
976 iov
[mh
.msg_iovlen
++] = (struct iovec
) { .iov_base
= (void*) service
, .iov_len
= req
.service_len
};
979 if (sendmsg(resolve
->fds
[REQUEST_SEND_FD
], &mh
, MSG_NOSIGNAL
) < 0)
982 resolve
->n_outstanding
++;
991 static int getaddrinfo_done(sd_resolve_query
* q
) {
994 assert(q
->getaddrinfo_handler
);
997 h_errno
= q
->_h_errno
;
999 return q
->getaddrinfo_handler(q
, q
->ret
, q
->addrinfo
, q
->userdata
);
1002 _public_
int sd_resolve_getnameinfo(
1003 sd_resolve
*resolve
,
1004 sd_resolve_query
**_q
,
1005 const struct sockaddr
*sa
, socklen_t salen
,
1008 sd_resolve_getnameinfo_handler_t callback
,
1011 _cleanup_(sd_resolve_query_unrefp
) sd_resolve_query
*q
= NULL
;
1012 NameInfoRequest req
= {};
1013 struct iovec iov
[2];
1017 assert_return(resolve
, -EINVAL
);
1018 assert_return(sa
, -EINVAL
);
1019 assert_return(salen
>= sizeof(struct sockaddr
), -EINVAL
);
1020 assert_return(salen
<= sizeof(union sockaddr_union
), -EINVAL
);
1021 assert_return((get
& ~SD_RESOLVE_GET_BOTH
) == 0, -EINVAL
);
1022 assert_return(callback
, -EINVAL
);
1023 assert_return(!resolve_pid_changed(resolve
), -ECHILD
);
1025 r
= alloc_query(resolve
, !_q
, &q
);
1029 q
->type
= REQUEST_NAMEINFO
;
1030 q
->getnameinfo_handler
= callback
;
1031 q
->userdata
= userdata
;
1033 req
= (NameInfoRequest
) {
1035 .header
.type
= REQUEST_NAMEINFO
,
1036 .header
.length
= sizeof(NameInfoRequest
) + salen
,
1039 .sockaddr_len
= salen
,
1040 .gethost
= !!(get
& SD_RESOLVE_GET_HOST
),
1041 .getserv
= !!(get
& SD_RESOLVE_GET_SERVICE
),
1044 iov
[0] = (struct iovec
) { .iov_base
= &req
, .iov_len
= sizeof(NameInfoRequest
) };
1045 iov
[1] = (struct iovec
) { .iov_base
= (void*) sa
, .iov_len
= salen
};
1047 mh
= (struct msghdr
) { .msg_iov
= iov
, .msg_iovlen
= ELEMENTSOF(iov
) };
1049 if (sendmsg(resolve
->fds
[REQUEST_SEND_FD
], &mh
, MSG_NOSIGNAL
) < 0)
1055 resolve
->n_outstanding
++;
1061 static int getnameinfo_done(sd_resolve_query
*q
) {
1065 assert(q
->getnameinfo_handler
);
1068 h_errno
= q
->_h_errno
;
1070 return q
->getnameinfo_handler(q
, q
->ret
, q
->host
, q
->serv
, q
->userdata
);
1073 _public_ sd_resolve_query
* sd_resolve_query_ref(sd_resolve_query
*q
) {
1074 assert_return(q
, NULL
);
1076 assert(q
->n_ref
>= 1);
1082 static void resolve_freeaddrinfo(struct addrinfo
*ai
) {
1084 struct addrinfo
*next
= ai
->ai_next
;
1087 free(ai
->ai_canonname
);
1093 static void resolve_query_disconnect(sd_resolve_query
*q
) {
1094 sd_resolve
*resolve
;
1102 resolve
= q
->resolve
;
1103 assert(resolve
->n_queries
> 0);
1106 assert(resolve
->n_done
> 0);
1110 i
= q
->id
% QUERIES_MAX
;
1111 assert(resolve
->query_array
[i
] == q
);
1112 resolve
->query_array
[i
] = NULL
;
1113 LIST_REMOVE(queries
, resolve
->queries
, q
);
1114 resolve
->n_queries
--;
1118 sd_resolve_unref(resolve
);
1121 static void resolve_query_free(sd_resolve_query
*q
) {
1124 resolve_query_disconnect(q
);
1126 resolve_freeaddrinfo(q
->addrinfo
);
1132 _public_ sd_resolve_query
* sd_resolve_query_unref(sd_resolve_query
* q
) {
1136 assert(q
->n_ref
>= 1);
1140 resolve_query_free(q
);
1145 _public_
int sd_resolve_query_is_done(sd_resolve_query
*q
) {
1146 assert_return(q
, -EINVAL
);
1147 assert_return(!resolve_pid_changed(q
->resolve
), -ECHILD
);
1152 _public_
void* sd_resolve_query_set_userdata(sd_resolve_query
*q
, void *userdata
) {
1155 assert_return(q
, NULL
);
1156 assert_return(!resolve_pid_changed(q
->resolve
), NULL
);
1159 q
->userdata
= userdata
;
1164 _public_
void* sd_resolve_query_get_userdata(sd_resolve_query
*q
) {
1165 assert_return(q
, NULL
);
1166 assert_return(!resolve_pid_changed(q
->resolve
), NULL
);
1171 _public_ sd_resolve
*sd_resolve_query_get_resolve(sd_resolve_query
*q
) {
1172 assert_return(q
, NULL
);
1173 assert_return(!resolve_pid_changed(q
->resolve
), NULL
);
1178 static int io_callback(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
1179 sd_resolve
*resolve
= userdata
;
1184 r
= sd_resolve_process(resolve
);
1191 _public_
int sd_resolve_attach_event(sd_resolve
*resolve
, sd_event
*event
, int64_t priority
) {
1194 assert_return(resolve
, -EINVAL
);
1195 assert_return(!resolve
->event
, -EBUSY
);
1197 assert(!resolve
->event_source
);
1200 resolve
->event
= sd_event_ref(event
);
1202 r
= sd_event_default(&resolve
->event
);
1207 r
= sd_event_add_io(resolve
->event
, &resolve
->event_source
, resolve
->fds
[RESPONSE_RECV_FD
], POLLIN
, io_callback
, resolve
);
1211 r
= sd_event_source_set_priority(resolve
->event_source
, priority
);
1218 sd_resolve_detach_event(resolve
);
1222 _public_
int sd_resolve_detach_event(sd_resolve
*resolve
) {
1223 assert_return(resolve
, -EINVAL
);
1225 if (!resolve
->event
)
1228 if (resolve
->event_source
) {
1229 sd_event_source_set_enabled(resolve
->event_source
, SD_EVENT_OFF
);
1230 resolve
->event_source
= sd_event_source_unref(resolve
->event_source
);
1233 resolve
->event
= sd_event_unref(resolve
->event
);
1237 _public_ sd_event
*sd_resolve_get_event(sd_resolve
*resolve
) {
1238 assert_return(resolve
, NULL
);
1240 return resolve
->event
;