File: | build-scan/../src/libsystemd/sd-resolve/sd-resolve.c |
Warning: | line 554, column 17 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | |||
2 | /*** | |||
3 | ***/ | |||
4 | ||||
5 | #include <errno(*__errno_location ()).h> | |||
6 | #include <poll.h> | |||
7 | #include <pthread.h> | |||
8 | #include <resolv.h> | |||
9 | #include <signal.h> | |||
10 | #include <stdint.h> | |||
11 | #include <stdio.h> | |||
12 | #include <stdlib.h> | |||
13 | #include <string.h> | |||
14 | #include <sys/prctl.h> | |||
15 | #include <unistd.h> | |||
16 | ||||
17 | #include "sd-resolve.h" | |||
18 | ||||
19 | #include "alloc-util.h" | |||
20 | #include "dns-domain.h" | |||
21 | #include "fd-util.h" | |||
22 | #include "io-util.h" | |||
23 | #include "list.h" | |||
24 | #include "missing.h" | |||
25 | #include "socket-util.h" | |||
26 | #include "util.h" | |||
27 | #include "process-util.h" | |||
28 | ||||
29 | #define WORKERS_MIN1U 1U | |||
30 | #define WORKERS_MAX16U 16U | |||
31 | #define QUERIES_MAX256U 256U | |||
32 | #define BUFSIZE10240U 10240U | |||
33 | ||||
34 | typedef enum { | |||
35 | REQUEST_ADDRINFO, | |||
36 | RESPONSE_ADDRINFO, | |||
37 | REQUEST_NAMEINFO, | |||
38 | RESPONSE_NAMEINFO, | |||
39 | REQUEST_TERMINATE, | |||
40 | RESPONSE_DIED | |||
41 | } QueryType; | |||
42 | ||||
43 | enum { | |||
44 | REQUEST_RECV_FD, | |||
45 | REQUEST_SEND_FD, | |||
46 | RESPONSE_RECV_FD, | |||
47 | RESPONSE_SEND_FD, | |||
48 | _FD_MAX | |||
49 | }; | |||
50 | ||||
51 | struct sd_resolve { | |||
52 | unsigned n_ref; | |||
53 | ||||
54 | bool_Bool dead:1; | |||
55 | pid_t original_pid; | |||
56 | ||||
57 | int fds[_FD_MAX]; | |||
58 | ||||
59 | pthread_t workers[WORKERS_MAX16U]; | |||
60 | unsigned n_valid_workers; | |||
61 | ||||
62 | unsigned current_id; | |||
63 | sd_resolve_query* query_array[QUERIES_MAX256U]; | |||
64 | unsigned n_queries, n_done, n_outstanding; | |||
65 | ||||
66 | sd_event_source *event_source; | |||
67 | sd_event *event; | |||
68 | ||||
69 | sd_resolve_query *current; | |||
70 | ||||
71 | sd_resolve **default_resolve_ptr; | |||
72 | pid_t tid; | |||
73 | ||||
74 | LIST_HEAD(sd_resolve_query, queries)sd_resolve_query *queries; | |||
75 | }; | |||
76 | ||||
77 | struct sd_resolve_query { | |||
78 | unsigned n_ref; | |||
79 | ||||
80 | sd_resolve *resolve; | |||
81 | ||||
82 | QueryType type:4; | |||
83 | bool_Bool done:1; | |||
84 | bool_Bool floating:1; | |||
85 | unsigned id; | |||
86 | ||||
87 | int ret; | |||
88 | int _errno; | |||
89 | int _h_errno; | |||
90 | struct addrinfo *addrinfo; | |||
91 | char *serv, *host; | |||
92 | ||||
93 | union { | |||
94 | sd_resolve_getaddrinfo_handler_t getaddrinfo_handler; | |||
95 | sd_resolve_getnameinfo_handler_t getnameinfo_handler; | |||
96 | }; | |||
97 | ||||
98 | void *userdata; | |||
99 | ||||
100 | LIST_FIELDS(sd_resolve_query, queries)sd_resolve_query *queries_next, *queries_prev; | |||
101 | }; | |||
102 | ||||
103 | typedef struct RHeader { | |||
104 | QueryType type; | |||
105 | unsigned id; | |||
106 | size_t length; | |||
107 | } RHeader; | |||
108 | ||||
109 | typedef struct AddrInfoRequest { | |||
110 | struct RHeader header; | |||
111 | bool_Bool hints_valid; | |||
112 | int ai_flags; | |||
113 | int ai_family; | |||
114 | int ai_socktype; | |||
115 | int ai_protocol; | |||
116 | size_t node_len, service_len; | |||
117 | } AddrInfoRequest; | |||
118 | ||||
119 | typedef struct AddrInfoResponse { | |||
120 | struct RHeader header; | |||
121 | int ret; | |||
122 | int _errno; | |||
123 | int _h_errno; | |||
124 | /* followed by addrinfo_serialization[] */ | |||
125 | } AddrInfoResponse; | |||
126 | ||||
127 | typedef struct AddrInfoSerialization { | |||
128 | int ai_flags; | |||
129 | int ai_family; | |||
130 | int ai_socktype; | |||
131 | int ai_protocol; | |||
132 | size_t ai_addrlen; | |||
133 | size_t canonname_len; | |||
134 | /* Followed by ai_addr amd ai_canonname with variable lengths */ | |||
135 | } AddrInfoSerialization; | |||
136 | ||||
137 | typedef struct NameInfoRequest { | |||
138 | struct RHeader header; | |||
139 | int flags; | |||
140 | socklen_t sockaddr_len; | |||
141 | bool_Bool gethost:1, getserv:1; | |||
142 | } NameInfoRequest; | |||
143 | ||||
144 | typedef struct NameInfoResponse { | |||
145 | struct RHeader header; | |||
146 | size_t hostlen, servlen; | |||
147 | int ret; | |||
148 | int _errno; | |||
149 | int _h_errno; | |||
150 | } NameInfoResponse; | |||
151 | ||||
152 | typedef union Packet { | |||
153 | RHeader rheader; | |||
154 | AddrInfoRequest addrinfo_request; | |||
155 | AddrInfoResponse addrinfo_response; | |||
156 | NameInfoRequest nameinfo_request; | |||
157 | NameInfoResponse nameinfo_response; | |||
158 | } Packet; | |||
159 | ||||
160 | static int getaddrinfo_done(sd_resolve_query* q); | |||
161 | static int getnameinfo_done(sd_resolve_query *q); | |||
162 | ||||
163 | static void resolve_query_disconnect(sd_resolve_query *q); | |||
164 | ||||
165 | #define RESOLVE_DONT_DESTROY(resolve)__attribute__((cleanup(sd_resolve_unrefp))) __attribute__ ((unused )) sd_resolve *_dont_destroy_resolve = sd_resolve_ref(resolve ) \ | |||
166 | _cleanup_(sd_resolve_unrefp)__attribute__((cleanup(sd_resolve_unrefp))) _unused___attribute__ ((unused)) sd_resolve *_dont_destroy_##resolve = sd_resolve_ref(resolve) | |||
167 | ||||
168 | static void query_assign_errno(sd_resolve_query *q, int ret, int error, int h_error) { | |||
169 | assert(q)do { if ((__builtin_expect(!!(!(q)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("q"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 169, __PRETTY_FUNCTION__); } while (0); | |||
170 | ||||
171 | q->ret = ret; | |||
172 | q->_errno = abs(error); | |||
173 | q->_h_errno = h_error; | |||
174 | } | |||
175 | ||||
176 | static int send_died(int out_fd) { | |||
177 | RHeader rh = { | |||
178 | .type = RESPONSE_DIED, | |||
179 | .length = sizeof(RHeader), | |||
180 | }; | |||
181 | ||||
182 | assert(out_fd >= 0)do { if ((__builtin_expect(!!(!(out_fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("out_fd >= 0"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 182, __PRETTY_FUNCTION__); } while (0); | |||
183 | ||||
184 | if (send(out_fd, &rh, rh.length, MSG_NOSIGNALMSG_NOSIGNAL) < 0) | |||
185 | return -errno(*__errno_location ()); | |||
186 | ||||
187 | return 0; | |||
188 | } | |||
189 | ||||
190 | static void *serialize_addrinfo(void *p, const struct addrinfo *ai, size_t *length, size_t maxlength) { | |||
191 | AddrInfoSerialization s; | |||
192 | size_t cnl, l; | |||
193 | ||||
194 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 194, __PRETTY_FUNCTION__); } while (0); | |||
195 | assert(ai)do { if ((__builtin_expect(!!(!(ai)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ai"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 195, __PRETTY_FUNCTION__); } while (0); | |||
196 | assert(length)do { if ((__builtin_expect(!!(!(length)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("length"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 196, __PRETTY_FUNCTION__); } while (0); | |||
197 | assert(*length <= maxlength)do { if ((__builtin_expect(!!(!(*length <= maxlength)),0)) ) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("*length <= maxlength" ), "../src/libsystemd/sd-resolve/sd-resolve.c", 197, __PRETTY_FUNCTION__ ); } while (0); | |||
198 | ||||
199 | cnl = ai->ai_canonname ? strlen(ai->ai_canonname)+1 : 0; | |||
200 | l = sizeof(AddrInfoSerialization) + ai->ai_addrlen + cnl; | |||
201 | ||||
202 | if (*length + l > maxlength) | |||
203 | return NULL((void*)0); | |||
204 | ||||
205 | s.ai_flags = ai->ai_flags; | |||
206 | s.ai_family = ai->ai_family; | |||
207 | s.ai_socktype = ai->ai_socktype; | |||
208 | s.ai_protocol = ai->ai_protocol; | |||
209 | s.ai_addrlen = ai->ai_addrlen; | |||
210 | s.canonname_len = cnl; | |||
211 | ||||
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); | |||
216 | ||||
217 | *length += l; | |||
218 | return (uint8_t*) p + l; | |||
219 | } | |||
220 | ||||
221 | static int send_addrinfo_reply( | |||
222 | int out_fd, | |||
223 | unsigned id, | |||
224 | int ret, | |||
225 | struct addrinfo *ai, | |||
226 | int _errno, | |||
227 | int _h_errno) { | |||
228 | ||||
229 | AddrInfoResponse resp = { | |||
230 | .header.type = RESPONSE_ADDRINFO, | |||
231 | .header.id = id, | |||
232 | .header.length = sizeof(AddrInfoResponse), | |||
233 | .ret = ret, | |||
234 | ._errno = _errno, | |||
235 | ._h_errno = _h_errno, | |||
236 | }; | |||
237 | ||||
238 | union { | |||
239 | AddrInfoSerialization ais; | |||
240 | uint8_t space[BUFSIZE10240U]; | |||
241 | } buffer; | |||
242 | struct iovec iov[2]; | |||
243 | struct msghdr mh; | |||
244 | ||||
245 | assert(out_fd >= 0)do { if ((__builtin_expect(!!(!(out_fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("out_fd >= 0"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 245, __PRETTY_FUNCTION__); } while (0); | |||
246 | ||||
247 | if (ret == 0 && ai) { | |||
248 | void *p = &buffer; | |||
249 | struct addrinfo *k; | |||
250 | ||||
251 | for (k = ai; k; k = k->ai_next) { | |||
252 | p = serialize_addrinfo(p, k, &resp.header.length, (uint8_t*) &buffer + BUFSIZE10240U - (uint8_t*) p); | |||
253 | if (!p) { | |||
254 | freeaddrinfo(ai); | |||
255 | return -ENOBUFS105; | |||
256 | } | |||
257 | } | |||
258 | } | |||
259 | ||||
260 | if (ai) | |||
261 | freeaddrinfo(ai); | |||
262 | ||||
263 | iov[0] = (struct iovec) { .iov_base = &resp, .iov_len = sizeof(AddrInfoResponse) }; | |||
264 | iov[1] = (struct iovec) { .iov_base = &buffer, .iov_len = resp.header.length - sizeof(AddrInfoResponse) }; | |||
265 | ||||
266 | mh = (struct msghdr) { .msg_iov = iov, .msg_iovlen = ELEMENTSOF(iov)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(iov), typeof(&*(iov))), sizeof(iov)/sizeof((iov)[ 0]), ((void)0))) }; | |||
267 | ||||
268 | if (sendmsg(out_fd, &mh, MSG_NOSIGNALMSG_NOSIGNAL) < 0) | |||
269 | return -errno(*__errno_location ()); | |||
270 | ||||
271 | return 0; | |||
272 | } | |||
273 | ||||
274 | static int send_nameinfo_reply( | |||
275 | int out_fd, | |||
276 | unsigned id, | |||
277 | int ret, | |||
278 | const char *host, | |||
279 | const char *serv, | |||
280 | int _errno, | |||
281 | int _h_errno) { | |||
282 | ||||
283 | NameInfoResponse resp = { | |||
284 | .header.type = RESPONSE_NAMEINFO, | |||
285 | .header.id = id, | |||
286 | .ret = ret, | |||
287 | ._errno = _errno, | |||
288 | ._h_errno = _h_errno, | |||
289 | }; | |||
290 | ||||
291 | struct iovec iov[3]; | |||
292 | struct msghdr mh; | |||
293 | size_t hl, sl; | |||
294 | ||||
295 | assert(out_fd >= 0)do { if ((__builtin_expect(!!(!(out_fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("out_fd >= 0"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 295, __PRETTY_FUNCTION__); } while (0); | |||
296 | ||||
297 | sl = serv ? strlen(serv)+1 : 0; | |||
298 | hl = host ? strlen(host)+1 : 0; | |||
299 | ||||
300 | resp.header.length = sizeof(NameInfoResponse) + hl + sl; | |||
301 | resp.hostlen = hl; | |||
302 | resp.servlen = sl; | |||
303 | ||||
304 | iov[0] = (struct iovec) { .iov_base = &resp, .iov_len = sizeof(NameInfoResponse) }; | |||
305 | iov[1] = (struct iovec) { .iov_base = (void*) host, .iov_len = hl }; | |||
306 | iov[2] = (struct iovec) { .iov_base = (void*) serv, .iov_len = sl }; | |||
307 | ||||
308 | mh = (struct msghdr) { .msg_iov = iov, .msg_iovlen = ELEMENTSOF(iov)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(iov), typeof(&*(iov))), sizeof(iov)/sizeof((iov)[ 0]), ((void)0))) }; | |||
309 | ||||
310 | if (sendmsg(out_fd, &mh, MSG_NOSIGNALMSG_NOSIGNAL) < 0) | |||
311 | return -errno(*__errno_location ()); | |||
312 | ||||
313 | return 0; | |||
314 | } | |||
315 | ||||
316 | static int handle_request(int out_fd, const Packet *packet, size_t length) { | |||
317 | const RHeader *req; | |||
318 | ||||
319 | assert(out_fd >= 0)do { if ((__builtin_expect(!!(!(out_fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("out_fd >= 0"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 319, __PRETTY_FUNCTION__); } while (0); | |||
320 | assert(packet)do { if ((__builtin_expect(!!(!(packet)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("packet"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 320, __PRETTY_FUNCTION__); } while (0); | |||
321 | ||||
322 | req = &packet->rheader; | |||
323 | ||||
324 | assert_return(length >= sizeof(RHeader), -EIO)do { if (!(((__builtin_expect(!!(length >= sizeof(RHeader) ),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD , ("length >= sizeof(RHeader)"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 324, __PRETTY_FUNCTION__), 0))) return (-5); } while (0); | |||
325 | assert_return(length == req->length, -EIO)do { if (!(((__builtin_expect(!!(length == req->length),1) )) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("length == req->length"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 325, __PRETTY_FUNCTION__), 0))) return (-5); } while (0); | |||
326 | ||||
327 | switch (req->type) { | |||
328 | ||||
329 | case REQUEST_ADDRINFO: { | |||
330 | const AddrInfoRequest *ai_req = &packet->addrinfo_request; | |||
331 | struct addrinfo hints, *result = NULL((void*)0); | |||
332 | const char *node, *service; | |||
333 | int ret; | |||
334 | ||||
335 | assert_return(length >= sizeof(AddrInfoRequest), -EBADMSG)do { if (!(((__builtin_expect(!!(length >= sizeof(AddrInfoRequest )),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD , ("length >= sizeof(AddrInfoRequest)"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 335, __PRETTY_FUNCTION__), 0))) return (-74); } while (0); | |||
336 | assert_return(length == sizeof(AddrInfoRequest) + ai_req->node_len + ai_req->service_len, -EBADMSG)do { if (!(((__builtin_expect(!!(length == sizeof(AddrInfoRequest ) + ai_req->node_len + ai_req->service_len),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("length == sizeof(AddrInfoRequest) + ai_req->node_len + ai_req->service_len" ), "../src/libsystemd/sd-resolve/sd-resolve.c", 336, __PRETTY_FUNCTION__ ), 0))) return (-74); } while (0); | |||
337 | ||||
338 | hints = (struct addrinfo) { | |||
339 | .ai_flags = ai_req->ai_flags, | |||
340 | .ai_family = ai_req->ai_family, | |||
341 | .ai_socktype = ai_req->ai_socktype, | |||
342 | .ai_protocol = ai_req->ai_protocol, | |||
343 | }; | |||
344 | ||||
345 | node = ai_req->node_len ? (const char*) ai_req + sizeof(AddrInfoRequest) : NULL((void*)0); | |||
346 | service = ai_req->service_len ? (const char*) ai_req + sizeof(AddrInfoRequest) + ai_req->node_len : NULL((void*)0); | |||
347 | ||||
348 | ret = getaddrinfo(node, service, | |||
349 | ai_req->hints_valid ? &hints : NULL((void*)0), | |||
350 | &result); | |||
351 | ||||
352 | /* send_addrinfo_reply() frees result */ | |||
353 | return send_addrinfo_reply(out_fd, req->id, ret, result, errno(*__errno_location ()), h_errno(*__h_errno_location ())); | |||
354 | } | |||
355 | ||||
356 | case REQUEST_NAMEINFO: { | |||
357 | const NameInfoRequest *ni_req = &packet->nameinfo_request; | |||
358 | char hostbuf[NI_MAXHOST1025], servbuf[NI_MAXSERV32]; | |||
359 | union sockaddr_union sa; | |||
360 | int ret; | |||
361 | ||||
362 | assert_return(length >= sizeof(NameInfoRequest), -EBADMSG)do { if (!(((__builtin_expect(!!(length >= sizeof(NameInfoRequest )),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD , ("length >= sizeof(NameInfoRequest)"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 362, __PRETTY_FUNCTION__), 0))) return (-74); } while (0); | |||
363 | assert_return(length == sizeof(NameInfoRequest) + ni_req->sockaddr_len, -EBADMSG)do { if (!(((__builtin_expect(!!(length == sizeof(NameInfoRequest ) + ni_req->sockaddr_len),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("length == sizeof(NameInfoRequest) + ni_req->sockaddr_len" ), "../src/libsystemd/sd-resolve/sd-resolve.c", 363, __PRETTY_FUNCTION__ ), 0))) return (-74); } while (0); | |||
364 | assert_return(ni_req->sockaddr_len <= sizeof(sa), -EBADMSG)do { if (!(((__builtin_expect(!!(ni_req->sockaddr_len <= sizeof(sa)),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD , ("ni_req->sockaddr_len <= sizeof(sa)"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 364, __PRETTY_FUNCTION__), 0))) return (-74); } while (0); | |||
365 | ||||
366 | memcpy(&sa, (const uint8_t *) ni_req + sizeof(NameInfoRequest), ni_req->sockaddr_len); | |||
367 | ||||
368 | ret = getnameinfo(&sa.sa, ni_req->sockaddr_len, | |||
369 | ni_req->gethost ? hostbuf : NULL((void*)0), ni_req->gethost ? sizeof(hostbuf) : 0, | |||
370 | ni_req->getserv ? servbuf : NULL((void*)0), ni_req->getserv ? sizeof(servbuf) : 0, | |||
371 | ni_req->flags); | |||
372 | ||||
373 | return send_nameinfo_reply(out_fd, req->id, ret, | |||
374 | ret == 0 && ni_req->gethost ? hostbuf : NULL((void*)0), | |||
375 | ret == 0 && ni_req->getserv ? servbuf : NULL((void*)0), | |||
376 | errno(*__errno_location ()), h_errno(*__h_errno_location ())); | |||
377 | } | |||
378 | ||||
379 | case REQUEST_TERMINATE: | |||
380 | /* Quit */ | |||
381 | return -ECONNRESET104; | |||
382 | ||||
383 | default: | |||
384 | assert_not_reached("Unknown request")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, ( "Unknown request"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 384, __PRETTY_FUNCTION__); } while (0); | |||
385 | } | |||
386 | ||||
387 | return 0; | |||
388 | } | |||
389 | ||||
390 | static void* thread_worker(void *p) { | |||
391 | sd_resolve *resolve = p; | |||
392 | ||||
393 | /* Assign a pretty name to this thread */ | |||
394 | (void) pthread_setname_np(pthread_self(), "sd-resolve"); | |||
395 | ||||
396 | while (!resolve->dead) { | |||
397 | union { | |||
398 | Packet packet; | |||
399 | uint8_t space[BUFSIZE10240U]; | |||
400 | } buf; | |||
401 | ssize_t length; | |||
402 | ||||
403 | length = recv(resolve->fds[REQUEST_RECV_FD], &buf, sizeof buf, 0); | |||
404 | if (length < 0) { | |||
405 | if (errno(*__errno_location ()) == EINTR4) | |||
406 | continue; | |||
407 | ||||
408 | break; | |||
409 | } | |||
410 | if (length == 0) | |||
411 | break; | |||
412 | ||||
413 | if (handle_request(resolve->fds[RESPONSE_SEND_FD], &buf.packet, (size_t) length) < 0) | |||
414 | break; | |||
415 | } | |||
416 | ||||
417 | send_died(resolve->fds[RESPONSE_SEND_FD]); | |||
418 | ||||
419 | return NULL((void*)0); | |||
420 | } | |||
421 | ||||
422 | static int start_threads(sd_resolve *resolve, unsigned extra) { | |||
423 | sigset_t ss, saved_ss; | |||
424 | unsigned n; | |||
425 | int r, k; | |||
426 | ||||
427 | if (sigfillset(&ss) < 0) | |||
428 | return -errno(*__errno_location ()); | |||
429 | ||||
430 | /* No signals in forked off threads please. We set the mask before forking, so that the threads never exist | |||
431 | * with a different mask than a fully blocked one */ | |||
432 | r = pthread_sigmask(SIG_BLOCK0, &ss, &saved_ss); | |||
433 | if (r > 0) | |||
434 | return -r; | |||
435 | ||||
436 | n = resolve->n_outstanding + extra; | |||
437 | n = CLAMP(n, WORKERS_MIN, WORKERS_MAX)__extension__ ({ const typeof((n)) __unique_prefix_X6 = ((n)) ; const typeof((1U)) __unique_prefix_LOW7 = ((1U)); const typeof ((16U)) __unique_prefix_HIGH8 = ((16U)); __unique_prefix_X6 > __unique_prefix_HIGH8 ? __unique_prefix_HIGH8 : __unique_prefix_X6 < __unique_prefix_LOW7 ? __unique_prefix_LOW7 : __unique_prefix_X6 ; }); | |||
438 | ||||
439 | while (resolve->n_valid_workers < n) { | |||
440 | r = pthread_create(&resolve->workers[resolve->n_valid_workers], NULL((void*)0), thread_worker, resolve); | |||
441 | if (r > 0) { | |||
442 | r = -r; | |||
443 | goto finish; | |||
444 | } | |||
445 | ||||
446 | resolve->n_valid_workers++; | |||
447 | } | |||
448 | ||||
449 | r = 0; | |||
450 | ||||
451 | finish: | |||
452 | k = pthread_sigmask(SIG_SETMASK2, &saved_ss, NULL((void*)0)); | |||
453 | if (k > 0 && r >= 0) | |||
454 | r = -k; | |||
455 | ||||
456 | return r; | |||
457 | } | |||
458 | ||||
459 | static bool_Bool resolve_pid_changed(sd_resolve *r) { | |||
460 | assert(r)do { if ((__builtin_expect(!!(!(r)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("r"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 460, __PRETTY_FUNCTION__); } while (0); | |||
461 | ||||
462 | /* We don't support people creating a resolver and keeping it | |||
463 | * around after fork(). Let's complain. */ | |||
464 | ||||
465 | return r->original_pid != getpid_cached(); | |||
466 | } | |||
467 | ||||
468 | _public___attribute__ ((visibility("default"))) int sd_resolve_new(sd_resolve **ret) { | |||
469 | _cleanup_(sd_resolve_unrefp)__attribute__((cleanup(sd_resolve_unrefp))) sd_resolve *resolve = NULL((void*)0); | |||
470 | int i; | |||
471 | ||||
472 | assert_return(ret, -EINVAL)do { if (!(((__builtin_expect(!!(ret),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 472, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
473 | ||||
474 | resolve = new0(sd_resolve, 1)((sd_resolve*) calloc((1), sizeof(sd_resolve))); | |||
475 | if (!resolve) | |||
476 | return -ENOMEM12; | |||
477 | ||||
478 | resolve->n_ref = 1; | |||
479 | resolve->original_pid = getpid_cached(); | |||
480 | ||||
481 | for (i = 0; i < _FD_MAX; i++) | |||
482 | resolve->fds[i] = -1; | |||
483 | ||||
484 | if (socketpair(PF_UNIX1, SOCK_DGRAMSOCK_DGRAM|SOCK_CLOEXECSOCK_CLOEXEC, 0, resolve->fds + REQUEST_RECV_FD) < 0) | |||
485 | return -errno(*__errno_location ()); | |||
486 | ||||
487 | if (socketpair(PF_UNIX1, SOCK_DGRAMSOCK_DGRAM|SOCK_CLOEXECSOCK_CLOEXEC, 0, resolve->fds + RESPONSE_RECV_FD) < 0) | |||
488 | return -errno(*__errno_location ()); | |||
489 | ||||
490 | for (i = 0; i < _FD_MAX; i++) | |||
491 | resolve->fds[i] = fd_move_above_stdio(resolve->fds[i]); | |||
492 | ||||
493 | (void) fd_inc_sndbuf(resolve->fds[REQUEST_SEND_FD], QUERIES_MAX256U * BUFSIZE10240U); | |||
494 | (void) fd_inc_rcvbuf(resolve->fds[REQUEST_RECV_FD], QUERIES_MAX256U * BUFSIZE10240U); | |||
495 | (void) fd_inc_sndbuf(resolve->fds[RESPONSE_SEND_FD], QUERIES_MAX256U * BUFSIZE10240U); | |||
496 | (void) fd_inc_rcvbuf(resolve->fds[RESPONSE_RECV_FD], QUERIES_MAX256U * BUFSIZE10240U); | |||
497 | ||||
498 | (void) fd_nonblock(resolve->fds[RESPONSE_RECV_FD], true1); | |||
499 | ||||
500 | *ret = TAKE_PTR(resolve)({ typeof(resolve) _ptr_ = (resolve); (resolve) = ((void*)0); _ptr_; }); | |||
501 | return 0; | |||
502 | } | |||
503 | ||||
504 | _public___attribute__ ((visibility("default"))) int sd_resolve_default(sd_resolve **ret) { | |||
505 | ||||
506 | static thread_local__thread sd_resolve *default_resolve = NULL((void*)0); | |||
507 | sd_resolve *e = NULL((void*)0); | |||
508 | int r; | |||
509 | ||||
510 | if (!ret) | |||
511 | return !!default_resolve; | |||
512 | ||||
513 | if (default_resolve) { | |||
514 | *ret = sd_resolve_ref(default_resolve); | |||
515 | return 0; | |||
516 | } | |||
517 | ||||
518 | r = sd_resolve_new(&e); | |||
519 | if (r < 0) | |||
520 | return r; | |||
521 | ||||
522 | e->default_resolve_ptr = &default_resolve; | |||
523 | e->tid = gettid(); | |||
524 | default_resolve = e; | |||
525 | ||||
526 | *ret = e; | |||
527 | return 1; | |||
528 | } | |||
529 | ||||
530 | _public___attribute__ ((visibility("default"))) int sd_resolve_get_tid(sd_resolve *resolve, pid_t *tid) { | |||
531 | assert_return(resolve, -EINVAL)do { if (!(((__builtin_expect(!!(resolve),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("resolve"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 531, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
532 | assert_return(tid, -EINVAL)do { if (!(((__builtin_expect(!!(tid),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("tid"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 532, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
533 | assert_return(!resolve_pid_changed(resolve), -ECHILD)do { if (!(((__builtin_expect(!!(!resolve_pid_changed(resolve )),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD , ("!resolve_pid_changed(resolve)"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 533, __PRETTY_FUNCTION__), 0))) return (-10); } while (0); | |||
534 | ||||
535 | if (resolve->tid != 0) { | |||
536 | *tid = resolve->tid; | |||
537 | return 0; | |||
538 | } | |||
539 | ||||
540 | if (resolve->event) | |||
541 | return sd_event_get_tid(resolve->event, tid); | |||
542 | ||||
543 | return -ENXIO6; | |||
544 | } | |||
545 | ||||
546 | static void resolve_free(sd_resolve *resolve) { | |||
547 | PROTECT_ERRNO__attribute__((cleanup(_reset_errno_))) __attribute__((unused )) int _saved_errno_ = (*__errno_location ()); | |||
548 | sd_resolve_query *q; | |||
549 | unsigned i; | |||
550 | ||||
551 | assert(resolve)do { if ((__builtin_expect(!!(!(resolve)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("resolve"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 551, __PRETTY_FUNCTION__); } while (0); | |||
552 | ||||
553 | while ((q = resolve->queries)) { | |||
554 | assert(q->floating)do { if ((__builtin_expect(!!(!(q->floating)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("q->floating"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 554, __PRETTY_FUNCTION__); } while (0); | |||
| ||||
555 | resolve_query_disconnect(q); | |||
556 | sd_resolve_query_unref(q); | |||
557 | } | |||
558 | ||||
559 | if (resolve->default_resolve_ptr) | |||
560 | *(resolve->default_resolve_ptr) = NULL((void*)0); | |||
561 | ||||
562 | resolve->dead = true1; | |||
563 | ||||
564 | sd_resolve_detach_event(resolve); | |||
565 | ||||
566 | if (resolve->fds[REQUEST_SEND_FD] >= 0) { | |||
567 | ||||
568 | RHeader req = { | |||
569 | .type = REQUEST_TERMINATE, | |||
570 | .length = sizeof req, | |||
571 | }; | |||
572 | ||||
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_NOSIGNALMSG_NOSIGNAL); | |||
576 | } | |||
577 | ||||
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((void*)0)); | |||
582 | ||||
583 | /* Close all communication channels */ | |||
584 | close_many(resolve->fds, _FD_MAX); | |||
585 | free(resolve); | |||
586 | } | |||
587 | ||||
588 | _public___attribute__ ((visibility("default"))) sd_resolve* sd_resolve_ref(sd_resolve *resolve) { | |||
589 | assert_return(resolve, NULL)do { if (!(((__builtin_expect(!!(resolve),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("resolve"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 589, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while (0); | |||
590 | ||||
591 | assert(resolve->n_ref >= 1)do { if ((__builtin_expect(!!(!(resolve->n_ref >= 1)),0 ))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("resolve->n_ref >= 1" ), "../src/libsystemd/sd-resolve/sd-resolve.c", 591, __PRETTY_FUNCTION__ ); } while (0); | |||
592 | resolve->n_ref++; | |||
593 | ||||
594 | return resolve; | |||
595 | } | |||
596 | ||||
597 | _public___attribute__ ((visibility("default"))) sd_resolve* sd_resolve_unref(sd_resolve *resolve) { | |||
598 | if (!resolve) | |||
| ||||
599 | return NULL((void*)0); | |||
600 | ||||
601 | assert(resolve->n_ref >= 1)do { if ((__builtin_expect(!!(!(resolve->n_ref >= 1)),0 ))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("resolve->n_ref >= 1" ), "../src/libsystemd/sd-resolve/sd-resolve.c", 601, __PRETTY_FUNCTION__ ); } while (0); | |||
602 | resolve->n_ref--; | |||
603 | ||||
604 | if (resolve->n_ref <= 0) | |||
605 | resolve_free(resolve); | |||
606 | ||||
607 | return NULL((void*)0); | |||
608 | } | |||
609 | ||||
610 | _public___attribute__ ((visibility("default"))) int sd_resolve_get_fd(sd_resolve *resolve) { | |||
611 | assert_return(resolve, -EINVAL)do { if (!(((__builtin_expect(!!(resolve),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("resolve"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 611, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
612 | assert_return(!resolve_pid_changed(resolve), -ECHILD)do { if (!(((__builtin_expect(!!(!resolve_pid_changed(resolve )),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD , ("!resolve_pid_changed(resolve)"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 612, __PRETTY_FUNCTION__), 0))) return (-10); } while (0); | |||
613 | ||||
614 | return resolve->fds[RESPONSE_RECV_FD]; | |||
615 | } | |||
616 | ||||
617 | _public___attribute__ ((visibility("default"))) int sd_resolve_get_events(sd_resolve *resolve) { | |||
618 | assert_return(resolve, -EINVAL)do { if (!(((__builtin_expect(!!(resolve),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("resolve"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 618, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
619 | assert_return(!resolve_pid_changed(resolve), -ECHILD)do { if (!(((__builtin_expect(!!(!resolve_pid_changed(resolve )),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD , ("!resolve_pid_changed(resolve)"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 619, __PRETTY_FUNCTION__), 0))) return (-10); } while (0); | |||
620 | ||||
621 | return resolve->n_queries > resolve->n_done ? POLLIN0x001 : 0; | |||
622 | } | |||
623 | ||||
624 | _public___attribute__ ((visibility("default"))) int sd_resolve_get_timeout(sd_resolve *resolve, uint64_t *usec) { | |||
625 | assert_return(resolve, -EINVAL)do { if (!(((__builtin_expect(!!(resolve),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("resolve"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 625, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
626 | assert_return(usec, -EINVAL)do { if (!(((__builtin_expect(!!(usec),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("usec"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 626, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
627 | assert_return(!resolve_pid_changed(resolve), -ECHILD)do { if (!(((__builtin_expect(!!(!resolve_pid_changed(resolve )),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD , ("!resolve_pid_changed(resolve)"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 627, __PRETTY_FUNCTION__), 0))) return (-10); } while (0); | |||
628 | ||||
629 | *usec = (uint64_t) -1; | |||
630 | return 0; | |||
631 | } | |||
632 | ||||
633 | static sd_resolve_query *lookup_query(sd_resolve *resolve, unsigned id) { | |||
634 | sd_resolve_query *q; | |||
635 | ||||
636 | assert(resolve)do { if ((__builtin_expect(!!(!(resolve)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("resolve"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 636, __PRETTY_FUNCTION__); } while (0); | |||
637 | ||||
638 | q = resolve->query_array[id % QUERIES_MAX256U]; | |||
639 | if (q) | |||
640 | if (q->id == id) | |||
641 | return q; | |||
642 | ||||
643 | return NULL((void*)0); | |||
644 | } | |||
645 | ||||
646 | static int complete_query(sd_resolve *resolve, sd_resolve_query *q) { | |||
647 | int r; | |||
648 | ||||
649 | assert(q)do { if ((__builtin_expect(!!(!(q)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("q"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 649, __PRETTY_FUNCTION__); } while (0); | |||
650 | assert(!q->done)do { if ((__builtin_expect(!!(!(!q->done)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("!q->done"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 650, __PRETTY_FUNCTION__); } while (0); | |||
651 | assert(q->resolve == resolve)do { if ((__builtin_expect(!!(!(q->resolve == resolve)),0) )) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("q->resolve == resolve" ), "../src/libsystemd/sd-resolve/sd-resolve.c", 651, __PRETTY_FUNCTION__ ); } while (0); | |||
652 | ||||
653 | q->done = true1; | |||
654 | resolve->n_done++; | |||
655 | ||||
656 | resolve->current = sd_resolve_query_ref(q); | |||
657 | ||||
658 | switch (q->type) { | |||
659 | ||||
660 | case REQUEST_ADDRINFO: | |||
661 | r = getaddrinfo_done(q); | |||
662 | break; | |||
663 | ||||
664 | case REQUEST_NAMEINFO: | |||
665 | r = getnameinfo_done(q); | |||
666 | break; | |||
667 | ||||
668 | default: | |||
669 | assert_not_reached("Cannot complete unknown query type")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, ( "Cannot complete unknown query type"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 669, __PRETTY_FUNCTION__); } while (0); | |||
670 | } | |||
671 | ||||
672 | resolve->current = NULL((void*)0); | |||
673 | ||||
674 | if (q->floating) { | |||
675 | resolve_query_disconnect(q); | |||
676 | sd_resolve_query_unref(q); | |||
677 | } | |||
678 | ||||
679 | sd_resolve_query_unref(q); | |||
680 | ||||
681 | return r; | |||
682 | } | |||
683 | ||||
684 | static int unserialize_addrinfo(const void **p, size_t *length, struct addrinfo **ret_ai) { | |||
685 | AddrInfoSerialization s; | |||
686 | size_t l; | |||
687 | struct addrinfo *ai; | |||
688 | ||||
689 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 689, __PRETTY_FUNCTION__); } while (0); | |||
690 | assert(*p)do { if ((__builtin_expect(!!(!(*p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("*p"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 690, __PRETTY_FUNCTION__); } while (0); | |||
691 | assert(ret_ai)do { if ((__builtin_expect(!!(!(ret_ai)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret_ai"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 691, __PRETTY_FUNCTION__); } while (0); | |||
692 | assert(length)do { if ((__builtin_expect(!!(!(length)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("length"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 692, __PRETTY_FUNCTION__); } while (0); | |||
693 | ||||
694 | if (*length < sizeof(AddrInfoSerialization)) | |||
695 | return -EBADMSG74; | |||
696 | ||||
697 | memcpy(&s, *p, sizeof(s)); | |||
698 | ||||
699 | l = sizeof(AddrInfoSerialization) + s.ai_addrlen + s.canonname_len; | |||
700 | if (*length < l) | |||
701 | return -EBADMSG74; | |||
702 | ||||
703 | ai = new0(struct addrinfo, 1)((struct addrinfo*) calloc((1), sizeof(struct addrinfo))); | |||
704 | if (!ai) | |||
705 | return -ENOMEM12; | |||
706 | ||||
707 | ai->ai_flags = s.ai_flags; | |||
708 | ai->ai_family = s.ai_family; | |||
709 | ai->ai_socktype = s.ai_socktype; | |||
710 | ai->ai_protocol = s.ai_protocol; | |||
711 | ai->ai_addrlen = s.ai_addrlen; | |||
712 | ||||
713 | if (s.ai_addrlen > 0) { | |||
714 | ai->ai_addr = memdup((const uint8_t*) *p + sizeof(AddrInfoSerialization), s.ai_addrlen); | |||
715 | if (!ai->ai_addr) { | |||
716 | free(ai); | |||
717 | return -ENOMEM12; | |||
718 | } | |||
719 | } | |||
720 | ||||
721 | if (s.canonname_len > 0) { | |||
722 | ai->ai_canonname = memdup((const uint8_t*) *p + sizeof(AddrInfoSerialization) + s.ai_addrlen, s.canonname_len); | |||
723 | if (!ai->ai_canonname) { | |||
724 | free(ai->ai_addr); | |||
725 | free(ai); | |||
726 | return -ENOMEM12; | |||
727 | } | |||
728 | } | |||
729 | ||||
730 | *length -= l; | |||
731 | *ret_ai = ai; | |||
732 | *p = ((const uint8_t*) *p) + l; | |||
733 | ||||
734 | return 0; | |||
735 | } | |||
736 | ||||
737 | static int handle_response(sd_resolve *resolve, const Packet *packet, size_t length) { | |||
738 | const RHeader *resp; | |||
739 | sd_resolve_query *q; | |||
740 | int r; | |||
741 | ||||
742 | assert(resolve)do { if ((__builtin_expect(!!(!(resolve)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("resolve"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 742, __PRETTY_FUNCTION__); } while (0); | |||
743 | assert(packet)do { if ((__builtin_expect(!!(!(packet)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("packet"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 743, __PRETTY_FUNCTION__); } while (0); | |||
744 | ||||
745 | resp = &packet->rheader; | |||
746 | assert_return(length >= sizeof(RHeader), -EIO)do { if (!(((__builtin_expect(!!(length >= sizeof(RHeader) ),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD , ("length >= sizeof(RHeader)"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 746, __PRETTY_FUNCTION__), 0))) return (-5); } while (0); | |||
747 | assert_return(length == resp->length, -EIO)do { if (!(((__builtin_expect(!!(length == resp->length),1 ))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD , ("length == resp->length"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 747, __PRETTY_FUNCTION__), 0))) return (-5); } while (0); | |||
748 | ||||
749 | if (resp->type == RESPONSE_DIED) { | |||
750 | resolve->dead = true1; | |||
751 | return 0; | |||
752 | } | |||
753 | ||||
754 | assert(resolve->n_outstanding > 0)do { if ((__builtin_expect(!!(!(resolve->n_outstanding > 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("resolve->n_outstanding > 0" ), "../src/libsystemd/sd-resolve/sd-resolve.c", 754, __PRETTY_FUNCTION__ ); } while (0); | |||
755 | resolve->n_outstanding--; | |||
756 | ||||
757 | q = lookup_query(resolve, resp->id); | |||
758 | if (!q) | |||
759 | return 0; | |||
760 | ||||
761 | switch (resp->type) { | |||
762 | ||||
763 | case RESPONSE_ADDRINFO: { | |||
764 | const AddrInfoResponse *ai_resp = &packet->addrinfo_response; | |||
765 | const void *p; | |||
766 | size_t l; | |||
767 | struct addrinfo *prev = NULL((void*)0); | |||
768 | ||||
769 | assert_return(length >= sizeof(AddrInfoResponse), -EBADMSG)do { if (!(((__builtin_expect(!!(length >= sizeof(AddrInfoResponse )),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD , ("length >= sizeof(AddrInfoResponse)"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 769, __PRETTY_FUNCTION__), 0))) return (-74); } while (0); | |||
770 | assert_return(q->type == REQUEST_ADDRINFO, -EBADMSG)do { if (!(((__builtin_expect(!!(q->type == REQUEST_ADDRINFO ),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD , ("q->type == REQUEST_ADDRINFO"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 770, __PRETTY_FUNCTION__), 0))) return (-74); } while (0); | |||
771 | ||||
772 | query_assign_errno(q, ai_resp->ret, ai_resp->_errno, ai_resp->_h_errno); | |||
773 | ||||
774 | l = length - sizeof(AddrInfoResponse); | |||
775 | p = (const uint8_t*) resp + sizeof(AddrInfoResponse); | |||
776 | ||||
777 | while (l > 0 && p) { | |||
778 | struct addrinfo *ai = NULL((void*)0); | |||
779 | ||||
780 | r = unserialize_addrinfo(&p, &l, &ai); | |||
781 | if (r < 0) { | |||
782 | query_assign_errno(q, EAI_SYSTEM-11, r, 0); | |||
783 | freeaddrinfo(q->addrinfo); | |||
784 | q->addrinfo = NULL((void*)0); | |||
785 | break; | |||
786 | } | |||
787 | ||||
788 | if (prev) | |||
789 | prev->ai_next = ai; | |||
790 | else | |||
791 | q->addrinfo = ai; | |||
792 | ||||
793 | prev = ai; | |||
794 | } | |||
795 | ||||
796 | return complete_query(resolve, q); | |||
797 | } | |||
798 | ||||
799 | case RESPONSE_NAMEINFO: { | |||
800 | const NameInfoResponse *ni_resp = &packet->nameinfo_response; | |||
801 | ||||
802 | assert_return(length >= sizeof(NameInfoResponse), -EBADMSG)do { if (!(((__builtin_expect(!!(length >= sizeof(NameInfoResponse )),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD , ("length >= sizeof(NameInfoResponse)"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 802, __PRETTY_FUNCTION__), 0))) return (-74); } while (0); | |||
803 | assert_return(q->type == REQUEST_NAMEINFO, -EBADMSG)do { if (!(((__builtin_expect(!!(q->type == REQUEST_NAMEINFO ),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD , ("q->type == REQUEST_NAMEINFO"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 803, __PRETTY_FUNCTION__), 0))) return (-74); } while (0); | |||
804 | ||||
805 | if (ni_resp->hostlen > DNS_HOSTNAME_MAX253 || | |||
806 | ni_resp->servlen > DNS_HOSTNAME_MAX253 || | |||
807 | sizeof(NameInfoResponse) + ni_resp->hostlen + ni_resp->servlen > length) | |||
808 | query_assign_errno(q, EAI_SYSTEM-11, EIO5, 0); | |||
809 | else { | |||
810 | query_assign_errno(q, ni_resp->ret, ni_resp->_errno, ni_resp->_h_errno); | |||
811 | ||||
812 | if (ni_resp->hostlen > 0) { | |||
813 | q->host = strndup((const char*) ni_resp + sizeof(NameInfoResponse), | |||
814 | ni_resp->hostlen-1); | |||
815 | if (!q->host) | |||
816 | query_assign_errno(q, EAI_MEMORY-10, ENOMEM12, 0); | |||
817 | } | |||
818 | ||||
819 | if (ni_resp->servlen > 0) { | |||
820 | q->serv = strndup((const char*) ni_resp + sizeof(NameInfoResponse) + ni_resp->hostlen, | |||
821 | ni_resp->servlen-1); | |||
822 | if (!q->serv) | |||
823 | query_assign_errno(q, EAI_MEMORY-10, ENOMEM12, 0); | |||
824 | } | |||
825 | } | |||
826 | ||||
827 | return complete_query(resolve, q); | |||
828 | } | |||
829 | ||||
830 | default: | |||
831 | return 0; | |||
832 | } | |||
833 | } | |||
834 | ||||
835 | _public___attribute__ ((visibility("default"))) int sd_resolve_process(sd_resolve *resolve) { | |||
836 | RESOLVE_DONT_DESTROY(resolve)__attribute__((cleanup(sd_resolve_unrefp))) __attribute__ ((unused )) sd_resolve *_dont_destroy_resolve = sd_resolve_ref(resolve ); | |||
837 | ||||
838 | union { | |||
839 | Packet packet; | |||
840 | uint8_t space[BUFSIZE10240U]; | |||
841 | } buf; | |||
842 | ssize_t l; | |||
843 | int r; | |||
844 | ||||
845 | assert_return(resolve, -EINVAL)do { if (!(((__builtin_expect(!!(resolve),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("resolve"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 845, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
846 | assert_return(!resolve_pid_changed(resolve), -ECHILD)do { if (!(((__builtin_expect(!!(!resolve_pid_changed(resolve )),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD , ("!resolve_pid_changed(resolve)"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 846, __PRETTY_FUNCTION__), 0))) return (-10); } while (0); | |||
847 | ||||
848 | /* We don't allow recursively invoking sd_resolve_process(). */ | |||
849 | assert_return(!resolve->current, -EBUSY)do { if (!(((__builtin_expect(!!(!resolve->current),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!resolve->current" ), "../src/libsystemd/sd-resolve/sd-resolve.c", 849, __PRETTY_FUNCTION__ ), 0))) return (-16); } while (0); | |||
850 | ||||
851 | l = recv(resolve->fds[RESPONSE_RECV_FD], &buf, sizeof buf, 0); | |||
852 | if (l < 0) { | |||
853 | if (errno(*__errno_location ()) == EAGAIN11) | |||
854 | return 0; | |||
855 | ||||
856 | return -errno(*__errno_location ()); | |||
857 | } | |||
858 | if (l == 0) | |||
859 | return -ECONNREFUSED111; | |||
860 | ||||
861 | r = handle_response(resolve, &buf.packet, (size_t) l); | |||
862 | if (r < 0) | |||
863 | return r; | |||
864 | ||||
865 | return 1; | |||
866 | } | |||
867 | ||||
868 | _public___attribute__ ((visibility("default"))) int sd_resolve_wait(sd_resolve *resolve, uint64_t timeout_usec) { | |||
869 | int r; | |||
870 | ||||
871 | assert_return(resolve, -EINVAL)do { if (!(((__builtin_expect(!!(resolve),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("resolve"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 871, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
872 | assert_return(!resolve_pid_changed(resolve), -ECHILD)do { if (!(((__builtin_expect(!!(!resolve_pid_changed(resolve )),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD , ("!resolve_pid_changed(resolve)"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 872, __PRETTY_FUNCTION__), 0))) return (-10); } while (0); | |||
873 | ||||
874 | if (resolve->n_done >= resolve->n_queries) | |||
875 | return 0; | |||
876 | ||||
877 | do { | |||
878 | r = fd_wait_for_event(resolve->fds[RESPONSE_RECV_FD], POLLIN0x001, timeout_usec); | |||
879 | } while (r == -EINTR4); | |||
880 | ||||
881 | if (r < 0) | |||
882 | return r; | |||
883 | if (r == 0) | |||
884 | return -ETIMEDOUT110; | |||
885 | ||||
886 | return sd_resolve_process(resolve); | |||
887 | } | |||
888 | ||||
889 | static int alloc_query(sd_resolve *resolve, bool_Bool floating, sd_resolve_query **_q) { | |||
890 | sd_resolve_query *q; | |||
891 | int r; | |||
892 | ||||
893 | assert(resolve)do { if ((__builtin_expect(!!(!(resolve)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("resolve"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 893, __PRETTY_FUNCTION__); } while (0); | |||
894 | assert(_q)do { if ((__builtin_expect(!!(!(_q)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("_q"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 894, __PRETTY_FUNCTION__); } while (0); | |||
895 | ||||
896 | if (resolve->n_queries >= QUERIES_MAX256U) | |||
897 | return -ENOBUFS105; | |||
898 | ||||
899 | r = start_threads(resolve, 1); | |||
900 | if (r < 0) | |||
901 | return r; | |||
902 | ||||
903 | while (resolve->query_array[resolve->current_id % QUERIES_MAX256U]) | |||
904 | resolve->current_id++; | |||
905 | ||||
906 | q = resolve->query_array[resolve->current_id % QUERIES_MAX256U] = new0(sd_resolve_query, 1)((sd_resolve_query*) calloc((1), sizeof(sd_resolve_query))); | |||
907 | if (!q) | |||
908 | return -ENOMEM12; | |||
909 | ||||
910 | q->n_ref = 1; | |||
911 | q->resolve = resolve; | |||
912 | q->floating = floating; | |||
913 | q->id = resolve->current_id++; | |||
914 | ||||
915 | if (!floating) | |||
916 | sd_resolve_ref(resolve); | |||
917 | ||||
918 | LIST_PREPEND(queries, resolve->queries, q)do { typeof(*(resolve->queries)) **_head = &(resolve-> queries), *_item = (q); do { if ((__builtin_expect(!!(!(_item )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("_item"), "../src/libsystemd/sd-resolve/sd-resolve.c", 918, __PRETTY_FUNCTION__ ); } while (0); if ((_item->queries_next = *_head)) _item-> queries_next->queries_prev = _item; _item->queries_prev = ((void*)0); *_head = _item; } while (0); | |||
919 | resolve->n_queries++; | |||
920 | ||||
921 | *_q = q; | |||
922 | return 0; | |||
923 | } | |||
924 | ||||
925 | _public___attribute__ ((visibility("default"))) int sd_resolve_getaddrinfo( | |||
926 | sd_resolve *resolve, | |||
927 | sd_resolve_query **_q, | |||
928 | const char *node, const char *service, | |||
929 | const struct addrinfo *hints, | |||
930 | sd_resolve_getaddrinfo_handler_t callback, void *userdata) { | |||
931 | ||||
932 | _cleanup_(sd_resolve_query_unrefp)__attribute__((cleanup(sd_resolve_query_unrefp))) sd_resolve_query *q = NULL((void*)0); | |||
933 | AddrInfoRequest req; | |||
934 | struct iovec iov[3]; | |||
935 | struct msghdr mh = {}; | |||
936 | int r; | |||
937 | size_t node_len, service_len; | |||
938 | ||||
939 | assert_return(resolve, -EINVAL)do { if (!(((__builtin_expect(!!(resolve),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("resolve"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 939, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
940 | assert_return(node || service, -EINVAL)do { if (!(((__builtin_expect(!!(node || service),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("node || service" ), "../src/libsystemd/sd-resolve/sd-resolve.c", 940, __PRETTY_FUNCTION__ ), 0))) return (-22); } while (0); | |||
941 | assert_return(callback, -EINVAL)do { if (!(((__builtin_expect(!!(callback),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("callback"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 941, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
942 | assert_return(!resolve_pid_changed(resolve), -ECHILD)do { if (!(((__builtin_expect(!!(!resolve_pid_changed(resolve )),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD , ("!resolve_pid_changed(resolve)"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 942, __PRETTY_FUNCTION__), 0))) return (-10); } while (0); | |||
943 | ||||
944 | r = alloc_query(resolve, !_q, &q); | |||
945 | if (r < 0) | |||
946 | return r; | |||
947 | ||||
948 | q->type = REQUEST_ADDRINFO; | |||
949 | q->getaddrinfo_handler = callback; | |||
950 | q->userdata = userdata; | |||
951 | ||||
952 | node_len = node ? strlen(node) + 1 : 0; | |||
953 | service_len = service ? strlen(service) + 1 : 0; | |||
954 | ||||
955 | req = (AddrInfoRequest) { | |||
956 | .node_len = node_len, | |||
957 | .service_len = service_len, | |||
958 | ||||
959 | .header.id = q->id, | |||
960 | .header.type = REQUEST_ADDRINFO, | |||
961 | .header.length = sizeof(AddrInfoRequest) + node_len + service_len, | |||
962 | ||||
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, | |||
968 | }; | |||
969 | ||||
970 | iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(AddrInfoRequest) }; | |||
971 | if (node) | |||
972 | iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = (void*) node, .iov_len = req.node_len }; | |||
973 | if (service) | |||
974 | iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = (void*) service, .iov_len = req.service_len }; | |||
975 | mh.msg_iov = iov; | |||
976 | ||||
977 | if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNALMSG_NOSIGNAL) < 0) | |||
978 | return -errno(*__errno_location ()); | |||
979 | ||||
980 | resolve->n_outstanding++; | |||
981 | ||||
982 | if (_q) | |||
983 | *_q = q; | |||
984 | TAKE_PTR(q)({ typeof(q) _ptr_ = (q); (q) = ((void*)0); _ptr_; }); | |||
985 | ||||
986 | return 0; | |||
987 | } | |||
988 | ||||
989 | static int getaddrinfo_done(sd_resolve_query* q) { | |||
990 | assert(q)do { if ((__builtin_expect(!!(!(q)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("q"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 990, __PRETTY_FUNCTION__); } while (0); | |||
991 | assert(q->done)do { if ((__builtin_expect(!!(!(q->done)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("q->done"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 991, __PRETTY_FUNCTION__); } while (0); | |||
992 | assert(q->getaddrinfo_handler)do { if ((__builtin_expect(!!(!(q->getaddrinfo_handler)),0 ))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("q->getaddrinfo_handler" ), "../src/libsystemd/sd-resolve/sd-resolve.c", 992, __PRETTY_FUNCTION__ ); } while (0); | |||
993 | ||||
994 | errno(*__errno_location ()) = q->_errno; | |||
995 | h_errno(*__h_errno_location ()) = q->_h_errno; | |||
996 | ||||
997 | return q->getaddrinfo_handler(q, q->ret, q->addrinfo, q->userdata); | |||
998 | } | |||
999 | ||||
1000 | _public___attribute__ ((visibility("default"))) int sd_resolve_getnameinfo( | |||
1001 | sd_resolve *resolve, | |||
1002 | sd_resolve_query**_q, | |||
1003 | const struct sockaddr *sa, socklen_t salen, | |||
1004 | int flags, | |||
1005 | uint64_t get, | |||
1006 | sd_resolve_getnameinfo_handler_t callback, | |||
1007 | void *userdata) { | |||
1008 | ||||
1009 | _cleanup_(sd_resolve_query_unrefp)__attribute__((cleanup(sd_resolve_query_unrefp))) sd_resolve_query *q = NULL((void*)0); | |||
1010 | NameInfoRequest req; | |||
1011 | struct iovec iov[2]; | |||
1012 | struct msghdr mh; | |||
1013 | int r; | |||
1014 | ||||
1015 | assert_return(resolve, -EINVAL)do { if (!(((__builtin_expect(!!(resolve),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("resolve"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 1015, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
1016 | assert_return(sa, -EINVAL)do { if (!(((__builtin_expect(!!(sa),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("sa"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 1016, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
1017 | assert_return(salen >= sizeof(struct sockaddr), -EINVAL)do { if (!(((__builtin_expect(!!(salen >= sizeof(struct sockaddr )),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD , ("salen >= sizeof(struct sockaddr)"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 1017, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
1018 | assert_return(salen <= sizeof(union sockaddr_union), -EINVAL)do { if (!(((__builtin_expect(!!(salen <= sizeof(union sockaddr_union )),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD , ("salen <= sizeof(union sockaddr_union)"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 1018, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
1019 | assert_return((get & ~SD_RESOLVE_GET_BOTH) == 0, -EINVAL)do { if (!(((__builtin_expect(!!((get & ~SD_RESOLVE_GET_BOTH ) == 0),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD , ("(get & ~SD_RESOLVE_GET_BOTH) == 0"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 1019, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
1020 | assert_return(callback, -EINVAL)do { if (!(((__builtin_expect(!!(callback),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("callback"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 1020, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
1021 | assert_return(!resolve_pid_changed(resolve), -ECHILD)do { if (!(((__builtin_expect(!!(!resolve_pid_changed(resolve )),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD , ("!resolve_pid_changed(resolve)"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 1021, __PRETTY_FUNCTION__), 0))) return (-10); } while (0); | |||
1022 | ||||
1023 | r = alloc_query(resolve, !_q, &q); | |||
1024 | if (r < 0) | |||
1025 | return r; | |||
1026 | ||||
1027 | q->type = REQUEST_NAMEINFO; | |||
1028 | q->getnameinfo_handler = callback; | |||
1029 | q->userdata = userdata; | |||
1030 | ||||
1031 | req = (NameInfoRequest) { | |||
1032 | .header.id = q->id, | |||
1033 | .header.type = REQUEST_NAMEINFO, | |||
1034 | .header.length = sizeof(NameInfoRequest) + salen, | |||
1035 | ||||
1036 | .flags = flags, | |||
1037 | .sockaddr_len = salen, | |||
1038 | .gethost = !!(get & SD_RESOLVE_GET_HOST), | |||
1039 | .getserv = !!(get & SD_RESOLVE_GET_SERVICE), | |||
1040 | }; | |||
1041 | ||||
1042 | iov[0] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(NameInfoRequest) }; | |||
1043 | iov[1] = (struct iovec) { .iov_base = (void*) sa, .iov_len = salen }; | |||
1044 | ||||
1045 | mh = (struct msghdr) { .msg_iov = iov, .msg_iovlen = ELEMENTSOF(iov)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(iov), typeof(&*(iov))), sizeof(iov)/sizeof((iov)[ 0]), ((void)0))) }; | |||
1046 | ||||
1047 | if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNALMSG_NOSIGNAL) < 0) | |||
1048 | return -errno(*__errno_location ()); | |||
1049 | ||||
1050 | if (_q) | |||
1051 | *_q = q; | |||
1052 | ||||
1053 | resolve->n_outstanding++; | |||
1054 | TAKE_PTR(q)({ typeof(q) _ptr_ = (q); (q) = ((void*)0); _ptr_; }); | |||
1055 | ||||
1056 | return 0; | |||
1057 | } | |||
1058 | ||||
1059 | static int getnameinfo_done(sd_resolve_query *q) { | |||
1060 | ||||
1061 | assert(q)do { if ((__builtin_expect(!!(!(q)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("q"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 1061, __PRETTY_FUNCTION__); } while (0); | |||
1062 | assert(q->done)do { if ((__builtin_expect(!!(!(q->done)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("q->done"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 1062, __PRETTY_FUNCTION__); } while (0); | |||
1063 | assert(q->getnameinfo_handler)do { if ((__builtin_expect(!!(!(q->getnameinfo_handler)),0 ))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("q->getnameinfo_handler" ), "../src/libsystemd/sd-resolve/sd-resolve.c", 1063, __PRETTY_FUNCTION__ ); } while (0); | |||
1064 | ||||
1065 | errno(*__errno_location ()) = q->_errno; | |||
1066 | h_errno(*__h_errno_location ()) = q->_h_errno; | |||
1067 | ||||
1068 | return q->getnameinfo_handler(q, q->ret, q->host, q->serv, q->userdata); | |||
1069 | } | |||
1070 | ||||
1071 | _public___attribute__ ((visibility("default"))) sd_resolve_query* sd_resolve_query_ref(sd_resolve_query *q) { | |||
1072 | assert_return(q, NULL)do { if (!(((__builtin_expect(!!(q),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("q"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 1072, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while (0); | |||
1073 | ||||
1074 | assert(q->n_ref >= 1)do { if ((__builtin_expect(!!(!(q->n_ref >= 1)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("q->n_ref >= 1"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 1074, __PRETTY_FUNCTION__); } while (0); | |||
1075 | q->n_ref++; | |||
1076 | ||||
1077 | return q; | |||
1078 | } | |||
1079 | ||||
1080 | static void resolve_freeaddrinfo(struct addrinfo *ai) { | |||
1081 | while (ai) { | |||
1082 | struct addrinfo *next = ai->ai_next; | |||
1083 | ||||
1084 | free(ai->ai_addr); | |||
1085 | free(ai->ai_canonname); | |||
1086 | free(ai); | |||
1087 | ai = next; | |||
1088 | } | |||
1089 | } | |||
1090 | ||||
1091 | static void resolve_query_disconnect(sd_resolve_query *q) { | |||
1092 | sd_resolve *resolve; | |||
1093 | unsigned i; | |||
1094 | ||||
1095 | assert(q)do { if ((__builtin_expect(!!(!(q)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("q"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 1095, __PRETTY_FUNCTION__); } while (0); | |||
1096 | ||||
1097 | if (!q->resolve) | |||
1098 | return; | |||
1099 | ||||
1100 | resolve = q->resolve; | |||
1101 | assert(resolve->n_queries > 0)do { if ((__builtin_expect(!!(!(resolve->n_queries > 0) ),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("resolve->n_queries > 0" ), "../src/libsystemd/sd-resolve/sd-resolve.c", 1101, __PRETTY_FUNCTION__ ); } while (0); | |||
1102 | ||||
1103 | if (q->done) { | |||
1104 | assert(resolve->n_done > 0)do { if ((__builtin_expect(!!(!(resolve->n_done > 0)),0 ))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("resolve->n_done > 0" ), "../src/libsystemd/sd-resolve/sd-resolve.c", 1104, __PRETTY_FUNCTION__ ); } while (0); | |||
1105 | resolve->n_done--; | |||
1106 | } | |||
1107 | ||||
1108 | i = q->id % QUERIES_MAX256U; | |||
1109 | assert(resolve->query_array[i] == q)do { if ((__builtin_expect(!!(!(resolve->query_array[i] == q)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("resolve->query_array[i] == q" ), "../src/libsystemd/sd-resolve/sd-resolve.c", 1109, __PRETTY_FUNCTION__ ); } while (0); | |||
1110 | resolve->query_array[i] = NULL((void*)0); | |||
1111 | LIST_REMOVE(queries, resolve->queries, q)do { typeof(*(resolve->queries)) **_head = &(resolve-> queries), *_item = (q); do { if ((__builtin_expect(!!(!(_item )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("_item"), "../src/libsystemd/sd-resolve/sd-resolve.c", 1111, __PRETTY_FUNCTION__ ); } while (0); if (_item->queries_next) _item->queries_next ->queries_prev = _item->queries_prev; if (_item->queries_prev ) _item->queries_prev->queries_next = _item->queries_next ; else { do { if ((__builtin_expect(!!(!(*_head == _item)),0) )) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("*_head == _item" ), "../src/libsystemd/sd-resolve/sd-resolve.c", 1111, __PRETTY_FUNCTION__ ); } while (0); *_head = _item->queries_next; } _item-> queries_next = _item->queries_prev = ((void*)0); } while ( 0); | |||
1112 | resolve->n_queries--; | |||
1113 | ||||
1114 | q->resolve = NULL((void*)0); | |||
1115 | if (!q->floating) | |||
1116 | sd_resolve_unref(resolve); | |||
1117 | } | |||
1118 | ||||
1119 | static void resolve_query_free(sd_resolve_query *q) { | |||
1120 | assert(q)do { if ((__builtin_expect(!!(!(q)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("q"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 1120, __PRETTY_FUNCTION__); } while (0); | |||
1121 | ||||
1122 | resolve_query_disconnect(q); | |||
1123 | ||||
1124 | resolve_freeaddrinfo(q->addrinfo); | |||
1125 | free(q->host); | |||
1126 | free(q->serv); | |||
1127 | free(q); | |||
1128 | } | |||
1129 | ||||
1130 | _public___attribute__ ((visibility("default"))) sd_resolve_query* sd_resolve_query_unref(sd_resolve_query* q) { | |||
1131 | if (!q
| |||
1132 | return NULL((void*)0); | |||
1133 | ||||
1134 | assert(q->n_ref >= 1)do { if ((__builtin_expect(!!(!(q->n_ref >= 1)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("q->n_ref >= 1"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 1134, __PRETTY_FUNCTION__); } while (0); | |||
1135 | q->n_ref--; | |||
1136 | ||||
1137 | if (q->n_ref <= 0) | |||
1138 | resolve_query_free(q); | |||
1139 | ||||
1140 | return NULL((void*)0); | |||
1141 | } | |||
1142 | ||||
1143 | _public___attribute__ ((visibility("default"))) int sd_resolve_query_is_done(sd_resolve_query *q) { | |||
1144 | assert_return(q, -EINVAL)do { if (!(((__builtin_expect(!!(q),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("q"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 1144, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
1145 | assert_return(!resolve_pid_changed(q->resolve), -ECHILD)do { if (!(((__builtin_expect(!!(!resolve_pid_changed(q->resolve )),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD , ("!resolve_pid_changed(q->resolve)"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 1145, __PRETTY_FUNCTION__), 0))) return (-10); } while (0); | |||
1146 | ||||
1147 | return q->done; | |||
1148 | } | |||
1149 | ||||
1150 | _public___attribute__ ((visibility("default"))) void* sd_resolve_query_set_userdata(sd_resolve_query *q, void *userdata) { | |||
1151 | void *ret; | |||
1152 | ||||
1153 | assert_return(q, NULL)do { if (!(((__builtin_expect(!!(q),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("q"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 1153, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while (0); | |||
1154 | assert_return(!resolve_pid_changed(q->resolve), NULL)do { if (!(((__builtin_expect(!!(!resolve_pid_changed(q->resolve )),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD , ("!resolve_pid_changed(q->resolve)"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 1154, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while (0); | |||
1155 | ||||
1156 | ret = q->userdata; | |||
1157 | q->userdata = userdata; | |||
1158 | ||||
1159 | return ret; | |||
1160 | } | |||
1161 | ||||
1162 | _public___attribute__ ((visibility("default"))) void* sd_resolve_query_get_userdata(sd_resolve_query *q) { | |||
1163 | assert_return(q, NULL)do { if (!(((__builtin_expect(!!(q),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("q"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 1163, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while (0); | |||
1164 | assert_return(!resolve_pid_changed(q->resolve), NULL)do { if (!(((__builtin_expect(!!(!resolve_pid_changed(q->resolve )),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD , ("!resolve_pid_changed(q->resolve)"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 1164, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while (0); | |||
1165 | ||||
1166 | return q->userdata; | |||
1167 | } | |||
1168 | ||||
1169 | _public___attribute__ ((visibility("default"))) sd_resolve *sd_resolve_query_get_resolve(sd_resolve_query *q) { | |||
1170 | assert_return(q, NULL)do { if (!(((__builtin_expect(!!(q),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("q"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 1170, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while (0); | |||
1171 | assert_return(!resolve_pid_changed(q->resolve), NULL)do { if (!(((__builtin_expect(!!(!resolve_pid_changed(q->resolve )),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD , ("!resolve_pid_changed(q->resolve)"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 1171, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while (0); | |||
1172 | ||||
1173 | return q->resolve; | |||
1174 | } | |||
1175 | ||||
1176 | static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) { | |||
1177 | sd_resolve *resolve = userdata; | |||
1178 | int r; | |||
1179 | ||||
1180 | assert(resolve)do { if ((__builtin_expect(!!(!(resolve)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("resolve"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 1180, __PRETTY_FUNCTION__); } while (0); | |||
1181 | ||||
1182 | r = sd_resolve_process(resolve); | |||
1183 | if (r < 0) | |||
1184 | return r; | |||
1185 | ||||
1186 | return 1; | |||
1187 | } | |||
1188 | ||||
1189 | _public___attribute__ ((visibility("default"))) int sd_resolve_attach_event(sd_resolve *resolve, sd_event *event, int64_t priority) { | |||
1190 | int r; | |||
1191 | ||||
1192 | assert_return(resolve, -EINVAL)do { if (!(((__builtin_expect(!!(resolve),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("resolve"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 1192, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
1193 | assert_return(!resolve->event, -EBUSY)do { if (!(((__builtin_expect(!!(!resolve->event),1))) ? ( 1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!resolve->event" ), "../src/libsystemd/sd-resolve/sd-resolve.c", 1193, __PRETTY_FUNCTION__ ), 0))) return (-16); } while (0); | |||
1194 | ||||
1195 | assert(!resolve->event_source)do { if ((__builtin_expect(!!(!(!resolve->event_source)),0 ))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!resolve->event_source" ), "../src/libsystemd/sd-resolve/sd-resolve.c", 1195, __PRETTY_FUNCTION__ ); } while (0); | |||
1196 | ||||
1197 | if (event) | |||
1198 | resolve->event = sd_event_ref(event); | |||
1199 | else { | |||
1200 | r = sd_event_default(&resolve->event); | |||
1201 | if (r < 0) | |||
1202 | return r; | |||
1203 | } | |||
1204 | ||||
1205 | r = sd_event_add_io(resolve->event, &resolve->event_source, resolve->fds[RESPONSE_RECV_FD], POLLIN0x001, io_callback, resolve); | |||
1206 | if (r < 0) | |||
1207 | goto fail; | |||
1208 | ||||
1209 | r = sd_event_source_set_priority(resolve->event_source, priority); | |||
1210 | if (r < 0) | |||
1211 | goto fail; | |||
1212 | ||||
1213 | return 0; | |||
1214 | ||||
1215 | fail: | |||
1216 | sd_resolve_detach_event(resolve); | |||
1217 | return r; | |||
1218 | } | |||
1219 | ||||
1220 | _public___attribute__ ((visibility("default"))) int sd_resolve_detach_event(sd_resolve *resolve) { | |||
1221 | assert_return(resolve, -EINVAL)do { if (!(((__builtin_expect(!!(resolve),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("resolve"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 1221, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
1222 | ||||
1223 | if (!resolve->event) | |||
1224 | return 0; | |||
1225 | ||||
1226 | if (resolve->event_source) { | |||
1227 | sd_event_source_set_enabled(resolve->event_source, SD_EVENT_OFF); | |||
1228 | resolve->event_source = sd_event_source_unref(resolve->event_source); | |||
1229 | } | |||
1230 | ||||
1231 | resolve->event = sd_event_unref(resolve->event); | |||
1232 | return 1; | |||
1233 | } | |||
1234 | ||||
1235 | _public___attribute__ ((visibility("default"))) sd_event *sd_resolve_get_event(sd_resolve *resolve) { | |||
1236 | assert_return(resolve, NULL)do { if (!(((__builtin_expect(!!(resolve),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("resolve"), "../src/libsystemd/sd-resolve/sd-resolve.c" , 1236, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while (0); | |||
1237 | ||||
1238 | return resolve->event; | |||
1239 | } |