Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/lib/libc/net/gethostnamadr.c
39530 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 1994, Garrett Wollman
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
* 1. Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
*
15
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
16
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
19
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
* SUCH DAMAGE.
26
*/
27
28
#include "namespace.h"
29
#include "reentrant.h"
30
#include <sys/param.h>
31
#include <sys/socket.h>
32
#include <netinet/in.h>
33
#include <arpa/inet.h>
34
#include <netdb.h>
35
#include <stdio.h>
36
#include <ctype.h>
37
#include <errno.h>
38
#include <stdlib.h>
39
#include <string.h>
40
#include <stdarg.h>
41
#include <nsswitch.h>
42
#include <arpa/nameser.h> /* XXX hack for _res */
43
#include <resolv.h> /* XXX hack for _res */
44
#include "un-namespace.h"
45
#include "netdb_private.h"
46
#ifdef NS_CACHING
47
#include "nscache.h"
48
#endif
49
50
static int gethostbyname_internal(const char *, int, struct hostent *, char *,
51
size_t, struct hostent **, int *, res_state);
52
53
/* Host lookup order if nsswitch.conf is broken or nonexistent */
54
static const ns_src default_src[] = {
55
{ NSSRC_FILES, NS_SUCCESS },
56
{ NSSRC_DNS, NS_SUCCESS },
57
{ 0 }
58
};
59
#ifdef NS_CACHING
60
static int host_id_func(char *, size_t *, va_list, void *);
61
static int host_marshal_func(char *, size_t *, void *, va_list, void *);
62
static int host_unmarshal_func(char *, size_t, void *, va_list, void *);
63
#endif
64
65
NETDB_THREAD_ALLOC(hostent)
66
NETDB_THREAD_ALLOC(hostent_data)
67
NETDB_THREAD_ALLOC(hostdata)
68
69
static void
70
hostent_free(void *ptr)
71
{
72
free(ptr);
73
}
74
75
static void
76
hostent_data_free(void *ptr)
77
{
78
struct hostent_data *hed = ptr;
79
80
if (hed == NULL)
81
return;
82
hed->stayopen = 0;
83
_endhosthtent(hed);
84
free(hed);
85
}
86
87
static void
88
hostdata_free(void *ptr)
89
{
90
free(ptr);
91
}
92
93
int
94
__copy_hostent(struct hostent *he, struct hostent *hptr, char *buf,
95
size_t buflen)
96
{
97
char *cp;
98
char **ptr;
99
int i, n;
100
int nptr, len;
101
102
/* Find out the amount of space required to store the answer. */
103
nptr = 2; /* NULL ptrs */
104
len = (char *)ALIGN(buf) - buf;
105
for (i = 0; he->h_addr_list[i]; i++, nptr++) {
106
len += he->h_length;
107
}
108
for (i = 0; he->h_aliases[i]; i++, nptr++) {
109
len += strlen(he->h_aliases[i]) + 1;
110
}
111
len += strlen(he->h_name) + 1;
112
len += nptr * sizeof(char*);
113
114
if (len > buflen) {
115
errno = ERANGE;
116
return (-1);
117
}
118
119
/* copy address size and type */
120
hptr->h_addrtype = he->h_addrtype;
121
n = hptr->h_length = he->h_length;
122
123
ptr = (char **)ALIGN(buf);
124
cp = (char *)ALIGN(buf) + nptr * sizeof(char *);
125
126
/* copy address list */
127
hptr->h_addr_list = ptr;
128
for (i = 0; he->h_addr_list[i]; i++ , ptr++) {
129
memcpy(cp, he->h_addr_list[i], n);
130
hptr->h_addr_list[i] = cp;
131
cp += n;
132
}
133
hptr->h_addr_list[i] = NULL;
134
ptr++;
135
136
/* copy official name */
137
n = strlen(he->h_name) + 1;
138
strcpy(cp, he->h_name);
139
hptr->h_name = cp;
140
cp += n;
141
142
/* copy aliases */
143
hptr->h_aliases = ptr;
144
for (i = 0 ; he->h_aliases[i]; i++) {
145
n = strlen(he->h_aliases[i]) + 1;
146
strcpy(cp, he->h_aliases[i]);
147
hptr->h_aliases[i] = cp;
148
cp += n;
149
}
150
hptr->h_aliases[i] = NULL;
151
152
return (0);
153
}
154
155
#ifdef NS_CACHING
156
static int
157
host_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata)
158
{
159
res_state statp;
160
u_long res_options;
161
162
const int op_id = 1;
163
char *str;
164
void *addr;
165
socklen_t len;
166
int type;
167
168
size_t desired_size, size;
169
enum nss_lookup_type lookup_type;
170
char *p;
171
int res = NS_UNAVAIL;
172
173
statp = __res_state();
174
res_options = statp->options & (RES_RECURSE | RES_DEFNAMES |
175
RES_DNSRCH | RES_NOALIASES | RES_USE_INET6);
176
177
lookup_type = (enum nss_lookup_type)(uintptr_t)cache_mdata;
178
switch (lookup_type) {
179
case nss_lt_name:
180
str = va_arg(ap, char *);
181
type = va_arg(ap, int);
182
183
size = strlen(str);
184
desired_size = sizeof(res_options) + sizeof(int) +
185
sizeof(enum nss_lookup_type) + sizeof(int) + size + 1;
186
187
if (desired_size > *buffer_size) {
188
res = NS_RETURN;
189
goto fin;
190
}
191
192
p = buffer;
193
194
memcpy(p, &res_options, sizeof(res_options));
195
p += sizeof(res_options);
196
197
memcpy(p, &op_id, sizeof(int));
198
p += sizeof(int);
199
200
memcpy(p, &lookup_type, sizeof(enum nss_lookup_type));
201
p += sizeof(int);
202
203
memcpy(p, &type, sizeof(int));
204
p += sizeof(int);
205
206
memcpy(p, str, size + 1);
207
208
res = NS_SUCCESS;
209
break;
210
case nss_lt_id:
211
addr = va_arg(ap, void *);
212
len = va_arg(ap, socklen_t);
213
type = va_arg(ap, int);
214
215
desired_size = sizeof(res_options) + sizeof(int) +
216
sizeof(enum nss_lookup_type) + sizeof(int) +
217
sizeof(socklen_t) + len;
218
219
if (desired_size > *buffer_size) {
220
res = NS_RETURN;
221
goto fin;
222
}
223
224
p = buffer;
225
memcpy(p, &res_options, sizeof(res_options));
226
p += sizeof(res_options);
227
228
memcpy(p, &op_id, sizeof(int));
229
p += sizeof(int);
230
231
memcpy(p, &lookup_type, sizeof(enum nss_lookup_type));
232
p += sizeof(int);
233
234
memcpy(p, &type, sizeof(int));
235
p += sizeof(int);
236
237
memcpy(p, &len, sizeof(socklen_t));
238
p += sizeof(socklen_t);
239
240
memcpy(p, addr, len);
241
242
res = NS_SUCCESS;
243
break;
244
default:
245
/* should be unreachable */
246
return (NS_UNAVAIL);
247
}
248
249
fin:
250
*buffer_size = desired_size;
251
return (res);
252
}
253
254
static int
255
host_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap,
256
void *cache_mdata)
257
{
258
char *str __unused;
259
void *addr __unused;
260
socklen_t len __unused;
261
int type __unused;
262
struct hostent *ht;
263
264
struct hostent new_ht;
265
size_t desired_size, aliases_size, addr_size, size;
266
char *p, **iter;
267
268
switch ((enum nss_lookup_type)(uintptr_t)cache_mdata) {
269
case nss_lt_name:
270
str = va_arg(ap, char *);
271
type = va_arg(ap, int);
272
break;
273
case nss_lt_id:
274
addr = va_arg(ap, void *);
275
len = va_arg(ap, socklen_t);
276
type = va_arg(ap, int);
277
break;
278
default:
279
/* should be unreachable */
280
return (NS_UNAVAIL);
281
}
282
ht = va_arg(ap, struct hostent *);
283
284
desired_size = _ALIGNBYTES + sizeof(struct hostent) + sizeof(char *);
285
if (ht->h_name != NULL)
286
desired_size += strlen(ht->h_name) + 1;
287
288
if (ht->h_aliases != NULL) {
289
aliases_size = 0;
290
for (iter = ht->h_aliases; *iter; ++iter) {
291
desired_size += strlen(*iter) + 1;
292
++aliases_size;
293
}
294
295
desired_size += _ALIGNBYTES +
296
(aliases_size + 1) * sizeof(char *);
297
}
298
299
if (ht->h_addr_list != NULL) {
300
addr_size = 0;
301
for (iter = ht->h_addr_list; *iter; ++iter)
302
++addr_size;
303
304
desired_size += addr_size * _ALIGN(ht->h_length);
305
desired_size += _ALIGNBYTES + (addr_size + 1) * sizeof(char *);
306
}
307
308
if (desired_size > *buffer_size) {
309
/* this assignment is here for future use */
310
*buffer_size = desired_size;
311
return (NS_RETURN);
312
}
313
314
memcpy(&new_ht, ht, sizeof(struct hostent));
315
memset(buffer, 0, desired_size);
316
317
*buffer_size = desired_size;
318
p = buffer + sizeof(struct hostent) + sizeof(char *);
319
memcpy(buffer + sizeof(struct hostent), &p, sizeof(char *));
320
p = (char *)_ALIGN(p);
321
322
if (new_ht.h_name != NULL) {
323
size = strlen(new_ht.h_name);
324
memcpy(p, new_ht.h_name, size);
325
new_ht.h_name = p;
326
p += size + 1;
327
}
328
329
if (new_ht.h_aliases != NULL) {
330
p = (char *)_ALIGN(p);
331
memcpy(p, new_ht.h_aliases, sizeof(char *) * aliases_size);
332
new_ht.h_aliases = (char **)p;
333
p += sizeof(char *) * (aliases_size + 1);
334
335
for (iter = new_ht.h_aliases; *iter; ++iter) {
336
size = strlen(*iter);
337
memcpy(p, *iter, size);
338
*iter = p;
339
p += size + 1;
340
}
341
}
342
343
if (new_ht.h_addr_list != NULL) {
344
p = (char *)_ALIGN(p);
345
memcpy(p, new_ht.h_addr_list, sizeof(char *) * addr_size);
346
new_ht.h_addr_list = (char **)p;
347
p += sizeof(char *) * (addr_size + 1);
348
349
size = _ALIGN(new_ht.h_length);
350
for (iter = new_ht.h_addr_list; *iter; ++iter) {
351
memcpy(p, *iter, size);
352
*iter = p;
353
p += size + 1;
354
}
355
}
356
memcpy(buffer, &new_ht, sizeof(struct hostent));
357
return (NS_SUCCESS);
358
}
359
360
static int
361
host_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap,
362
void *cache_mdata)
363
{
364
char *str __unused;
365
void *addr __unused;
366
socklen_t len __unused;
367
int type __unused;
368
struct hostent *ht;
369
370
char *p;
371
char **iter;
372
char *orig_buf;
373
size_t orig_buf_size;
374
375
switch ((enum nss_lookup_type)(uintptr_t)cache_mdata) {
376
case nss_lt_name:
377
str = va_arg(ap, char *);
378
type = va_arg(ap, int);
379
break;
380
case nss_lt_id:
381
addr = va_arg(ap, void *);
382
len = va_arg(ap, socklen_t);
383
type = va_arg(ap, int);
384
break;
385
default:
386
/* should be unreachable */
387
return (NS_UNAVAIL);
388
}
389
390
ht = va_arg(ap, struct hostent *);
391
orig_buf = va_arg(ap, char *);
392
orig_buf_size = va_arg(ap, size_t);
393
394
if (orig_buf_size <
395
buffer_size - sizeof(struct hostent) - sizeof(char *)) {
396
errno = ERANGE;
397
return (NS_RETURN);
398
}
399
400
memcpy(ht, buffer, sizeof(struct hostent));
401
memcpy(&p, buffer + sizeof(struct hostent), sizeof(char *));
402
403
orig_buf = (char *)_ALIGN(orig_buf);
404
memcpy(orig_buf, buffer + sizeof(struct hostent) + sizeof(char *) +
405
_ALIGN(p) - (size_t)p,
406
buffer_size - sizeof(struct hostent) - sizeof(char *) -
407
_ALIGN(p) + (size_t)p);
408
p = (char *)_ALIGN(p);
409
410
NS_APPLY_OFFSET(ht->h_name, orig_buf, p, char *);
411
if (ht->h_aliases != NULL) {
412
NS_APPLY_OFFSET(ht->h_aliases, orig_buf, p, char **);
413
414
for (iter = ht->h_aliases; *iter; ++iter)
415
NS_APPLY_OFFSET(*iter, orig_buf, p, char *);
416
}
417
418
if (ht->h_addr_list != NULL) {
419
NS_APPLY_OFFSET(ht->h_addr_list, orig_buf, p, char **);
420
421
for (iter = ht->h_addr_list; *iter; ++iter)
422
NS_APPLY_OFFSET(*iter, orig_buf, p, char *);
423
}
424
425
*((struct hostent **)retval) = ht;
426
return (NS_SUCCESS);
427
}
428
#endif /* NS_CACHING */
429
430
static int
431
fakeaddr(const char *name, int af, struct hostent *hp, char *buf,
432
size_t buflen, res_state statp)
433
{
434
struct hostent_data *hed;
435
struct hostent he;
436
437
if ((hed = __hostent_data_init()) == NULL) {
438
errno = ENOMEM;
439
RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
440
return (-1);
441
}
442
443
if ((af != AF_INET ||
444
inet_aton(name, (struct in_addr *)hed->host_addr) != 1) &&
445
inet_pton(af, name, hed->host_addr) != 1) {
446
RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
447
return (-1);
448
}
449
strncpy(hed->hostbuf, name, MAXDNAME);
450
hed->hostbuf[MAXDNAME] = '\0';
451
if (af == AF_INET && (statp->options & RES_USE_INET6) != 0U) {
452
_map_v4v6_address((char *)hed->host_addr,
453
(char *)hed->host_addr);
454
af = AF_INET6;
455
}
456
he.h_addrtype = af;
457
switch(af) {
458
case AF_INET:
459
he.h_length = NS_INADDRSZ;
460
break;
461
case AF_INET6:
462
he.h_length = NS_IN6ADDRSZ;
463
break;
464
default:
465
errno = EAFNOSUPPORT;
466
RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
467
return (-1);
468
}
469
he.h_name = hed->hostbuf;
470
he.h_aliases = hed->host_aliases;
471
hed->host_aliases[0] = NULL;
472
hed->h_addr_ptrs[0] = (char *)hed->host_addr;
473
hed->h_addr_ptrs[1] = NULL;
474
he.h_addr_list = hed->h_addr_ptrs;
475
if (__copy_hostent(&he, hp, buf, buflen) != 0) {
476
RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
477
return (-1);
478
}
479
RES_SET_H_ERRNO(statp, NETDB_SUCCESS);
480
return (0);
481
}
482
483
int
484
gethostbyname_r(const char *name, struct hostent *he, char *buffer,
485
size_t buflen, struct hostent **result, int *h_errnop)
486
{
487
res_state statp;
488
489
statp = __res_state();
490
if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) {
491
RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
492
return (-1);
493
}
494
if (statp->options & RES_USE_INET6) {
495
if (fakeaddr(name, AF_INET, he, buffer, buflen, statp) == 0) {
496
*result = he;
497
return (0);
498
}
499
if (gethostbyname_internal(name, AF_INET6, he, buffer, buflen,
500
result, h_errnop, statp) == 0)
501
return (0);
502
}
503
return (gethostbyname_internal(name, AF_INET, he, buffer, buflen,
504
result, h_errnop, statp));
505
}
506
507
int
508
gethostbyname2_r(const char *name, int af, struct hostent *he, char *buffer,
509
size_t buflen, struct hostent **result, int *h_errnop)
510
{
511
res_state statp;
512
513
statp = __res_state();
514
if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) {
515
RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
516
return (-1);
517
}
518
return (gethostbyname_internal(name, af, he, buffer, buflen, result,
519
h_errnop, statp));
520
}
521
522
int
523
gethostbyname_internal(const char *name, int af, struct hostent *hp, char *buf,
524
size_t buflen, struct hostent **result, int *h_errnop, res_state statp)
525
{
526
const char *cp;
527
int rval, ret_errno = 0;
528
char abuf[MAXDNAME];
529
530
#ifdef NS_CACHING
531
static const nss_cache_info cache_info =
532
NS_COMMON_CACHE_INFO_INITIALIZER(
533
hosts, (void *)nss_lt_name,
534
host_id_func, host_marshal_func, host_unmarshal_func);
535
#endif
536
static const ns_dtab dtab[] = {
537
NS_FILES_CB(_ht_gethostbyname, NULL)
538
{ NSSRC_DNS, _dns_gethostbyname, NULL },
539
NS_NIS_CB(_nis_gethostbyname, NULL) /* force -DHESIOD */
540
#ifdef NS_CACHING
541
NS_CACHE_CB(&cache_info)
542
#endif
543
{ 0 }
544
};
545
546
switch (af) {
547
case AF_INET:
548
case AF_INET6:
549
break;
550
default:
551
RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
552
*h_errnop = statp->res_h_errno;
553
errno = EAFNOSUPPORT;
554
return (-1);
555
}
556
557
/*
558
* if there aren't any dots, it could be a user-level alias.
559
* this is also done in res_query() since we are not the only
560
* function that looks up host names.
561
*/
562
if (!strchr(name, '.') &&
563
(cp = res_hostalias(statp, name, abuf, sizeof abuf)))
564
name = cp;
565
566
if (fakeaddr(name, af, hp, buf, buflen, statp) == 0) {
567
*result = hp;
568
return (0);
569
}
570
571
rval = _nsdispatch((void *)result, dtab, NSDB_HOSTS,
572
"gethostbyname2_r", default_src, name, af, hp, buf, buflen,
573
&ret_errno, h_errnop);
574
575
if (rval != NS_SUCCESS) {
576
errno = ret_errno;
577
return ((ret_errno != 0) ? ret_errno : -1);
578
}
579
return (0);
580
}
581
582
int
583
gethostbyaddr_r(const void *addr, socklen_t len, int af, struct hostent *hp,
584
char *buf, size_t buflen, struct hostent **result, int *h_errnop)
585
{
586
const u_char *uaddr = (const u_char *)addr;
587
const struct in6_addr *addr6;
588
socklen_t size;
589
int rval, ret_errno = 0;
590
res_state statp;
591
592
#ifdef NS_CACHING
593
static const nss_cache_info cache_info =
594
NS_COMMON_CACHE_INFO_INITIALIZER(
595
hosts, (void *)nss_lt_id,
596
host_id_func, host_marshal_func, host_unmarshal_func);
597
#endif
598
static const ns_dtab dtab[] = {
599
NS_FILES_CB(_ht_gethostbyaddr, NULL)
600
{ NSSRC_DNS, _dns_gethostbyaddr, NULL },
601
NS_NIS_CB(_nis_gethostbyaddr, NULL) /* force -DHESIOD */
602
#ifdef NS_CACHING
603
NS_CACHE_CB(&cache_info)
604
#endif
605
{ 0 }
606
};
607
608
statp = __res_state();
609
if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) {
610
RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
611
*h_errnop = statp->res_h_errno;
612
return (-1);
613
}
614
615
if (af == AF_INET6 && len == NS_IN6ADDRSZ) {
616
addr6 = (const struct in6_addr *)addr;
617
if (IN6_IS_ADDR_LINKLOCAL(addr6)) {
618
RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
619
*h_errnop = statp->res_h_errno;
620
return (-1);
621
}
622
if (IN6_IS_ADDR_V4MAPPED(addr6) ||
623
IN6_IS_ADDR_V4COMPAT(addr6)) {
624
/* Unmap. */
625
uaddr += NS_IN6ADDRSZ - NS_INADDRSZ;
626
af = AF_INET;
627
len = NS_INADDRSZ;
628
}
629
}
630
switch (af) {
631
case AF_INET:
632
size = NS_INADDRSZ;
633
break;
634
case AF_INET6:
635
size = NS_IN6ADDRSZ;
636
break;
637
default:
638
errno = EAFNOSUPPORT;
639
RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
640
*h_errnop = statp->res_h_errno;
641
return (-1);
642
}
643
if (size != len) {
644
errno = EINVAL;
645
RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
646
*h_errnop = statp->res_h_errno;
647
return (-1);
648
}
649
650
rval = _nsdispatch((void *)result, dtab, NSDB_HOSTS,
651
"gethostbyaddr_r", default_src, uaddr, len, af, hp, buf, buflen,
652
&ret_errno, h_errnop);
653
654
if (rval != NS_SUCCESS) {
655
errno = ret_errno;
656
return ((ret_errno != 0) ? ret_errno : -1);
657
}
658
return (0);
659
}
660
661
struct hostent *
662
gethostbyname(const char *name)
663
{
664
struct hostdata *hd;
665
struct hostent *rval;
666
int ret_h_errno;
667
668
if ((hd = __hostdata_init()) == NULL)
669
return (NULL);
670
if (gethostbyname_r(name, &hd->host, hd->data, sizeof(hd->data), &rval,
671
&ret_h_errno) != 0)
672
return (NULL);
673
return (rval);
674
}
675
676
struct hostent *
677
gethostbyname2(const char *name, int af)
678
{
679
struct hostdata *hd;
680
struct hostent *rval;
681
int ret_h_errno;
682
683
if ((hd = __hostdata_init()) == NULL)
684
return (NULL);
685
if (gethostbyname2_r(name, af, &hd->host, hd->data, sizeof(hd->data),
686
&rval, &ret_h_errno) != 0)
687
return (NULL);
688
return (rval);
689
}
690
691
struct hostent *
692
gethostbyaddr(const void *addr, socklen_t len, int af)
693
{
694
struct hostdata *hd;
695
struct hostent *rval;
696
int ret_h_errno;
697
698
if ((hd = __hostdata_init()) == NULL)
699
return (NULL);
700
if (gethostbyaddr_r(addr, len, af, &hd->host, hd->data,
701
sizeof(hd->data), &rval, &ret_h_errno) != 0)
702
return (NULL);
703
return (rval);
704
}
705
706
void
707
sethostent(int stayopen)
708
{
709
struct hostent_data *hed;
710
711
if ((hed = __hostent_data_init()) == NULL)
712
return;
713
_sethosthtent(stayopen, hed);
714
_sethostdnsent(stayopen);
715
}
716
717
void
718
endhostent(void)
719
{
720
struct hostent_data *hed;
721
722
if ((hed = __hostent_data_init()) == NULL)
723
return;
724
_endhosthtent(hed);
725
_endhostdnsent();
726
}
727
728