10 RCSID(
"$Id: 2022362d3d095e3ca25814906e625cf018fcc5e1 $")
12 #include <freeradius-devel/libradius.h>
15 #include <sys/param.h>
17 #ifndef HAVE_GETNAMEINFO
18 # undef LOCAL_GETHOSTBYNAMERSTYLE
19 # ifndef GETHOSTBYNAMERSTYLE
20 # define LOCAL_GETHOSTBYNAMERSTYLE 1
21 #elif (GETHOSTBYNAMERSTYLE != SYSVSTYLE) && (GETHOSTBYNAMERSTYLE != GNUSTYLE)
22 # define LOCAL_GETHOSTBYNAMERSTYLE 1
26 #ifndef HAVE_GETADDRINFO
27 # undef LOCAL_GETHOSTBYADDRR
28 # ifndef GETHOSTBYADDRRSTYLE
29 # define LOCAL_GETHOSTBYADDRR 1
30 # elif (GETHOSTBYADDRRSTYLE != SYSVSTYLE) && (GETHOSTBYADDRRSTYLE != GNUSTYLE)
31 # define LOCAL_GETHOSTBYADDRR 1
45 # ifdef LOCAL_GETHOSTBYNAMERSTYLE
46 static int fr_hostbyname = 0;
47 static pthread_mutex_t fr_hostbyname_mutex;
50 # ifdef LOCAL_GETHOSTBYNAMERSTYLE
51 static int fr_hostbyaddr = 0;
52 static pthread_mutex_t fr_hostbyaddr_mutex;
76 #if defined(LOCAL_GETHOSTBYNAMER) || defined(LOCAL_GETHOSTBYADDRR)
77 # define BUFFER_OVERFLOW 255
78 static int copy_hostent(
struct hostent *from,
struct hostent *to,
char *buffer,
int buflen,
int *error)
84 to->h_addrtype = from->h_addrtype;
85 to->h_length = from->h_length;
86 to->h_name = (
char *)ptr;
89 len = strlen(from->h_name) + 1;
90 strcpy(ptr, from->h_name);
94 to->h_aliases = (
char**)ptr;
95 for (i = 0; from->h_aliases[i]; i++);
96 ptr += (i+1) *
sizeof(
char *);
98 for (i = 0; from->h_aliases[i]; i++) {
99 len = strlen(from->h_aliases[i])+1;
100 if ((ptr-buffer) + len < buflen) {
101 to->h_aliases[i] = ptr;
102 strcpy(ptr, from->h_aliases[i]);
109 to->h_aliases[i] = NULL;
112 to->h_addr_list = (
char**)ptr;
113 for (i = 0; (
int *)from->h_addr_list[i] != 0; i++);
114 ptr += (i + 1) *
sizeof(
int *);
116 for (i = 0; (
int *)from->h_addr_list[i] != 0; i++) {
119 if ((ptr-buffer)+len < buflen) {
120 to->h_addr_list[i] = ptr;
121 memcpy(ptr, from->h_addr_list[i], len);
128 to->h_addr_list[i] = 0;
133 #ifdef LOCAL_GETHOSTBYNAMERSTYLE
134 static struct hostent *
136 char *buffer,
int buflen,
int *error)
140 # ifdef HAVE_PTHREAD_H
141 if (fr_hostbyname == 0) {
148 hp = gethostbyname(hostname);
149 if ((!hp) || (hp->h_addrtype != AF_INET) || (hp->h_length != 4)) {
157 # ifdef HAVE_PTHREAD_H
166 #ifdef LOCAL_GETHOSTBYADDRR
167 static struct hostent *
gethostbyaddr_r(
char const *addr,
int len,
int type,
struct hostent *result,
168 char *buffer,
int buflen,
int *error)
172 #ifdef HAVE_PTHREAD_H
173 if (fr_hostbyaddr == 0) {
180 hp = gethostbyaddr(addr, len, type);
181 if ((!hp) || (hp->h_addrtype != AF_INET) || (hp->h_length != 4)) {
189 #ifdef HAVE_PTHREAD_H
204 #ifndef HAVE_GETADDRINFO
205 static struct addrinfo *
malloc_ai(uint16_t port, u_long addr,
int socktype,
int proto)
209 ai = (
struct addrinfo *)malloc(
sizeof(
struct addrinfo) +
sizeof(
struct sockaddr_in));
210 if (!ai)
return NULL;
212 memset(ai, 0,
sizeof(
struct addrinfo) +
sizeof(
struct sockaddr_in));
213 ai->ai_addr = (
struct sockaddr *)(ai + 1);
214 ai->ai_addrlen =
sizeof(
struct sockaddr_in);
215 # ifdef HAVE_SOCKADDR_SA_LEN
216 ai->ai_addr->sa_len =
sizeof(
struct sockaddr_in);
218 ai->ai_addr->sa_family = ai->ai_family = AF_INET;
219 ((
struct sockaddr_in *)(ai)->ai_addr)->sin_port = port;
220 ((
struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr;
221 ai->ai_socktype = socktype;
222 ai->ai_protocol = proto;
231 return "memory allocation failure";
234 return "ai_family not supported";
237 return "hostname nor servname provided, or not known";
240 return "servname not supported for ai_socktype";
243 return "unknown error";
249 struct addrinfo *next;
251 if (ai->ai_canonname) free(ai->ai_canonname);
256 }
while ((ai = next) != NULL);
259 int getaddrinfo(
char const *
hostname,
char const *servname,
struct addrinfo
const *hints,
struct addrinfo **res)
261 struct addrinfo *cur, *prev = NULL;
263 struct hostent result;
265 int i, socktype,
proto;
270 if (hints && (hints->ai_family != PF_INET) && (hints->ai_family != PF_UNSPEC))
return EAI_FAMILY;
272 socktype = (hints && hints->ai_socktype) ? hints->ai_socktype : SOCK_STREAM;
273 if (hints && hints->ai_protocol) {
274 proto = hints->ai_protocol;
290 if (isdigit((
int)*servname)) {
291 port = htons(atoi(servname));
294 char const *pe_proto;
309 if ((se = getservbyname(servname, pe_proto)) == NULL)
return EAI_SERVICE;
316 if (hints && hints->ai_flags & AI_PASSIVE) {
317 *res =
malloc_ai(port, htonl(0x00000000), socktype, proto);
319 *res =
malloc_ai(port, htonl(0x7f000001), socktype, proto);
321 if (!*res)
return EAI_MEMORY;
328 *res =
malloc_ai(port, in.s_addr, socktype, proto);
329 if (!*res)
return EAI_MEMORY;
334 if (hints && hints->ai_flags & AI_NUMERICHOST)
return EAI_NONAME;
337 #ifdef GETHOSTBYNAMERSTYLE
338 # if GETHOSTBYNAMERSTYLE == SYSVSTYLE
339 hp =
gethostbyname_r(hostname, &result, buffer,
sizeof(buffer), &error);
340 # elif GETHOSTBYNAMERSTYLE == GNUSTYLE
341 if (
gethostbyname_r(hostname, &result, buffer,
sizeof(buffer), &hp, &error) != 0) hp = NULL;
343 hp =
gethostbyname_r(hostname, &result, buffer,
sizeof(buffer), &error);
346 hp =
gethostbyname_r(hostname, &result, buffer,
sizeof(buffer), &error);
349 if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
350 for (i = 0; hp->h_addr_list[i]; i++) {
351 if ((cur =
malloc_ai(port, ((
struct in_addr *)hp->h_addr_list[i])->s_addr,
352 socktype, proto)) == NULL) {
365 if (hints && hints->ai_flags & AI_CANONNAME && *res) {
366 if (((*res)->ai_canonname = strdup(hp->h_name)) == NULL) {
378 #ifndef HAVE_GETNAMEINFO
379 int getnameinfo(
struct sockaddr
const *sa, socklen_t salen,
char *host,
size_t hostlen,
char *serv,
size_t servlen,
382 const struct sockaddr_in *sin = (
struct sockaddr_in const *)sa;
384 struct hostent result;
390 snprintf(tmpserv,
sizeof(tmpserv),
"%d", ntohs(sin->sin_port));
391 if (strlen(tmpserv) > servlen)
return EAI_MEMORY;
393 strcpy(serv, tmpserv);
396 if (flags & NI_NUMERICHOST) {
398 if (flags & NI_NAMEREQD)
return EAI_NONAME;
399 if (strlen(inet_ntoa(sin->sin_addr)) >= hostlen)
return EAI_MEMORY;
401 strcpy(host, inet_ntoa(sin->sin_addr));
405 #ifdef GETHOSTBYADDRRSTYLE
406 # if GETHOSTBYADDRRSTYLE == SYSVSTYLE
408 salen, AF_INET, &result, buffer,
sizeof(buffer), &error);
409 # elif GETHOSTBYADDRRSTYLE == GNUSTYLE
411 &result, buffer,
sizeof(buffer), &hp, &error) != 0) {
416 &result, buffer,
sizeof(buffer), &error);
420 &result, buffer,
sizeof(buffer), &error);
423 if (strlen(hp->h_name) >= hostlen)
return EAI_MEMORY;
425 strcpy(host, hp->h_name);
429 if (flags & NI_NAMEREQD)
return EAI_NONAME;
430 if (strlen(inet_ntoa(sin->sin_addr)) >= hostlen)
return EAI_MEMORY;
432 strcpy(host, inet_ntoa(sin->sin_addr));
static struct hostent * gethostbyaddr_r(char const *addr, int len, int type, struct hostent *result, char *buffer, int buflen, int *error)
#define pthread_mutex_init(_x, _y)
char const * gai_strerror(int ecode)
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
static char const * hostname(char *buf, size_t buflen, uint32_t ipaddr)
static int copy_hostent(struct hostent *from, struct hostent *to, char *buffer, int buflen, int *error)
static char const * proto
int inet_aton(char const *cp, struct in_addr *inp)
#define pthread_mutex_unlock(_x)
void freeaddrinfo(struct addrinfo *ai)
static struct addrinfo * malloc_ai(uint16_t port, u_long addr, int socktype, int proto)
int getnameinfo(struct sockaddr const *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, unsigned int flags)
static struct hostent * gethostbyname_r(char const *hostname, struct hostent *result, char *buffer, int buflen, int *error)
#define pthread_mutex_lock(_x)
int getaddrinfo(char const *hostname, char const *servname, struct addrinfo const *hints, struct addrinfo **res)