mirror of
https://kernel.googlesource.com/pub/scm/network/tftp/tftp-hpa
synced 2025-04-26 01:49:52 +03:00

Add autoconf rules to detect IPv6 availability and some of the neeeded support functions. Add stubs for getaddrinfo and inet_ntop. You can disable IPv6 at compile time with ./configure --without-ipv6 Signed-off-by: Karsten Keil <kkeil@suse.de> Signed-off-by: H. Peter Anvin <hpa@zytor.com>
121 lines
2.7 KiB
C
121 lines
2.7 KiB
C
/*
|
|
* getaddrinfo.c
|
|
*
|
|
* Simple version of getaddrinfo()
|
|
*
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
extern int errno;
|
|
extern int h_errno;
|
|
|
|
void freeaddrinfo(struct addrinfo *res)
|
|
{
|
|
if (!res)
|
|
return;
|
|
if (res->ai_next)
|
|
freeaddrinfo(res->ai_next);
|
|
if (res->ai_addr)
|
|
free(res->ai_addr);
|
|
if (res->ai_canonname)
|
|
free(res->ai_canonname);
|
|
free(res);
|
|
}
|
|
|
|
int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints,
|
|
struct addrinfo **res)
|
|
{
|
|
struct hostent *host;
|
|
struct sockaddr *sa;
|
|
int err, size = 0;
|
|
|
|
if ((!node) || (!res)) {
|
|
errno = EINVAL;
|
|
return EAI_SYSTEM;
|
|
}
|
|
*res = NULL;
|
|
/* we do not support service in this version */
|
|
if (service) {
|
|
errno = EINVAL;
|
|
return EAI_SYSTEM;
|
|
}
|
|
host = gethostbyname(node);
|
|
if (!host)
|
|
return EAI_NONAME;
|
|
if (hints) {
|
|
if (hints->ai_family != AF_UNSPEC) {
|
|
if (hints->ai_family != host->h_addrtype)
|
|
return EAI_ADDRFAMILY;
|
|
}
|
|
}
|
|
*res = malloc(sizeof(struct addrinfo));
|
|
if (!*res) {
|
|
return EAI_MEMORY;
|
|
}
|
|
memset(*res, 0, sizeof(struct addrinfo));
|
|
(*res)->ai_family = host->h_addrtype;
|
|
if (host->h_length) {
|
|
if (host->h_addrtype == AF_INET)
|
|
size = sizeof(struct sockaddr_in);
|
|
#ifdef HAVE_IPV6
|
|
else if (host->h_addrtype == AF_INET6)
|
|
size = sizeof(struct sockaddr_in6);
|
|
#endif
|
|
else {
|
|
free(*res);
|
|
*res = NULL;
|
|
return EAI_ADDRFAMILY;
|
|
}
|
|
sa = malloc(size);
|
|
if (!sa) {
|
|
free(*res);
|
|
*res = NULL;
|
|
return EAI_MEMORY;
|
|
}
|
|
memset(sa, 0, size);
|
|
(*res)->ai_addr = sa;
|
|
(*res)->ai_addrlen = size;
|
|
sa->sa_family = host->h_addrtype;
|
|
if (host->h_addrtype == AF_INET)
|
|
memcpy(&((struct sockaddr_in *)sa)->sin_addr, host->h_addr, host->h_length);
|
|
#ifdef HAVE_IPV6
|
|
else
|
|
memcpy(&((struct sockaddr_in6 *)sa)->sin6_addr, host->h_addr, host->h_length);
|
|
#endif
|
|
}
|
|
if (host->h_name)
|
|
(*res)->ai_canonname = strdup(host->h_name);
|
|
|
|
/* we only handle the first address entry and do not build a list now */
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
const char *gai_strerror(int errcode)
|
|
{
|
|
const char *s = NULL;
|
|
|
|
switch(errcode) {
|
|
case 0:
|
|
s = "no error";
|
|
break;
|
|
case EAI_MEMORY:
|
|
s = "no memory";
|
|
break;
|
|
case EAI_SYSTEM:
|
|
s = strerror(errno);
|
|
break;
|
|
case EAI_NONAME:
|
|
s = hstrerror(h_errno);
|
|
break;
|
|
case EAI_ADDRFAMILY:
|
|
s = "address does not match address family";
|
|
break;
|
|
default:
|
|
s = "unknown error code";
|
|
break;
|
|
}
|
|
return s;
|
|
}
|