Bug Summary

File:src/lib/libc/asr/getaddrinfo_async.c
Warning:line 548, column 25
The right operand of '!=' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name getaddrinfo_async.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/lib/libc/obj -resource-dir /usr/local/llvm16/lib/clang/16 -include namespace.h -I /usr/src/lib/libc/include -I /usr/src/lib/libc/hidden -D __LIBC__ -D APIWARN -D YP -I /usr/src/lib/libc/yp -I /usr/src/lib/libc -I /usr/src/lib/libc/gdtoa -I /usr/src/lib/libc/arch/amd64/gdtoa -D INFNAN_CHECK -D MULTIPLE_THREADS -D NO_FENV_H -D USE_LOCALE -I /usr/src/lib/libc -I /usr/src/lib/libc/citrus -D RESOLVSORT -D FLOATING_POINT -D PRINTF_WIDE_CHAR -D SCANF_WIDE_CHAR -D FUTEX -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/lib/libc/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/lib/libc/asr/getaddrinfo_async.c
1/* $OpenBSD: getaddrinfo_async.c,v 1.61 2023/11/21 15:26:56 florian Exp $ */
2/*
3 * Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <sys/types.h>
19#include <sys/socket.h>
20#include <sys/uio.h>
21#include <netinet/in.h>
22#include <arpa/nameser.h>
23#include <net/if.h>
24#include <netdb.h>
25
26#include <asr.h>
27#include <errno(*__errno()).h>
28#include <ifaddrs.h>
29#include <resolv.h>
30#include <stdlib.h>
31#include <string.h>
32#include <unistd.h>
33#include <limits.h>
34
35#include "asr_private.h"
36
37struct match {
38 int family;
39 int socktype;
40 int protocol;
41};
42
43static int getaddrinfo_async_run(struct asr_query *, struct asr_result *);
44static int get_port(const char *, const char *, int);
45static int iter_family(struct asr_query *, int);
46static int addrinfo_add(struct asr_query *, const struct sockaddr *, const char *);
47static int addrinfo_from_file(struct asr_query *, int, FILE *);
48static int addrinfo_from_pkt(struct asr_query *, char *, size_t);
49static int addrconfig_setup(struct asr_query *);
50
51static const struct match matches[] = {
52 { PF_INET2, SOCK_DGRAM2, IPPROTO_UDP17 },
53 { PF_INET2, SOCK_STREAM1, IPPROTO_TCP6 },
54 { PF_INET2, SOCK_RAW3, 0 },
55 { PF_INET624, SOCK_DGRAM2, IPPROTO_UDP17 },
56 { PF_INET624, SOCK_STREAM1, IPPROTO_TCP6 },
57 { PF_INET624, SOCK_RAW3, 0 },
58 { -1, 0, 0, },
59};
60
61#define MATCH_FAMILY(a, b)((a) == matches[(b)].family || (a) == 0) ((a) == matches[(b)].family || (a) == PF_UNSPEC0)
62#define MATCH_PROTO(a, b)((a) == matches[(b)].protocol || (a) == 0 || matches[(b)].protocol
== 0)
((a) == matches[(b)].protocol || (a) == 0 || matches[(b)].protocol == 0)
63/* Do not match SOCK_RAW unless explicitly specified */
64#define MATCH_SOCKTYPE(a, b)((a) == matches[(b)].socktype || ((a) == 0 && matches
[(b)].socktype != 3))
((a) == matches[(b)].socktype || ((a) == 0 && \
65 matches[(b)].socktype != SOCK_RAW3))
66
67enum {
68 DOM_INIT,
69 DOM_DOMAIN,
70 DOM_DONE
71};
72
73struct asr_query *
74getaddrinfo_async(const char *hostname, const char *servname,
75 const struct addrinfo *hints, void *asr)
76{
77 struct asr_ctx *ac;
78 struct asr_query *as;
79
80 if (hints == NULL((void *)0) || (hints->ai_flags & AI_NUMERICHOST4) == 0)
81 ac = _asr_use_resolver(asr);
82 else
83 ac = _asr_no_resolver();
84 if ((as = _asr_async_new(ac, ASR_GETADDRINFO)) == NULL((void *)0))
85 goto abort; /* errno set */
86 as->as_run = getaddrinfo_async_run;
87
88 if (hostname) {
89 if ((as->as.ai.hostname = strdup(hostname)) == NULL((void *)0))
90 goto abort; /* errno set */
91 }
92 if (servname && (as->as.ai.servname = strdup(servname)) == NULL((void *)0))
93 goto abort; /* errno set */
94 if (hints)
95 memmove(&as->as.ai.hints, hints, sizeof *hints);
96 else {
97 memset(&as->as.ai.hints, 0, sizeof as->as.ai.hints);
98 as->as.ai.hints.ai_family = PF_UNSPEC0;
99 as->as.ai.hints.ai_flags = AI_ADDRCONFIG64;
100 }
101
102 _asr_ctx_unref(ac);
103 return (as);
104 abort:
105 if (as)
106 _asr_async_free(as);
107 _asr_ctx_unref(ac);
108 return (NULL((void *)0));
109}
110DEF_WEAK(getaddrinfo_async)__asm__(".weak " "getaddrinfo_async" " ; " "getaddrinfo_async"
" = " "_libc_getaddrinfo_async")
;
111
112static int
113getaddrinfo_async_run(struct asr_query *as, struct asr_result *ar)
114{
115 char fqdn[MAXDNAME1025];
116 const char *str;
117 struct addrinfo *ai;
118 int i, family, r, is_localhost = 0;
119 FILE *f;
120 union {
121 struct sockaddr sa;
122 struct sockaddr_in sain;
123 struct sockaddr_in6 sain6;
124 } sa;
125
126 next:
127 switch (as->as_state) {
1
Control jumps to 'case ASR_STATE_SAME_DB:' at line 363
128
129 case ASR_STATE_INIT:
130
131 /*
132 * First, make sure the parameters are valid.
133 */
134
135 as->as_count = 0;
136
137 if (as->as.ai.hostname == NULL((void *)0) &&
138 as->as.ai.servname == NULL((void *)0)) {
139 ar->ar_gai_errno = EAI_NONAME-2;
140 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
141 break;
142 }
143
144 if (as->as.ai.hostname && as->as.ai.hostname[0] == '\0') {
145 ar->ar_gai_errno = EAI_NODATA-5;
146 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
147 break;
148 }
149
150 ai = &as->as.ai.hints;
151
152 if (ai->ai_addrlen ||
153 ai->ai_canonname ||
154 ai->ai_addr ||
155 ai->ai_next) {
156 ar->ar_gai_errno = EAI_BADHINTS-12;
157 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
158 break;
159 }
160
161 if (ai->ai_flags & ~AI_MASK(1 | 2 | 4 | 16 | 32 | 64) ||
162 (ai->ai_flags & AI_CANONNAME2 && ai->ai_flags & AI_FQDN32)) {
163 ar->ar_gai_errno = EAI_BADFLAGS-1;
164 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
165 break;
166 }
167
168 if (ai->ai_family != PF_UNSPEC0 &&
169 ai->ai_family != PF_INET2 &&
170 ai->ai_family != PF_INET624) {
171 ar->ar_gai_errno = EAI_FAMILY-6;
172 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
173 break;
174 }
175
176 if (ai->ai_socktype &&
177 ai->ai_socktype != SOCK_DGRAM2 &&
178 ai->ai_socktype != SOCK_STREAM1 &&
179 ai->ai_socktype != SOCK_RAW3) {
180 ar->ar_gai_errno = EAI_SOCKTYPE-7;
181 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
182 break;
183 }
184
185 if (ai->ai_socktype == SOCK_RAW3 &&
186 get_port(as->as.ai.servname, NULL((void *)0), 1) != 0) {
187 ar->ar_gai_errno = EAI_SERVICE-8;
188 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
189 break;
190 }
191
192 /* Restrict result set to configured address families */
193 if (ai->ai_flags & AI_ADDRCONFIG64) {
194 if (addrconfig_setup(as) == -1) {
195 ar->ar_errno = errno(*__errno());
196 ar->ar_gai_errno = EAI_SYSTEM-11;
197 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
198 break;
199 }
200 }
201
202 /* Make sure there is at least a valid combination */
203 for (i = 0; matches[i].family != -1; i++)
204 if (MATCH_FAMILY(ai->ai_family, i)((ai->ai_family) == matches[(i)].family || (ai->ai_family
) == 0)
&&
205 MATCH_SOCKTYPE(ai->ai_socktype, i)((ai->ai_socktype) == matches[(i)].socktype || ((ai->ai_socktype
) == 0 && matches[(i)].socktype != 3))
&&
206 MATCH_PROTO(ai->ai_protocol, i)((ai->ai_protocol) == matches[(i)].protocol || (ai->ai_protocol
) == 0 || matches[(i)].protocol == 0)
)
207 break;
208 if (matches[i].family == -1) {
209 ar->ar_gai_errno = EAI_BADHINTS-12;
210 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
211 break;
212 }
213
214 if (ai->ai_protocol == 0 || ai->ai_protocol == IPPROTO_UDP17)
215 as->as.ai.port_udp = get_port(as->as.ai.servname, "udp",
216 as->as.ai.hints.ai_flags & AI_NUMERICSERV16);
217 if (ai->ai_protocol == 0 || ai->ai_protocol == IPPROTO_TCP6)
218 as->as.ai.port_tcp = get_port(as->as.ai.servname, "tcp",
219 as->as.ai.hints.ai_flags & AI_NUMERICSERV16);
220 if (as->as.ai.port_tcp == -2 || as->as.ai.port_udp == -2 ||
221 (as->as.ai.port_tcp == -1 && as->as.ai.port_udp == -1) ||
222 (ai->ai_protocol && (as->as.ai.port_udp == -1 ||
223 as->as.ai.port_tcp == -1))) {
224 ar->ar_gai_errno = EAI_SERVICE-8;
225 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
226 break;
227 }
228
229 ar->ar_gai_errno = 0;
230
231 if (!(ai->ai_flags & AI_NUMERICHOST4))
232 is_localhost = _asr_is_localhost(as->as.ai.hostname);
233 /*
234 * If hostname is NULL, "localhost" or falls within the
235 * ".localhost." domain, use local address.
236 * RFC 6761, 6.3:
237 * 3. Name resolution APIs and libraries SHOULD recognize
238 * localhost names as special and SHOULD always return the IP
239 * loopback address for address queries and negative responses
240 * for all other query types. Name resolution APIs SHOULD NOT
241 * send queries for localhost names to their configured caching
242 * DNS server(s).
243 */
244 if (as->as.ai.hostname == NULL((void *)0) || is_localhost) {
245 for (family = iter_family(as, 1);
246 family != -1;
247 family = iter_family(as, 0)) {
248 /*
249 * We could use statically built sockaddrs for
250 * those, rather than parsing over and over.
251 */
252 if (family == PF_INET2)
253 str = (ai->ai_flags & AI_PASSIVE1 &&
254 !is_localhost) ? "0.0.0.0" :
255 "127.0.0.1";
256 else /* PF_INET6 */
257 str = (ai->ai_flags & AI_PASSIVE1 &&
258 !is_localhost) ? "::" : "::1";
259 /* This can't fail */
260 _asr_sockaddr_from_str(&sa.sa, family, str);
261 if ((r = addrinfo_add(as, &sa.sa, NULL((void *)0)))) {
262 ar->ar_gai_errno = r;
263 break;
264 }
265 }
266 if (ar->ar_gai_errno == 0 && as->as_count == 0) {
267 ar->ar_gai_errno = EAI_NODATA-5;
268 }
269 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
270 break;
271 }
272
273 /* Try numeric addresses first */
274 for (family = iter_family(as, 1);
275 family != -1;
276 family = iter_family(as, 0)) {
277
278 if (_asr_sockaddr_from_str(&sa.sa, family,
279 as->as.ai.hostname) == -1)
280 continue;
281
282 if ((r = addrinfo_add(as, &sa.sa, NULL((void *)0))))
283 ar->ar_gai_errno = r;
284 break;
285 }
286 if (ar->ar_gai_errno || as->as_count) {
287 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
288 break;
289 }
290
291 if (ai->ai_flags & AI_NUMERICHOST4) {
292 ar->ar_gai_errno = EAI_NONAME-2;
293 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
294 break;
295 }
296
297 /* make sure there are no funny characters in hostname */
298 if (!hnok_lenient(as->as.ai.hostname)) {
299 ar->ar_gai_errno = EAI_FAIL-4;
300 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
301 break;
302 }
303
304 async_set_state(as, ASR_STATE_NEXT_DB)do { ; (as)->as_state = (ASR_STATE_NEXT_DB); } while (0);
305 break;
306
307 case ASR_STATE_NEXT_DB:
308 if (_asr_iter_db(as) == -1) {
309 async_set_state(as, ASR_STATE_NOT_FOUND)do { ; (as)->as_state = (ASR_STATE_NOT_FOUND); } while (0);
310 break;
311 }
312 as->as_family_idx = 0;
313 async_set_state(as, ASR_STATE_SAME_DB)do { ; (as)->as_state = (ASR_STATE_SAME_DB); } while (0);
314 break;
315
316 case ASR_STATE_NEXT_FAMILY:
317 as->as_family_idx += 1;
318 if (as->as.ai.hints.ai_family != AF_UNSPEC0 ||
319 AS_FAMILY(as)((as)->as_ctx->ac_family[(as)->as_family_idx]) == -1) {
320 /* The family was specified, or we have tried all
321 * families with this DB.
322 */
323 if (as->as_count) {
324 ar->ar_gai_errno = 0;
325 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
326 } else
327 async_set_state(as, ASR_STATE_NEXT_DOMAIN)do { ; (as)->as_state = (ASR_STATE_NEXT_DOMAIN); } while (
0)
;
328 break;
329 }
330 async_set_state(as, ASR_STATE_SAME_DB)do { ; (as)->as_state = (ASR_STATE_SAME_DB); } while (0);
331 break;
332
333 case ASR_STATE_NEXT_DOMAIN:
334 /* domain search is only for dns */
335 if (AS_DB(as)((as)->as_ctx->ac_db[(as)->as_db_idx - 1]) != ASR_DB_DNS'b') {
336 async_set_state(as, ASR_STATE_NEXT_DB)do { ; (as)->as_state = (ASR_STATE_NEXT_DB); } while (0);
337 break;
338 }
339 as->as_family_idx = 0;
340
341 free(as->as.ai.fqdn);
342 as->as.ai.fqdn = NULL((void *)0);
343 r = _asr_iter_domain(as, as->as.ai.hostname, fqdn, sizeof(fqdn));
344 if (r == -1) {
345 async_set_state(as, ASR_STATE_NEXT_DB)do { ; (as)->as_state = (ASR_STATE_NEXT_DB); } while (0);
346 break;
347 }
348 if (r == 0) {
349 ar->ar_gai_errno = EAI_FAIL-4;
350 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
351 break;
352 }
353 as->as.ai.fqdn = strdup(fqdn);
354 if (as->as.ai.fqdn == NULL((void *)0)) {
355 ar->ar_gai_errno = EAI_MEMORY-10;
356 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
357 break;
358 }
359
360 async_set_state(as, ASR_STATE_SAME_DB)do { ; (as)->as_state = (ASR_STATE_SAME_DB); } while (0);
361 break;
362
363 case ASR_STATE_SAME_DB:
364 /* query the current DB again */
365 switch (AS_DB(as)((as)->as_ctx->ac_db[(as)->as_db_idx - 1])) {
2
Control jumps to 'case 102:' at line 403
366 case ASR_DB_DNS'b':
367 if (as->as.ai.fqdn == NULL((void *)0)) {
368 /* First try, initialize domain iteration */
369 as->as_dom_flags = 0;
370 as->as_dom_step = DOM_INIT;
371 async_set_state(as, ASR_STATE_NEXT_DOMAIN)do { ; (as)->as_state = (ASR_STATE_NEXT_DOMAIN); } while (
0)
;
372 break;
373 }
374
375 family = (as->as.ai.hints.ai_family == AF_UNSPEC0) ?
376 AS_FAMILY(as)((as)->as_ctx->ac_family[(as)->as_family_idx]) : as->as.ai.hints.ai_family;
377
378 if (family == AF_INET2 &&
379 as->as_flags & ASYNC_NO_INET0x00010000) {
380 async_set_state(as, ASR_STATE_NEXT_FAMILY)do { ; (as)->as_state = (ASR_STATE_NEXT_FAMILY); } while (
0)
;
381 break;
382 } else if (family == AF_INET624 &&
383 as->as_flags & ASYNC_NO_INET60x00020000) {
384 async_set_state(as, ASR_STATE_NEXT_FAMILY)do { ; (as)->as_state = (ASR_STATE_NEXT_FAMILY); } while (
0)
;
385 break;
386 }
387
388 as->as_subq = _res_query_async_ctx(as->as.ai.fqdn,
389 C_IN1, (family == AF_INET624) ? T_AAAA28 : T_A1,
390 as->as_ctx);
391
392 if (as->as_subq == NULL((void *)0)) {
393 if (errno(*__errno()) == ENOMEM12)
394 ar->ar_gai_errno = EAI_MEMORY-10;
395 else
396 ar->ar_gai_errno = EAI_FAIL-4;
397 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
398 break;
399 }
400 async_set_state(as, ASR_STATE_SUBQUERY)do { ; (as)->as_state = (ASR_STATE_SUBQUERY); } while (0);
401 break;
402
403 case ASR_DB_FILE'f':
404 f = fopen(_PATH_HOSTS"/etc/hosts", "re");
405 if (f == NULL((void *)0)) {
3
Assuming 'f' is not equal to NULL
406 async_set_state(as, ASR_STATE_NEXT_DB)do { ; (as)->as_state = (ASR_STATE_NEXT_DB); } while (0);
407 break;
408 }
409 family = (as->as.ai.hints.ai_family == AF_UNSPEC0) ?
4
Assuming field 'ai_family' is not equal to AF_UNSPEC
5
'?' condition is false
410 AS_FAMILY(as)((as)->as_ctx->ac_family[(as)->as_family_idx]) : as->as.ai.hints.ai_family;
411
412 r = addrinfo_from_file(as, family, f);
6
Calling 'addrinfo_from_file'
413 if (r == -1) {
414 if (errno(*__errno()) == ENOMEM12)
415 ar->ar_gai_errno = EAI_MEMORY-10;
416 else
417 ar->ar_gai_errno = EAI_FAIL-4;
418 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
419 } else
420 async_set_state(as, ASR_STATE_NEXT_FAMILY)do { ; (as)->as_state = (ASR_STATE_NEXT_FAMILY); } while (
0)
;
421 fclose(f);
422 break;
423
424 default:
425 async_set_state(as, ASR_STATE_NEXT_DB)do { ; (as)->as_state = (ASR_STATE_NEXT_DB); } while (0);
426 }
427 break;
428
429 case ASR_STATE_SUBQUERY:
430 if ((r = asr_run(as->as_subq, ar)) == ASYNC_COND0)
431 return (ASYNC_COND0);
432
433 as->as_subq = NULL((void *)0);
434
435 if (ar->ar_datalen == -1) {
436 async_set_state(as, ASR_STATE_NEXT_FAMILY)do { ; (as)->as_state = (ASR_STATE_NEXT_FAMILY); } while (
0)
;
437 break;
438 }
439
440 r = addrinfo_from_pkt(as, ar->ar_data, ar->ar_datalen);
441 if (r == -1) {
442 if (errno(*__errno()) == ENOMEM12)
443 ar->ar_gai_errno = EAI_MEMORY-10;
444 else
445 ar->ar_gai_errno = EAI_FAIL-4;
446 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
447 } else
448 async_set_state(as, ASR_STATE_NEXT_FAMILY)do { ; (as)->as_state = (ASR_STATE_NEXT_FAMILY); } while (
0)
;
449 free(ar->ar_data);
450 break;
451
452 case ASR_STATE_NOT_FOUND:
453 /* No result found. Maybe we can try again. */
454 if (as->as_flags & ASYNC_AGAIN0x00000200)
455 ar->ar_gai_errno = EAI_AGAIN-3;
456 else
457 ar->ar_gai_errno = EAI_NODATA-5;
458 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
459 break;
460
461 case ASR_STATE_HALT:
462 if (ar->ar_gai_errno == 0) {
463 ar->ar_count = as->as_count;
464 ar->ar_addrinfo = as->as.ai.aifirst;
465 as->as.ai.aifirst = NULL((void *)0);
466 } else {
467 ar->ar_count = 0;
468 ar->ar_addrinfo = NULL((void *)0);
469 }
470 return (ASYNC_DONE1);
471
472 default:
473 ar->ar_errno = EOPNOTSUPP45;
474 ar->ar_gai_errno = EAI_SYSTEM-11;
475 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
476 break;
477 }
478 goto next;
479}
480
481/*
482 * Retrieve the port number for the service name "servname" and
483 * the protocol "proto".
484 */
485static int
486get_port(const char *servname, const char *proto, int numonly)
487{
488 struct servent se;
489 struct servent_data sed;
490 int port;
491 const char *e;
492
493 if (servname == NULL((void *)0))
494 return (0);
495
496 e = NULL((void *)0);
497 port = strtonum(servname, 0, USHRT_MAX0xffff, &e);
498 if (e == NULL((void *)0))
499 return (port);
500 if (errno(*__errno()) == ERANGE34)
501 return (-2); /* invalid */
502 if (numonly)
503 return (-2);
504
505 port = -1;
506 memset(&sed, 0, sizeof(sed));
507 if (getservbyname_r(servname, proto, &se, &sed) != -1)
508 port = ntohs(se.s_port)(__uint16_t)(__builtin_constant_p(se.s_port) ? (__uint16_t)((
(__uint16_t)(se.s_port) & 0xffU) << 8 | ((__uint16_t
)(se.s_port) & 0xff00U) >> 8) : __swap16md(se.s_port
))
;
509 endservent_r(&sed);
510
511 return (port);
512}
513
514/*
515 * Iterate over the address families that are to be queried. Use the
516 * list on the async context, unless a specific family was given in hints.
517 */
518static int
519iter_family(struct asr_query *as, int first)
520{
521 if (first) {
522 as->as_family_idx = 0;
523 if (as->as.ai.hints.ai_family != PF_UNSPEC0)
524 return as->as.ai.hints.ai_family;
525 return AS_FAMILY(as)((as)->as_ctx->ac_family[(as)->as_family_idx]);
526 }
527
528 if (as->as.ai.hints.ai_family != PF_UNSPEC0)
529 return (-1);
530
531 as->as_family_idx++;
532
533 return AS_FAMILY(as)((as)->as_ctx->ac_family[(as)->as_family_idx]);
534}
535
536/*
537 * Use the sockaddr at "sa" to extend the result list on the "as" context,
538 * with the specified canonical name "cname". This function adds one
539 * entry per protocol/socktype match.
540 */
541static int
542addrinfo_add(struct asr_query *as, const struct sockaddr *sa, const char *cname)
543{
544 struct addrinfo *ai;
545 int i, port, proto;
546
547 for (i = 0; matches[i].family != -1; i++) {
17
Assuming the condition is true
548 if (matches[i].family != sa->sa_family ||
18
The right operand of '!=' is a garbage value
549 !MATCH_SOCKTYPE(as->as.ai.hints.ai_socktype, i)((as->as.ai.hints.ai_socktype) == matches[(i)].socktype ||
((as->as.ai.hints.ai_socktype) == 0 && matches[(i
)].socktype != 3))
||
550 !MATCH_PROTO(as->as.ai.hints.ai_protocol, i)((as->as.ai.hints.ai_protocol) == matches[(i)].protocol ||
(as->as.ai.hints.ai_protocol) == 0 || matches[(i)].protocol
== 0)
)
551 continue;
552
553 proto = as->as.ai.hints.ai_protocol;
554 if (!proto)
555 proto = matches[i].protocol;
556
557 if (proto == IPPROTO_TCP6)
558 port = as->as.ai.port_tcp;
559 else if (proto == IPPROTO_UDP17)
560 port = as->as.ai.port_udp;
561 else
562 port = 0;
563
564 /* servname specified, but not defined for this protocol */
565 if (port == -1)
566 continue;
567
568 ai = calloc(1, sizeof(*ai) + sa->sa_len);
569 if (ai == NULL((void *)0))
570 return (EAI_MEMORY-10);
571 ai->ai_family = sa->sa_family;
572 ai->ai_socktype = matches[i].socktype;
573 ai->ai_protocol = proto;
574 ai->ai_flags = as->as.ai.hints.ai_flags;
575 ai->ai_addrlen = sa->sa_len;
576 ai->ai_addr = (void *)(ai + 1);
577 if (cname &&
578 as->as.ai.hints.ai_flags & (AI_CANONNAME2 | AI_FQDN32)) {
579 if ((ai->ai_canonname = strdup(cname)) == NULL((void *)0)) {
580 free(ai);
581 return (EAI_MEMORY-10);
582 }
583 }
584 memmove(ai->ai_addr, sa, sa->sa_len);
585 if (sa->sa_family == PF_INET2)
586 ((struct sockaddr_in *)ai->ai_addr)->sin_port =
587 htons(port)(__uint16_t)(__builtin_constant_p(port) ? (__uint16_t)(((__uint16_t
)(port) & 0xffU) << 8 | ((__uint16_t)(port) & 0xff00U
) >> 8) : __swap16md(port))
;
588 else if (sa->sa_family == PF_INET624)
589 ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port =
590 htons(port)(__uint16_t)(__builtin_constant_p(port) ? (__uint16_t)(((__uint16_t
)(port) & 0xffU) << 8 | ((__uint16_t)(port) & 0xff00U
) >> 8) : __swap16md(port))
;
591
592 if (as->as.ai.aifirst == NULL((void *)0))
593 as->as.ai.aifirst = ai;
594 if (as->as.ai.ailast)
595 as->as.ai.ailast->ai_next = ai;
596 as->as.ai.ailast = ai;
597 as->as_count += 1;
598 }
599
600 return (0);
601}
602
603static int
604addrinfo_from_file(struct asr_query *as, int family, FILE *f)
605{
606 char *tokens[MAXTOKEN10], *c, buf[BUFSIZ1024 + 1];
607 int n, i;
608 union {
609 struct sockaddr sa;
610 struct sockaddr_in sain;
611 struct sockaddr_in6 sain6;
612 } u;
613
614 for (;;) {
7
Loop condition is true. Entering loop body
615 n = _asr_parse_namedb_line(f, tokens, MAXTOKEN10, buf, sizeof(buf));
616 if (n == -1)
8
Assuming the condition is false
9
Taking false branch
617 break; /* ignore errors reading the file */
618
619 for (i = 1; i < n; i++) {
10
Assuming 'i' is >= 'n'
11
Loop condition is false. Execution continues on line 626
620 if (strcasecmp(as->as.ai.hostname, tokens[i]))
621 continue;
622 if (_asr_sockaddr_from_str(&u.sa, family, tokens[0]) == -1)
623 continue;
624 break;
625 }
626 if (i == n)
12
Assuming 'i' is not equal to 'n'
13
Taking false branch
627 continue;
628
629 if (as->as.ai.hints.ai_flags & (AI_CANONNAME2 | AI_FQDN32))
14
Assuming the condition is false
15
Taking false branch
630 c = tokens[1];
631 else
632 c = NULL((void *)0);
633
634 if (addrinfo_add(as, &u.sa, c))
16
Calling 'addrinfo_add'
635 return (-1); /* errno set */
636 }
637 return (0);
638}
639
640static int
641addrinfo_from_pkt(struct asr_query *as, char *pkt, size_t pktlen)
642{
643 struct asr_unpack p;
644 struct asr_dns_header h;
645 struct asr_dns_query q;
646 struct asr_dns_rr rr;
647 int i;
648 union {
649 struct sockaddr sa;
650 struct sockaddr_in sain;
651 struct sockaddr_in6 sain6;
652 } u;
653 char buf[MAXDNAME1025], *c;
654
655 _asr_unpack_init(&p, pkt, pktlen);
656 _asr_unpack_header(&p, &h);
657 for (; h.qdcount; h.qdcount--)
658 _asr_unpack_query(&p, &q);
659
660 for (i = 0; i < h.ancount; i++) {
661 _asr_unpack_rr(&p, &rr);
662 if (rr.rr_type != q.q_type ||
663 rr.rr_class != q.q_class)
664 continue;
665
666 memset(&u, 0, sizeof u);
667 if (rr.rr_type == T_A1) {
668 u.sain.sin_len = sizeof u.sain;
669 u.sain.sin_family = AF_INET2;
670 u.sain.sin_addr = rr.rr.in_a.addr;
671 u.sain.sin_port = 0;
672 } else if (rr.rr_type == T_AAAA28) {
673 u.sain6.sin6_len = sizeof u.sain6;
674 u.sain6.sin6_family = AF_INET624;
675 u.sain6.sin6_addr = rr.rr.in_aaaa.addr6;
676 u.sain6.sin6_port = 0;
677 } else
678 continue;
679
680 if (as->as.ai.hints.ai_flags & AI_CANONNAME2) {
681 _asr_strdname(rr.rr_dname, buf, sizeof buf);
682 buf[strlen(buf) - 1] = '\0';
683 c = res_hnok__res_hnok(buf) ? buf : NULL((void *)0);
684 } else if (as->as.ai.hints.ai_flags & AI_FQDN32)
685 c = as->as.ai.fqdn;
686 else
687 c = NULL((void *)0);
688
689 if (addrinfo_add(as, &u.sa, c))
690 return (-1); /* errno set */
691 }
692 return (0);
693}
694
695static int
696addrconfig_setup(struct asr_query *as)
697{
698 struct ifaddrs *ifa, *ifa0;
699 struct if_data *ifa_data;
700 struct sockaddr_in *sinp;
701 struct sockaddr_in6 *sin6p;
702 int rtable, ifa_rtable = -1;
703
704 if (getifaddrs(&ifa0) == -1)
705 return (-1);
706
707 rtable = getrtable();
708
709 as->as_flags |= ASYNC_NO_INET0x00010000 | ASYNC_NO_INET60x00020000;
710
711 for (ifa = ifa0; ifa != NULL((void *)0); ifa = ifa->ifa_next) {
712 if (ifa->ifa_addr == NULL((void *)0))
713 continue;
714
715 switch (ifa->ifa_addr->sa_family) {
716 case PF_LINK18:
717 /* AF_LINK comes before inet / inet6 on an interface */
718 ifa_data = (struct if_data *)ifa->ifa_data;
719 ifa_rtable = ifa_data->ifi_rdomain;
720 break;
721 case PF_INET2:
722 if (ifa_rtable != rtable)
723 continue;
724
725 sinp = (struct sockaddr_in *)ifa->ifa_addr;
726
727 if (sinp->sin_addr.s_addr == htonl(INADDR_LOOPBACK)(__uint32_t)(__builtin_constant_p(((u_int32_t)(0x7f000001))) ?
(__uint32_t)(((__uint32_t)(((u_int32_t)(0x7f000001))) & 0xff
) << 24 | ((__uint32_t)(((u_int32_t)(0x7f000001))) &
0xff00) << 8 | ((__uint32_t)(((u_int32_t)(0x7f000001))
) & 0xff0000) >> 8 | ((__uint32_t)(((u_int32_t)(0x7f000001
))) & 0xff000000) >> 24) : __swap32md(((u_int32_t)(
0x7f000001))))
)
728 continue;
729
730 as->as_flags &= ~ASYNC_NO_INET0x00010000;
731 break;
732 case PF_INET624:
733 if (ifa_rtable != rtable)
734 continue;
735
736 sin6p = (struct sockaddr_in6 *)ifa->ifa_addr;
737
738 if (IN6_IS_ADDR_LOOPBACK(&sin6p->sin6_addr)((*(const u_int32_t *)(const void *)(&(&sin6p->sin6_addr
)->__u6_addr.__u6_addr8[0]) == 0) && (*(const u_int32_t
*)(const void *)(&(&sin6p->sin6_addr)->__u6_addr
.__u6_addr8[4]) == 0) && (*(const u_int32_t *)(const void
*)(&(&sin6p->sin6_addr)->__u6_addr.__u6_addr8[
8]) == 0) && (*(const u_int32_t *)(const void *)(&
(&sin6p->sin6_addr)->__u6_addr.__u6_addr8[12]) == (
__uint32_t)(__builtin_constant_p(1) ? (__uint32_t)(((__uint32_t
)(1) & 0xff) << 24 | ((__uint32_t)(1) & 0xff00)
<< 8 | ((__uint32_t)(1) & 0xff0000) >> 8 | (
(__uint32_t)(1) & 0xff000000) >> 24) : __swap32md(1
))))
)
739 continue;
740
741 if (IN6_IS_ADDR_LINKLOCAL(&sin6p->sin6_addr)(((&sin6p->sin6_addr)->__u6_addr.__u6_addr8[0] == 0xfe
) && (((&sin6p->sin6_addr)->__u6_addr.__u6_addr8
[1] & 0xc0) == 0x80))
)
742 continue;
743
744 as->as_flags &= ~ASYNC_NO_INET60x00020000;
745 break;
746 }
747 }
748
749 freeifaddrs(ifa0);
750
751 return (0);
752}