File: | src/lib/libc/asr/gethostnamadr_async.c |
Warning: | line 286, column 8 Although the value stored to 'r' is used in the enclosing expression, the value is never actually read from 'r' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: gethostnamadr_async.c,v 1.45 2019/06/27 05:26:37 martijn 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 | |
39 | struct hostent_ext { |
40 | struct hostent h; |
41 | char *aliases[MAXALIASES35 + 1]; |
42 | char *addrs[MAXADDRS35 + 1]; |
43 | char *end; |
44 | char *pos; |
45 | }; |
46 | |
47 | struct netent_ext { |
48 | struct netent n; |
49 | char *aliases[MAXALIASES35 + 1]; |
50 | char *end; |
51 | char *pos; |
52 | }; |
53 | |
54 | static int gethostnamadr_async_run(struct asr_query *, struct asr_result *); |
55 | static struct hostent_ext *hostent_alloc(int); |
56 | static int hostent_set_cname(struct hostent_ext *, const char *, int); |
57 | static int hostent_add_alias(struct hostent_ext *, const char *, int); |
58 | static int hostent_add_addr(struct hostent_ext *, const void *, size_t); |
59 | static struct hostent_ext *hostent_from_addr(int, const char *, const char *); |
60 | static struct hostent_ext *hostent_file_match(FILE *, int, int, const char *, |
61 | int); |
62 | static struct hostent_ext *hostent_from_packet(int, int, char *, size_t); |
63 | static void netent_from_hostent(struct asr_result *ar); |
64 | |
65 | struct asr_query * |
66 | gethostbyname_async(const char *name, void *asr) |
67 | { |
68 | return gethostbyname2_async(name, AF_INET2, asr); |
69 | } |
70 | DEF_WEAK(gethostbyname_async)__asm__(".weak " "gethostbyname_async" " ; " "gethostbyname_async" " = " "_libc_gethostbyname_async"); |
71 | |
72 | struct asr_query * |
73 | gethostbyname2_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 | } |
107 | DEF_WEAK(gethostbyname2_async)__asm__(".weak " "gethostbyname2_async" " ; " "gethostbyname2_async" " = " "_libc_gethostbyname2_async"); |
108 | |
109 | struct asr_query * |
110 | gethostbyaddr_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 | } |
121 | DEF_WEAK(gethostbyaddr_async)__asm__(".weak " "gethostbyaddr_async" " ; " "gethostbyaddr_async" " = " "_libc_gethostbyaddr_async"); |
122 | |
123 | struct 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 | |
146 | static int |
147 | gethostnamadr_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 | async_set_state(as, ASR_STATE_NEXT_DB)do { ; (as)->as_state = (ASR_STATE_NEXT_DB); } while (0); |
208 | break; |
209 | |
210 | case ASR_STATE_NEXT_DB: |
211 | |
212 | if (_asr_iter_db(as) == -1) { |
213 | async_set_state(as, ASR_STATE_NOT_FOUND)do { ; (as)->as_state = (ASR_STATE_NOT_FOUND); } while (0); |
214 | break; |
215 | } |
216 | |
217 | switch (AS_DB(as)((as)->as_ctx->ac_db[(as)->as_db_idx - 1])) { |
218 | |
219 | case ASR_DB_DNS'b': |
220 | |
221 | /* Create a subquery to do the DNS lookup */ |
222 | |
223 | if (as->as_type == ASR_GETHOSTBYNAME) { |
224 | type = (as->as.hostnamadr.family == AF_INET2) ? |
225 | T_A1 : T_AAAA28; |
226 | as->as_subq = _res_search_async_ctx( |
227 | as->as.hostnamadr.name, |
228 | C_IN1, type, as->as_ctx); |
229 | } else { |
230 | _asr_addr_as_fqdn(as->as.hostnamadr.addr, |
231 | as->as.hostnamadr.family, |
232 | name, sizeof(name)); |
233 | as->as_subq = _res_query_async_ctx( |
234 | name, C_IN1, T_PTR12, as->as_ctx); |
235 | } |
236 | |
237 | if (as->as_subq == NULL((void *)0)) { |
238 | ar->ar_errno = errno(*__errno()); |
239 | ar->ar_h_errno = NETDB_INTERNAL-1; |
240 | async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0); |
241 | break; |
242 | } |
243 | |
244 | async_set_state(as, ASR_STATE_SUBQUERY)do { ; (as)->as_state = (ASR_STATE_SUBQUERY); } while (0); |
245 | break; |
246 | |
247 | case ASR_DB_FILE'f': |
248 | |
249 | /* Try to find a match in the host file */ |
250 | |
251 | if ((f = fopen(_PATH_HOSTS"/etc/hosts", "re")) == NULL((void *)0)) |
252 | break; |
253 | |
254 | if (as->as_type == ASR_GETHOSTBYNAME) |
255 | data = as->as.hostnamadr.name; |
256 | else |
257 | data = as->as.hostnamadr.addr; |
258 | |
259 | h = hostent_file_match(f, as->as_type, |
260 | as->as.hostnamadr.family, data, |
261 | as->as.hostnamadr.addrlen); |
262 | saved_errno = errno(*__errno()); |
263 | fclose(f); |
264 | errno(*__errno()) = saved_errno; |
265 | |
266 | if (h == NULL((void *)0)) { |
267 | if (errno(*__errno())) { |
268 | ar->ar_errno = errno(*__errno()); |
269 | ar->ar_h_errno = NETDB_INTERNAL-1; |
270 | async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0); |
271 | } |
272 | /* otherwise not found */ |
273 | break; |
274 | } |
275 | ar->ar_hostent = &h->h; |
276 | ar->ar_h_errno = NETDB_SUCCESS0; |
277 | async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0); |
278 | break; |
279 | } |
280 | break; |
281 | |
282 | case ASR_STATE_SUBQUERY: |
283 | |
284 | /* Run the DNS subquery. */ |
285 | |
286 | 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' | |
287 | return (ASYNC_COND0); |
288 | |
289 | /* Done. */ |
290 | as->as_subq = NULL((void *)0); |
291 | |
292 | /* |
293 | * We either got no packet or a packet without an answer. |
294 | * Saveguard the h_errno and use the next DB. |
295 | */ |
296 | if (ar->ar_count == 0) { |
297 | free(ar->ar_data); |
298 | as->as.hostnamadr.subq_h_errno = ar->ar_h_errno; |
299 | async_set_state(as, ASR_STATE_NEXT_DB)do { ; (as)->as_state = (ASR_STATE_NEXT_DB); } while (0); |
300 | break; |
301 | } |
302 | |
303 | /* Read the hostent from the packet. */ |
304 | |
305 | h = hostent_from_packet(as->as_type, |
306 | as->as.hostnamadr.family, ar->ar_data, ar->ar_datalen); |
307 | free(ar->ar_data); |
308 | if (h == NULL((void *)0)) { |
309 | ar->ar_errno = errno(*__errno()); |
310 | ar->ar_h_errno = NETDB_INTERNAL-1; |
311 | async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0); |
312 | break; |
313 | } |
314 | |
315 | if (as->as_type == ASR_GETHOSTBYADDR) { |
316 | if (hostent_add_addr(h, as->as.hostnamadr.addr, |
317 | as->as.hostnamadr.addrlen) == -1) { |
318 | free(h); |
319 | ar->ar_errno = errno(*__errno()); |
320 | ar->ar_h_errno = NETDB_INTERNAL-1; |
321 | async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0); |
322 | break; |
323 | } |
324 | } |
325 | |
326 | /* |
327 | * No valid hostname or address found in the dns packet. |
328 | * Ignore it. |
329 | */ |
330 | if ((as->as_type == ASR_GETHOSTBYNAME && |
331 | h->h.h_addr_list[0] == NULL((void *)0)) || |
332 | h->h.h_name == NULL((void *)0)) { |
333 | free(h); |
334 | async_set_state(as, ASR_STATE_NEXT_DB)do { ; (as)->as_state = (ASR_STATE_NEXT_DB); } while (0); |
335 | break; |
336 | } |
337 | |
338 | ar->ar_hostent = &h->h; |
339 | ar->ar_h_errno = NETDB_SUCCESS0; |
340 | async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0); |
341 | break; |
342 | |
343 | case ASR_STATE_NOT_FOUND: |
344 | ar->ar_errno = 0; |
345 | if (as->as.hostnamadr.subq_h_errno) |
346 | ar->ar_h_errno = as->as.hostnamadr.subq_h_errno; |
347 | else |
348 | ar->ar_h_errno = HOST_NOT_FOUND1; |
349 | async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0); |
350 | break; |
351 | |
352 | case ASR_STATE_HALT: |
353 | if (ar->ar_h_errno == NETDB_SUCCESS0 && |
354 | as->as_flags & ASYNC_GETNET0x00001000) |
355 | netent_from_hostent(ar); |
356 | if (ar->ar_h_errno) { |
357 | ar->ar_hostent = NULL((void *)0); |
358 | ar->ar_netent = NULL((void *)0); |
359 | } else |
360 | ar->ar_errno = 0; |
361 | return (ASYNC_DONE1); |
362 | |
363 | default: |
364 | ar->ar_errno = EOPNOTSUPP45; |
365 | ar->ar_h_errno = NETDB_INTERNAL-1; |
366 | ar->ar_gai_errno = EAI_SYSTEM-11; |
367 | async_set_state(as, ASR_STATE_HALT)do { ; (as)->as_state = (ASR_STATE_HALT); } while (0); |
368 | break; |
369 | } |
370 | goto next; |
371 | } |
372 | |
373 | /* |
374 | * Create a hostent from a numeric address string. |
375 | */ |
376 | static struct hostent_ext * |
377 | hostent_from_addr(int family, const char *name, const char *addr) |
378 | { |
379 | struct hostent_ext *h; |
380 | |
381 | if ((h = hostent_alloc(family)) == NULL((void *)0)) |
382 | return (NULL((void *)0)); |
383 | if (hostent_set_cname(h, name, 0) == -1) |
384 | goto fail; |
385 | if (hostent_add_addr(h, addr, h->h.h_length) == -1) |
386 | goto fail; |
387 | return (h); |
388 | fail: |
389 | free(h); |
390 | return (NULL((void *)0)); |
391 | } |
392 | |
393 | /* |
394 | * Lookup the first matching entry in the hostfile, either by address or by |
395 | * name depending on reqtype, and build a hostent from the line. |
396 | */ |
397 | static struct hostent_ext * |
398 | hostent_file_match(FILE *f, int reqtype, int family, const char *data, |
399 | int datalen) |
400 | { |
401 | char *tokens[MAXTOKEN10], addr[16], buf[BUFSIZ1024 + 1]; |
402 | struct hostent_ext *h; |
403 | int n, i; |
404 | |
405 | for (;;) { |
406 | n = _asr_parse_namedb_line(f, tokens, MAXTOKEN10, buf, sizeof(buf)); |
407 | if (n == -1) { |
408 | errno(*__errno()) = 0; /* ignore errors reading the file */ |
409 | return (NULL((void *)0)); |
410 | } |
411 | |
412 | /* there must be an address and at least one name */ |
413 | if (n < 2) |
414 | continue; |
415 | |
416 | if (reqtype == ASR_GETHOSTBYNAME) { |
417 | for (i = 1; i < n; i++) { |
418 | if (strcasecmp(data, tokens[i])) |
419 | continue; |
420 | if (inet_pton(family, tokens[0], addr) == 1) |
421 | goto found; |
422 | } |
423 | } else { |
424 | if (inet_pton(family, tokens[0], addr) == 1 && |
425 | memcmp(addr, data, datalen) == 0) |
426 | goto found; |
427 | } |
428 | } |
429 | |
430 | found: |
431 | if ((h = hostent_alloc(family)) == NULL((void *)0)) |
432 | return (NULL((void *)0)); |
433 | if (hostent_set_cname(h, tokens[1], 0) == -1) |
434 | goto fail; |
435 | for (i = 2; i < n; i ++) |
436 | if (hostent_add_alias(h, tokens[i], 0) == -1) |
437 | goto fail; |
438 | if (hostent_add_addr(h, addr, h->h.h_length) == -1) |
439 | goto fail; |
440 | return (h); |
441 | fail: |
442 | free(h); |
443 | return (NULL((void *)0)); |
444 | } |
445 | |
446 | /* |
447 | * Fill the hostent from the given DNS packet. |
448 | */ |
449 | static struct hostent_ext * |
450 | hostent_from_packet(int reqtype, int family, char *pkt, size_t pktlen) |
451 | { |
452 | struct hostent_ext *h; |
453 | struct asr_unpack p; |
454 | struct asr_dns_header hdr; |
455 | struct asr_dns_query q; |
456 | struct asr_dns_rr rr; |
457 | char dname[MAXDNAME1025]; |
458 | |
459 | if ((h = hostent_alloc(family)) == NULL((void *)0)) |
460 | return (NULL((void *)0)); |
461 | |
462 | _asr_unpack_init(&p, pkt, pktlen); |
463 | _asr_unpack_header(&p, &hdr); |
464 | for (; hdr.qdcount; hdr.qdcount--) |
465 | _asr_unpack_query(&p, &q); |
466 | strlcpy(dname, q.q_dname, sizeof(dname)); |
467 | |
468 | for (; hdr.ancount; hdr.ancount--) { |
469 | _asr_unpack_rr(&p, &rr); |
470 | if (rr.rr_class != C_IN1) |
471 | continue; |
472 | switch (rr.rr_type) { |
473 | |
474 | case T_CNAME5: |
475 | if (reqtype == ASR_GETHOSTBYNAME) { |
476 | if (hostent_add_alias(h, rr.rr_dname, 1) == -1) |
477 | goto fail; |
478 | } else { |
479 | if (strcasecmp(rr.rr_dname, dname) == 0) |
480 | strlcpy(dname, rr.rr.cname.cname, |
481 | sizeof(dname)); |
482 | } |
483 | break; |
484 | |
485 | case T_PTR12: |
486 | if (reqtype != ASR_GETHOSTBYADDR) |
487 | break; |
488 | if (strcasecmp(rr.rr_dname, dname) != 0) |
489 | continue; |
490 | if (hostent_set_cname(h, rr.rr.ptr.ptrname, 1) == -1) |
491 | hostent_add_alias(h, rr.rr.ptr.ptrname, 1); |
492 | break; |
493 | |
494 | case T_A1: |
495 | if (reqtype != ASR_GETHOSTBYNAME) |
496 | break; |
497 | if (family != AF_INET2) |
498 | break; |
499 | if (hostent_set_cname(h, rr.rr_dname, 1) == -1) |
500 | ; |
501 | if (hostent_add_addr(h, &rr.rr.in_a.addr, 4) == -1) |
502 | goto fail; |
503 | break; |
504 | |
505 | case T_AAAA28: |
506 | if (reqtype != ASR_GETHOSTBYNAME) |
507 | break; |
508 | if (family != AF_INET624) |
509 | break; |
510 | if (hostent_set_cname(h, rr.rr_dname, 1) == -1) |
511 | ; |
512 | if (hostent_add_addr(h, &rr.rr.in_aaaa.addr6, 16) == -1) |
513 | goto fail; |
514 | break; |
515 | } |
516 | } |
517 | |
518 | return (h); |
519 | fail: |
520 | free(h); |
521 | return (NULL((void *)0)); |
522 | } |
523 | |
524 | static struct hostent_ext * |
525 | hostent_alloc(int family) |
526 | { |
527 | struct hostent_ext *h; |
528 | size_t alloc; |
529 | |
530 | alloc = sizeof(*h) + 1024; |
531 | if ((h = calloc(1, alloc)) == NULL((void *)0)) |
532 | return (NULL((void *)0)); |
533 | |
534 | h->h.h_addrtype = family; |
535 | h->h.h_length = (family == AF_INET2) ? 4 : 16; |
536 | h->h.h_aliases = h->aliases; |
537 | h->h.h_addr_list = h->addrs; |
538 | h->pos = (char *)(h) + sizeof(*h); |
539 | h->end = h->pos + 1024; |
540 | |
541 | return (h); |
542 | } |
543 | |
544 | static int |
545 | hostent_set_cname(struct hostent_ext *h, const char *name, int isdname) |
546 | { |
547 | char buf[MAXDNAME1025]; |
548 | size_t n; |
549 | |
550 | if (h->h.h_name) |
551 | return (-1); |
552 | |
553 | if (isdname) { |
554 | _asr_strdname(name, buf, sizeof buf); |
555 | buf[strlen(buf) - 1] = '\0'; |
556 | if (!res_hnok__res_hnok(buf)) |
557 | return (-1); |
558 | name = buf; |
559 | } |
560 | |
561 | n = strlen(name) + 1; |
562 | if (h->pos + n >= h->end) |
563 | return (-1); |
564 | |
565 | h->h.h_name = h->pos; |
566 | memmove(h->pos, name, n); |
567 | h->pos += n; |
568 | return (0); |
569 | } |
570 | |
571 | static int |
572 | hostent_add_alias(struct hostent_ext *h, const char *name, int isdname) |
573 | { |
574 | char buf[MAXDNAME1025]; |
575 | size_t i, n; |
576 | |
577 | for (i = 0; i < MAXALIASES35; i++) |
578 | if (h->aliases[i] == NULL((void *)0)) |
579 | break; |
580 | if (i == MAXALIASES35) |
581 | return (0); |
582 | |
583 | if (isdname) { |
584 | _asr_strdname(name, buf, sizeof buf); |
585 | buf[strlen(buf)-1] = '\0'; |
586 | if (!res_hnok__res_hnok(buf)) |
587 | return (-1); |
588 | name = buf; |
589 | } |
590 | |
591 | n = strlen(name) + 1; |
592 | if (h->pos + n >= h->end) |
593 | return (0); |
594 | |
595 | h->aliases[i] = h->pos; |
596 | memmove(h->pos, name, n); |
597 | h->pos += n; |
598 | return (0); |
599 | } |
600 | |
601 | static int |
602 | hostent_add_addr(struct hostent_ext *h, const void *addr, size_t size) |
603 | { |
604 | int i; |
605 | |
606 | for (i = 0; i < MAXADDRS35; i++) |
607 | if (h->addrs[i] == NULL((void *)0)) |
608 | break; |
609 | if (i == MAXADDRS35) |
610 | return (0); |
611 | |
612 | if (h->pos + size >= h->end) |
613 | return (0); |
614 | |
615 | h->addrs[i] = h->pos; |
616 | memmove(h->pos, addr, size); |
617 | h->pos += size; |
618 | return (0); |
619 | } |
620 | |
621 | static void |
622 | netent_from_hostent(struct asr_result *ar) |
623 | { |
624 | struct in_addr *addr; |
625 | struct netent_ext *n; |
626 | struct hostent_ext *h; |
627 | char **na, **ha; |
628 | size_t sz; |
629 | |
630 | /* Allocate and initialize the output. */ |
631 | if ((n = calloc(1, sizeof(*n) + 1024)) == NULL((void *)0)) { |
632 | ar->ar_h_errno = NETDB_INTERNAL-1; |
633 | ar->ar_errno = errno(*__errno()); |
634 | goto out; |
635 | } |
636 | n->pos = (char *)(n) + sizeof(*n); |
637 | n->end = n->pos + 1024; |
638 | n->n.n_name = n->pos; |
639 | n->n.n_aliases = n->aliases; |
640 | |
641 | /* Copy the fixed-size data. */ |
642 | h = (struct hostent_ext *)ar->ar_hostent; |
643 | addr = (struct in_addr *)h->h.h_addrh_addr_list[0]; |
644 | 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)); |
645 | n->n.n_addrtype = h->h.h_addrtype; |
646 | |
647 | /* Copy the network name. */ |
648 | sz = strlen(h->h.h_name) + 1; |
649 | memcpy(n->pos, h->h.h_name, sz); |
650 | n->pos += sz; |
651 | |
652 | /* |
653 | * Copy the aliases. |
654 | * No overflow check is needed because we are merely copying |
655 | * a part of the data from a structure of the same size. |
656 | */ |
657 | na = n->aliases; |
658 | for (ha = h->aliases; *ha != NULL((void *)0); ha++) { |
659 | sz = strlen(*ha) + 1; |
660 | memcpy(n->pos, *ha, sz); |
661 | *na++ = n->pos; |
662 | n->pos += sz; |
663 | } |
664 | *na = NULL((void *)0); |
665 | |
666 | /* Handle the return values. */ |
667 | ar->ar_netent = &n->n; |
668 | out: |
669 | free(ar->ar_hostent); |
670 | ar->ar_hostent = NULL((void *)0); |
671 | } |