2 * Asterisk -- A telephony toolkit for Linux.
6 * Copyright (C) 2004, Digium
8 * This program is free software, distributed under the terms of
9 * the GNU General Public License
14 #include <asterisk/lock.h>
15 #include <asterisk/utils.h>
17 #if defined(__FreeBSD__) || defined(__OpenBSD__)
19 /* duh? ERANGE value copied from web... */
23 AST_MUTEX_DEFINE_STATIC(__mutex);
25 int gethostbyname_r (const char *name, struct hostent *ret, char *buf,
26 size_t buflen, struct hostent **result,
31 ast_mutex_lock(&__mutex); /* begin critical area */
34 ph = gethostbyname(name);
35 *h_errnop = h_errno; /* copy h_errno to *h_herrnop */
42 int naddr=0, naliases=0;
43 /* determine if we have enough space in buf */
45 /* count how many addresses */
46 for (p = ph->h_addr_list; *p != 0; p++) {
47 nbytes += ph->h_length; /* addresses */
48 nbytes += sizeof(*p); /* pointers */
51 nbytes += sizeof(*p); /* one more for the terminating NULL */
53 /* count how many aliases, and total length of strings */
54 for (p = ph->h_aliases; *p != 0; p++) {
55 nbytes += (strlen(*p)+1); /* aliases */
56 nbytes += sizeof(*p); /* pointers */
59 nbytes += sizeof(*p); /* one more for the terminating NULL */
61 /* here nbytes is the number of bytes required in buffer */
62 /* as a terminator must be there, the minimum value is ph->h_length */
65 ast_mutex_unlock(&__mutex); /* end critical area */
66 return ERANGE; /* not enough space in buf!! */
69 /* There is enough space. Now we need to do a deep copy! */
70 /* Allocation in buffer:
71 from [0] to [(naddr-1) * sizeof(*p)]:
73 at [naddr * sizeof(*p)]:
75 from [(naddr+1) * sizeof(*p)] to [(naddr+naliases) * sizeof(*p)] :
77 at [(naddr+naliases+1) * sizeof(*p)]:
79 then naddr addresses (fixed length), and naliases aliases (asciiz).
82 *ret = *ph; /* copy whole structure (not its address!) */
85 q = (char **)buf; /* pointer to pointers area (type: char **) */
86 ret->h_addr_list = q; /* update pointer to address list */
87 pbuf = buf + ((naddr+naliases+2)*sizeof(*p)); /* skip that area */
88 for (p = ph->h_addr_list; *p != 0; p++) {
89 memcpy(pbuf, *p, ph->h_length); /* copy address bytes */
90 *q++ = pbuf; /* the pointer is the one inside buf... */
91 pbuf += ph->h_length; /* advance pbuf */
93 *q++ = NULL; /* address list terminator */
96 ret->h_aliases = q; /* update pointer to aliases list */
97 for (p = ph->h_aliases; *p != 0; p++) {
98 strcpy(pbuf, *p); /* copy alias strings */
99 *q++ = pbuf; /* the pointer is the one inside buf... */
100 pbuf += strlen(*p); /* advance pbuf */
101 *pbuf++ = 0; /* string terminator */
103 *q++ = NULL; /* terminator */
105 strcpy(pbuf, ph->h_name); /* copy alias strings */
107 pbuf += strlen(ph->h_name); /* advance pbuf */
108 *pbuf++ = 0; /* string terminator */
110 *result = ret; /* and let *result point to structure */
113 h_errno = hsave; /* restore h_errno */
114 ast_mutex_unlock(&__mutex); /* end critical area */
116 return (*result == NULL); /* return 0 on success, non-zero on error */
122 struct hostent *ast_gethostbyname(const char *host, struct ast_hostent *hp)
127 struct hostent *result = NULL;
128 /* Although it is perfectly legitimate to lookup a pure integer, for
129 the sake of the sanity of people who like to name their peers as
130 integers, we break with tradition and refuse to look up a
140 res = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &result, &herrno);
142 if (res || !result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])