Bug Summary

File:src/lib/libc/asr/gethostnamadr_async.c
Warning:line 324, column 8
Although the value stored to 'r' is used in the enclosing expression, the value is never actually read from 'r'

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 gethostnamadr_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/gethostnamadr_async.c
1/* $OpenBSD: gethostnamadr_async.c,v 1.49 2023/11/22 13:19:31 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 <netinet/in.h>
21#include <arpa/inet.h>
22#include <arpa/nameser.h>
23#include <netdb.h>
24
25#include <asr.h>
26#include <ctype.h>
27#include <errno(*__errno()).h>
28#include <resolv.h> /* for res_hnok */
29#include <stdlib.h>
30#include <string.h>
31#include <unistd.h>
32#include <limits.h>
33
34#include "asr_private.h"
35
36#define MAXALIASES35 35
37#define MAXADDRS35 35
38
39struct hostent_ext {
40 struct hostent h;
41 char *aliases[MAXALIASES35 + 1];
42 char *addrs[MAXADDRS35 + 1];
43 char *end;
44 char *pos;
45};
46
47struct netent_ext {
48 struct netent n;
49 char *aliases[MAXALIASES35 + 1];
50 char *end;
51 char *pos;
52};
53
54static int gethostnamadr_async_run(struct asr_query *, struct asr_result *);
55static struct hostent_ext *hostent_alloc(int);
56static int hostent_set_cname(struct hostent_ext *, const char *, int);
57static int hostent_add_alias(struct hostent_ext *, const char *, int);
58static int hostent_add_addr(struct hostent_ext *, const void *, size_t);
59static struct hostent_ext *hostent_from_addr(int, const char *, const char *);
60static struct hostent_ext *hostent_file_match(FILE *, int, int, const char *,
61 int);
62static struct hostent_ext *hostent_from_packet(int, int, char *, size_t);
63static void netent_from_hostent(struct asr_result *ar);
64
65struct asr_query *
66gethostbyname_async(const char *name, void *asr)
67{
68 return gethostbyname2_async(name, AF_INET2, asr);
69}
70DEF_WEAK(gethostbyname_async)__asm__(".weak " "gethostbyname_async" " ; " "gethostbyname_async"
" = " "_libc_gethostbyname_async")
;
71
72struct asr_query *
73gethostbyname2_async(const char *name, int af, void *asr)
74{
75 struct asr_ctx *ac;
76 struct asr_query *as;
77
78 /* the original segfaults */
79 if (name == NULL((void *)0)) {
80 errno(*__errno()) = EINVAL22;
81 return (NULL((void *)0));
82 }
83
84 ac = _asr_use_resolver(asr);
85 if ((as = _asr_async_new(ac, ASR_GETHOSTBYNAME)) == NULL((void *)0))
86 goto abort; /* errno set */
87 as->as_run = gethostnamadr_async_run;
88
89 as->as.hostnamadr.family = af;
90 if (af == AF_INET2)
91 as->as.hostnamadr.addrlen = INADDRSZ4;
92 else if (af == AF_INET624)
93 as->as.hostnamadr.addrlen = IN6ADDRSZ16;
94 as->as.hostnamadr.name = strdup(name);
95 if (as->as.hostnamadr.name == NULL((void *)0))
96 goto abort; /* errno set */
97
98 _asr_ctx_unref(ac);
99 return (as);
100
101 abort:
102 if (as)
103 _asr_async_free(as);
104 _asr_ctx_unref(ac);
105 return (NULL((void *)0));
106}
107DEF_WEAK(gethostbyname2_async)__asm__(".weak " "gethostbyname2_async" " ; " "gethostbyname2_async"
" = " "_libc_gethostbyname2_async")
;
108
109struct asr_query *
110gethostbyaddr_async(const void *addr, socklen_t len, int af, void *asr)
111{
112 struct asr_ctx *ac;
113 struct asr_query *as;
114
115 ac = _asr_use_resolver(asr);
116 as = _gethostbyaddr_async_ctx(addr, len, af, ac);
117 _asr_ctx_unref(ac);
118
119 return (as);
120}
121DEF_WEAK(gethostbyaddr_async)__asm__(".weak " "gethostbyaddr_async" " ; " "gethostbyaddr_async"
" = " "_libc_gethostbyaddr_async")
;
122
123struct asr_query *
124_gethostbyaddr_async_ctx(const void *addr, socklen_t len, int af,
125 struct asr_ctx *ac)
126{
127 struct asr_query *as;
128
129 if ((as = _asr_async_new(ac, ASR_GETHOSTBYADDR)) == NULL((void *)0))
130 goto abort; /* errno set */
131 as->as_run = gethostnamadr_async_run;
132
133 as->as.hostnamadr.family = af;
134 as->as.hostnamadr.addrlen = len;
135 if (len > 0)
136 memmove(as->as.hostnamadr.addr, addr, (len > 16) ? 16 : len);
137
138 return (as);
139
140 abort:
141 if (as)
142 _asr_async_free(as);
143 return (NULL((void *)0));
144}
145
146static int
147gethostnamadr_async_run(struct asr_query *as, struct asr_result *ar)
148{
149 struct hostent_ext *h;
150 int r, type, saved_errno;
151 FILE *f;
152 char name[MAXDNAME1025], *data, addr[16], *c;
153
154 next:
155 switch (as->as_state) {
156
157 case ASR_STATE_INIT:
158
159 if (as->as.hostnamadr.family != AF_INET2 &&
160 as->as.hostnamadr.family != AF_INET624) {
161 ar->ar_h_errno = NETDB_INTERNAL-1;
162 ar->ar_errno = EAFNOSUPPORT47;
163 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
164 break;
165 }
166
167 if ((as->as.hostnamadr.family == AF_INET2 &&
168 as->as.hostnamadr.addrlen != INADDRSZ4) ||
169 (as->as.hostnamadr.family == AF_INET624 &&
170 as->as.hostnamadr.addrlen != IN6ADDRSZ16)) {
171 ar->ar_h_errno = NETDB_INTERNAL-1;
172 ar->ar_errno = EINVAL22;
173 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
174 break;
175 }
176
177 if (as->as_type == ASR_GETHOSTBYNAME) {
178
179 if (as->as.hostnamadr.name[0] == '\0') {
180 ar->ar_h_errno = NO_DATA4;
181 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
182 break;
183 }
184
185 /* Name might be an IP address string */
186 for (c = as->as.hostnamadr.name; *c; c++)
187 if (!isdigit((unsigned char)*c) &&
188 *c != '.' && *c != ':')
189 break;
190 if (*c == 0 &&
191 inet_pton(as->as.hostnamadr.family,
192 as->as.hostnamadr.name, addr) == 1) {
193 h = hostent_from_addr(as->as.hostnamadr.family,
194 as->as.hostnamadr.name, addr);
195 if (h == NULL((void *)0)) {
196 ar->ar_errno = errno(*__errno());
197 ar->ar_h_errno = NETDB_INTERNAL-1;
198 }
199 else {
200 ar->ar_hostent = &h->h;
201 ar->ar_h_errno = NETDB_SUCCESS0;
202 }
203 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
204 break;
205 }
206
207 if (!hnok_lenient(as->as.hostnamadr.name)) {
208 ar->ar_h_errno = NETDB_INTERNAL-1;
209 ar->ar_errno = EINVAL22;
210 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
211 break;
212 }
213
214 /*
215 * If hostname is "localhost" or falls within the
216 * ".localhost." domain, use local address.
217 * RFC 6761, 6.3:
218 * 3. Name resolution APIs and libraries SHOULD
219 * recognize localhost names as special and SHOULD
220 * always return the IP loopback address for address
221 * queries and negative responses for all other query
222 * types. Name resolution APIs SHOULD NOT send queries
223 * for localhost names to their configured caching DNS
224 * server(s).
225 */
226
227 if (_asr_is_localhost(as->as.hostnamadr.name)) {
228 inet_pton(as->as.hostnamadr.family,
229 as->as.hostnamadr.family == AF_INET2 ?
230 "127.0.0.1" : "::1", addr);
231 h = hostent_from_addr(as->as.hostnamadr.family,
232 as->as.hostnamadr.name, addr);
233 if (h == NULL((void *)0)) {
234 ar->ar_errno = errno(*__errno());
235 ar->ar_h_errno = NETDB_INTERNAL-1;
236 }
237 else {
238 ar->ar_hostent = &h->h;
239 ar->ar_h_errno = NETDB_SUCCESS0;
240 }
241 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
242 break;
243 }
244 }
245 async_set_state(as, ASR_STATE_NEXT_DB)do { ; (as)->as_state = (ASR_STATE_NEXT_DB); } while (0);
246 break;
247
248 case ASR_STATE_NEXT_DB:
249
250 if (_asr_iter_db(as) == -1) {
251 async_set_state(as, ASR_STATE_NOT_FOUND)do { ; (as)->as_state = (ASR_STATE_NOT_FOUND); } while (0);
252 break;
253 }
254
255 switch (AS_DB(as)((as)->as_ctx->ac_db[(as)->as_db_idx - 1])) {
256
257 case ASR_DB_DNS'b':
258
259 /* Create a subquery to do the DNS lookup */
260
261 if (as->as_type == ASR_GETHOSTBYNAME) {
262 type = (as->as.hostnamadr.family == AF_INET2) ?
263 T_A1 : T_AAAA28;
264 as->as_subq = _res_search_async_ctx(
265 as->as.hostnamadr.name,
266 C_IN1, type, as->as_ctx);
267 } else {
268 _asr_addr_as_fqdn(as->as.hostnamadr.addr,
269 as->as.hostnamadr.family,
270 name, sizeof(name));
271 as->as_subq = _res_query_async_ctx(
272 name, C_IN1, T_PTR12, as->as_ctx);
273 }
274
275 if (as->as_subq == NULL((void *)0)) {
276 ar->ar_errno = errno(*__errno());
277 ar->ar_h_errno = NETDB_INTERNAL-1;
278 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
279 break;
280 }
281
282 async_set_state(as, ASR_STATE_SUBQUERY)do { ; (as)->as_state = (ASR_STATE_SUBQUERY); } while (0);
283 break;
284
285 case ASR_DB_FILE'f':
286
287 /* Try to find a match in the host file */
288
289 if ((f = fopen(_PATH_HOSTS"/etc/hosts", "re")) == NULL((void *)0))
290 break;
291
292 if (as->as_type == ASR_GETHOSTBYNAME)
293 data = as->as.hostnamadr.name;
294 else
295 data = as->as.hostnamadr.addr;
296
297 h = hostent_file_match(f, as->as_type,
298 as->as.hostnamadr.family, data,
299 as->as.hostnamadr.addrlen);
300 saved_errno = errno(*__errno());
301 fclose(f);
302 errno(*__errno()) = saved_errno;
303
304 if (h == NULL((void *)0)) {
305 if (errno(*__errno())) {
306 ar->ar_errno = errno(*__errno());
307 ar->ar_h_errno = NETDB_INTERNAL-1;
308 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
309 }
310 /* otherwise not found */
311 break;
312 }
313 ar->ar_hostent = &h->h;
314 ar->ar_h_errno = NETDB_SUCCESS0;
315 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
316 break;
317 }
318 break;
319
320 case ASR_STATE_SUBQUERY:
321
322 /* Run the DNS subquery. */
323
324 if ((r = asr_run(as->as_subq, ar)) == ASYNC_COND0)
Although the value stored to 'r' is used in the enclosing expression, the value is never actually read from 'r'
325 return (ASYNC_COND0);
326
327 /* Done. */
328 as->as_subq = NULL((void *)0);
329
330 /*
331 * We either got no packet or a packet without an answer.
332 * Saveguard the h_errno and use the next DB.
333 */
334 if (ar->ar_count == 0) {
335 free(ar->ar_data);
336 as->as.hostnamadr.subq_h_errno = ar->ar_h_errno;
337 async_set_state(as, ASR_STATE_NEXT_DB)do { ; (as)->as_state = (ASR_STATE_NEXT_DB); } while (0);
338 break;
339 }
340
341 /* Read the hostent from the packet. */
342
343 h = hostent_from_packet(as->as_type,
344 as->as.hostnamadr.family, ar->ar_data, ar->ar_datalen);
345 free(ar->ar_data);
346 if (h == NULL((void *)0)) {
347 ar->ar_errno = errno(*__errno());
348 ar->ar_h_errno = NETDB_INTERNAL-1;
349 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
350 break;
351 }
352
353 if (as->as_type == ASR_GETHOSTBYADDR) {
354 if (hostent_add_addr(h, as->as.hostnamadr.addr,
355 as->as.hostnamadr.addrlen) == -1) {
356 free(h);
357 ar->ar_errno = errno(*__errno());
358 ar->ar_h_errno = NETDB_INTERNAL-1;
359 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
360 break;
361 }
362 }
363
364 /*
365 * No valid hostname or address found in the dns packet.
366 * Ignore it.
367 */
368 if ((as->as_type == ASR_GETHOSTBYNAME &&
369 h->h.h_addr_list[0] == NULL((void *)0)) ||
370 h->h.h_name == NULL((void *)0)) {
371 free(h);
372 async_set_state(as, ASR_STATE_NEXT_DB)do { ; (as)->as_state = (ASR_STATE_NEXT_DB); } while (0);
373 break;
374 }
375
376 ar->ar_hostent = &h->h;
377 ar->ar_h_errno = NETDB_SUCCESS0;
378 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
379 break;
380
381 case ASR_STATE_NOT_FOUND:
382 ar->ar_errno = 0;
383 if (as->as.hostnamadr.subq_h_errno)
384 ar->ar_h_errno = as->as.hostnamadr.subq_h_errno;
385 else
386 ar->ar_h_errno = HOST_NOT_FOUND1;
387 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
388 break;
389
390 case ASR_STATE_HALT:
391 if (ar->ar_h_errno == NETDB_SUCCESS0 &&
392 as->as_flags & ASYNC_GETNET0x00001000)
393 netent_from_hostent(ar);
394 if (ar->ar_h_errno) {
395 ar->ar_hostent = NULL((void *)0);
396 ar->ar_netent = NULL((void *)0);
397 } else
398 ar->ar_errno = 0;
399 return (ASYNC_DONE1);
400
401 default:
402 ar->ar_errno = EOPNOTSUPP45;
403 ar->ar_h_errno = NETDB_INTERNAL-1;
404 ar->ar_gai_errno = EAI_SYSTEM-11;
405 async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0);
406 break;
407 }
408 goto next;
409}
410
411/*
412 * Create a hostent from a numeric address string.
413 */
414static struct hostent_ext *
415hostent_from_addr(int family, const char *name, const char *addr)
416{
417 struct hostent_ext *h;
418
419 if ((h = hostent_alloc(family)) == NULL((void *)0))
420 return (NULL((void *)0));
421 if (hostent_set_cname(h, name, 0) == -1)
422 goto fail;
423 if (hostent_add_addr(h, addr, h->h.h_length) == -1)
424 goto fail;
425 return (h);
426fail:
427 free(h);
428 return (NULL((void *)0));
429}
430
431/*
432 * Lookup the first matching entry in the hostfile, either by address or by
433 * name depending on reqtype, and build a hostent from the line.
434 */
435static struct hostent_ext *
436hostent_file_match(FILE *f, int reqtype, int family, const char *data,
437 int datalen)
438{
439 char *tokens[MAXTOKEN10], addr[16], buf[BUFSIZ1024 + 1];
440 struct hostent_ext *h;
441 int n, i;
442
443 for (;;) {
444 n = _asr_parse_namedb_line(f, tokens, MAXTOKEN10, buf, sizeof(buf));
445 if (n == -1) {
446 errno(*__errno()) = 0; /* ignore errors reading the file */
447 return (NULL((void *)0));
448 }
449
450 /* there must be an address and at least one name */
451 if (n < 2)
452 continue;
453
454 if (reqtype == ASR_GETHOSTBYNAME) {
455 for (i = 1; i < n; i++) {
456 if (strcasecmp(data, tokens[i]))
457 continue;
458 if (inet_pton(family, tokens[0], addr) == 1)
459 goto found;
460 }
461 } else {
462 if (inet_pton(family, tokens[0], addr) == 1 &&
463 memcmp(addr, data, datalen) == 0)
464 goto found;
465 }
466 }
467
468found:
469 if ((h = hostent_alloc(family)) == NULL((void *)0))
470 return (NULL((void *)0));
471 if (hostent_set_cname(h, tokens[1], 0) == -1)
472 goto fail;
473 for (i = 2; i < n; i ++)
474 if (hostent_add_alias(h, tokens[i], 0) == -1)
475 goto fail;
476 if (hostent_add_addr(h, addr, h->h.h_length) == -1)
477 goto fail;
478 return (h);
479fail:
480 free(h);
481 return (NULL((void *)0));
482}
483
484/*
485 * Fill the hostent from the given DNS packet.
486 */
487static struct hostent_ext *
488hostent_from_packet(int reqtype, int family, char *pkt, size_t pktlen)
489{
490 struct hostent_ext *h;
491 struct asr_unpack p;
492 struct asr_dns_header hdr;
493 struct asr_dns_query q;
494 struct asr_dns_rr rr;
495 char dname[MAXDNAME1025];
496
497 if ((h = hostent_alloc(family)) == NULL((void *)0))
498 return (NULL((void *)0));
499
500 _asr_unpack_init(&p, pkt, pktlen);
501 _asr_unpack_header(&p, &hdr);
502 for (; hdr.qdcount; hdr.qdcount--)
503 _asr_unpack_query(&p, &q);
504 strlcpy(dname, q.q_dname, sizeof(dname));
505
506 for (; hdr.ancount; hdr.ancount--) {
507 _asr_unpack_rr(&p, &rr);
508 if (rr.rr_class != C_IN1)
509 continue;
510 switch (rr.rr_type) {
511
512 case T_CNAME5:
513 if (reqtype == ASR_GETHOSTBYNAME) {
514 if (hostent_add_alias(h, rr.rr_dname, 1) == -1)
515 goto fail;
516 } else {
517 if (strcasecmp(rr.rr_dname, dname) == 0)
518 strlcpy(dname, rr.rr.cname.cname,
519 sizeof(dname));
520 }
521 break;
522
523 case T_PTR12:
524 if (reqtype != ASR_GETHOSTBYADDR)
525 break;
526 if (strcasecmp(rr.rr_dname, dname) != 0)
527 continue;
528 if (hostent_set_cname(h, rr.rr.ptr.ptrname, 1) == -1)
529 hostent_add_alias(h, rr.rr.ptr.ptrname, 1);
530 break;
531
532 case T_A1:
533 if (reqtype != ASR_GETHOSTBYNAME)
534 break;
535 if (family != AF_INET2)
536 break;
537 if (hostent_set_cname(h, rr.rr_dname, 1) == -1)
538 ;
539 if (hostent_add_addr(h, &rr.rr.in_a.addr, 4) == -1)
540 goto fail;
541 break;
542
543 case T_AAAA28:
544 if (reqtype != ASR_GETHOSTBYNAME)
545 break;
546 if (family != AF_INET624)
547 break;
548 if (hostent_set_cname(h, rr.rr_dname, 1) == -1)
549 ;
550 if (hostent_add_addr(h, &rr.rr.in_aaaa.addr6, 16) == -1)
551 goto fail;
552 break;
553 }
554 }
555
556 return (h);
557fail:
558 free(h);
559 return (NULL((void *)0));
560}
561
562static struct hostent_ext *
563hostent_alloc(int family)
564{
565 struct hostent_ext *h;
566 size_t alloc;
567
568 alloc = sizeof(*h) + 1024;
569 if ((h = calloc(1, alloc)) == NULL((void *)0))
570 return (NULL((void *)0));
571
572 h->h.h_addrtype = family;
573 h->h.h_length = (family == AF_INET2) ? 4 : 16;
574 h->h.h_aliases = h->aliases;
575 h->h.h_addr_list = h->addrs;
576 h->pos = (char *)(h) + sizeof(*h);
577 h->end = h->pos + 1024;
578
579 return (h);
580}
581
582static int
583hostent_set_cname(struct hostent_ext *h, const char *name, int isdname)
584{
585 char buf[MAXDNAME1025];
586 size_t n;
587
588 if (h->h.h_name)
589 return (-1);
590
591 if (isdname) {
592 _asr_strdname(name, buf, sizeof buf);
593 buf[strlen(buf) - 1] = '\0';
594 if (!res_hnok__res_hnok(buf))
595 return (-1);
596 name = buf;
597 }
598
599 n = strlen(name) + 1;
600 if (h->pos + n >= h->end)
601 return (-1);
602
603 h->h.h_name = h->pos;
604 memmove(h->pos, name, n);
605 h->pos += n;
606 return (0);
607}
608
609static int
610hostent_add_alias(struct hostent_ext *h, const char *name, int isdname)
611{
612 char buf[MAXDNAME1025];
613 size_t i, n;
614
615 for (i = 0; i < MAXALIASES35; i++)
616 if (h->aliases[i] == NULL((void *)0))
617 break;
618 if (i == MAXALIASES35)
619 return (0);
620
621 if (isdname) {
622 _asr_strdname(name, buf, sizeof buf);
623 buf[strlen(buf)-1] = '\0';
624 if (!res_hnok__res_hnok(buf))
625 return (-1);
626 name = buf;
627 }
628
629 n = strlen(name) + 1;
630 if (h->pos + n >= h->end)
631 return (0);
632
633 h->aliases[i] = h->pos;
634 memmove(h->pos, name, n);
635 h->pos += n;
636 return (0);
637}
638
639static int
640hostent_add_addr(struct hostent_ext *h, const void *addr, size_t size)
641{
642 int i;
643
644 for (i = 0; i < MAXADDRS35; i++)
645 if (h->addrs[i] == NULL((void *)0))
646 break;
647 if (i == MAXADDRS35)
648 return (0);
649
650 if (h->pos + size >= h->end)
651 return (0);
652
653 h->addrs[i] = h->pos;
654 memmove(h->pos, addr, size);
655 h->pos += size;
656 return (0);
657}
658
659static void
660netent_from_hostent(struct asr_result *ar)
661{
662 struct in_addr *addr;
663 struct netent_ext *n;
664 struct hostent_ext *h;
665 char **na, **ha;
666 size_t sz;
667
668 /* Allocate and initialize the output. */
669 if ((n = calloc(1, sizeof(*n) + 1024)) == NULL((void *)0)) {
670 ar->ar_h_errno = NETDB_INTERNAL-1;
671 ar->ar_errno = errno(*__errno());
672 goto out;
673 }
674 n->pos = (char *)(n) + sizeof(*n);
675 n->end = n->pos + 1024;
676 n->n.n_name = n->pos;
677 n->n.n_aliases = n->aliases;
678
679 /* Copy the fixed-size data. */
680 h = (struct hostent_ext *)ar->ar_hostent;
681 addr = (struct in_addr *)h->h.h_addrh_addr_list[0];
682 n->n.n_net = ntohl(addr->s_addr)(__uint32_t)(__builtin_constant_p(addr->s_addr) ? (__uint32_t
)(((__uint32_t)(addr->s_addr) & 0xff) << 24 | ((
__uint32_t)(addr->s_addr) & 0xff00) << 8 | ((__uint32_t
)(addr->s_addr) & 0xff0000) >> 8 | ((__uint32_t)
(addr->s_addr) & 0xff000000) >> 24) : __swap32md
(addr->s_addr))
;
683 n->n.n_addrtype = h->h.h_addrtype;
684
685 /* Copy the network name. */
686 sz = strlen(h->h.h_name) + 1;
687 memcpy(n->pos, h->h.h_name, sz);
688 n->pos += sz;
689
690 /*
691 * Copy the aliases.
692 * No overflow check is needed because we are merely copying
693 * a part of the data from a structure of the same size.
694 */
695 na = n->aliases;
696 for (ha = h->aliases; *ha != NULL((void *)0); ha++) {
697 sz = strlen(*ha) + 1;
698 memcpy(n->pos, *ha, sz);
699 *na++ = n->pos;
700 n->pos += sz;
701 }
702 *na = NULL((void *)0);
703
704 /* Handle the return values. */
705 ar->ar_netent = &n->n;
706out:
707 free(ar->ar_hostent);
708 ar->ar_hostent = NULL((void *)0);
709}