|
@@ -36,6 +36,11 @@
|
|
|
* partial IPv6 support (i.e. gethostbyname2() and resolve_address2()
|
|
|
* functions added), IPv6 nameservers are also supported.
|
|
|
*
|
|
|
+ * 6-Oct-2001 Jari Korva <jari.korva@iki.fi>
|
|
|
+ * more IPv6 support (IPv6 support for gethostbyaddr();
|
|
|
+ * address family parameter and improved IPv6 support for get_hosts_byname
|
|
|
+ * and read_etc_hosts; getnameinfo() port from glibc; defined
|
|
|
+ * defined ip6addr_any and in6addr_loopback)
|
|
|
*/
|
|
|
|
|
|
#define __FORCE_GLIBC__
|
|
@@ -100,9 +105,9 @@ extern int nameservers;
|
|
|
extern char * nameserver[MAX_SERVERS];
|
|
|
extern int searchdomains;
|
|
|
extern char * searchdomain[MAX_SEARCH];
|
|
|
-extern struct hostent * get_hosts_byname(const char * name);
|
|
|
+extern struct hostent * get_hosts_byname(const char * name, int type);
|
|
|
extern struct hostent * get_hosts_byaddr(const char * addr, int len, int type);
|
|
|
-extern struct hostent * read_etc_hosts(const char * name, int ip);
|
|
|
+extern struct hostent * read_etc_hosts(const char * name, int type, int ip);
|
|
|
extern int resolve_address(const char * address, int nscount,
|
|
|
char ** nsip, struct in_addr * in);
|
|
|
extern int resolve_mailbox(const char * address, int nscount,
|
|
@@ -977,7 +982,7 @@ struct hostent *gethostbyname(const char *name)
|
|
|
if (!name)
|
|
|
return 0;
|
|
|
|
|
|
- if ((hp = get_hosts_byname(name))) /* do /etc/hosts first */
|
|
|
+ if ((hp = get_hosts_byname(name, AF_INET))) /* do /etc/hosts first */
|
|
|
return(hp);
|
|
|
|
|
|
memset(&h, 0, sizeof(h));
|
|
@@ -1037,6 +1042,14 @@ struct hostent *gethostbyname(const char *name)
|
|
|
|
|
|
#ifdef L_gethostbyname2
|
|
|
|
|
|
+#ifdef __UCLIBC_HAS_IPV6__
|
|
|
+/* TBD: Not the right place for defining these, I guess */
|
|
|
+const struct in6_addr in6addr_any =
|
|
|
+ { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } };
|
|
|
+const struct in6_addr in6addr_loopback =
|
|
|
+ { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } };
|
|
|
+#endif /* __UCLIBC_HAS_IPV6__ */
|
|
|
+
|
|
|
struct hostent *gethostbyname2(const char *name, int family)
|
|
|
{
|
|
|
#ifndef __UCLIBC_HAS_IPV6__
|
|
@@ -1063,7 +1076,7 @@ struct hostent *gethostbyname2(const char *name, int family)
|
|
|
if (!name)
|
|
|
return 0;
|
|
|
|
|
|
- if ((hp = get_hosts_byname(name))) /* do /etc/hosts first */
|
|
|
+ if ((hp = get_hosts_byname(name, family))) /* do /etc/hosts first */
|
|
|
return(hp);
|
|
|
|
|
|
memset(&h, 0, sizeof(h));
|
|
@@ -1188,32 +1201,68 @@ struct hostent *gethostbyaddr (const void *addr, socklen_t len, int type)
|
|
|
static char namebuf[256];
|
|
|
static struct in_addr in;
|
|
|
static struct in_addr *addr_list[2];
|
|
|
+#ifdef __UCLIBC_HAS_IPV6__
|
|
|
+ char *qp;
|
|
|
+ static struct in6_addr in6;
|
|
|
+ static struct in6_addr *addr_list6[2];
|
|
|
+#endif /* __UCLIBC_HAS_IPV6__ */
|
|
|
struct hostent *hp;
|
|
|
unsigned char *packet;
|
|
|
struct resolv_answer a;
|
|
|
int i;
|
|
|
int nest = 0;
|
|
|
|
|
|
- if (!addr || (len != sizeof(in)) || (type != AF_INET))
|
|
|
+ if (!addr)
|
|
|
return 0;
|
|
|
+
|
|
|
+ switch (type) {
|
|
|
+ case AF_INET:
|
|
|
+ if (len != sizeof(struct in_addr))
|
|
|
+ return 0;
|
|
|
+ break;
|
|
|
+#ifdef __UCLIBC_HAS_IPV6__
|
|
|
+ case AF_INET6:
|
|
|
+ if (len != sizeof(struct in6_addr))
|
|
|
+ return 0;
|
|
|
+ break;
|
|
|
+#endif /* __UCLIBC_HAS_IPV6__ */
|
|
|
+ default:
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
if ((hp = get_hosts_byaddr(addr, len, type))) /* do /etc/hosts first */
|
|
|
return(hp);
|
|
|
|
|
|
- memcpy(&in.s_addr, addr, len);
|
|
|
-
|
|
|
open_nameservers();
|
|
|
|
|
|
memset(&h, 0, sizeof(h));
|
|
|
|
|
|
- addr_list[0] = ∈
|
|
|
- addr_list[1] = 0;
|
|
|
+ if(type == AF_INET) {
|
|
|
+ memcpy(&in.s_addr, addr, len);
|
|
|
|
|
|
- sprintf(namebuf, "%d.%d.%d.%d.in-addr.arpa",
|
|
|
+ addr_list[0] = ∈
|
|
|
+
|
|
|
+ sprintf(namebuf, "%d.%d.%d.%d.in-addr.arpa",
|
|
|
(in.s_addr >> 24) & 0xff,
|
|
|
(in.s_addr >> 16) & 0xff,
|
|
|
(in.s_addr >> 8) & 0xff,
|
|
|
(in.s_addr >> 0) & 0xff);
|
|
|
+#ifdef __UCLIBC_HAS_IPV6__
|
|
|
+ } else {
|
|
|
+ memcpy(&in6.s6_addr, addr, len);
|
|
|
+
|
|
|
+ addr_list6[0] = &in6;
|
|
|
+ qp = namebuf;
|
|
|
+
|
|
|
+ for (i = len - 1; i >= 0; i--) {
|
|
|
+ qp += sprintf(qp, "%x.%x.", in6.s6_addr[i] & 0xf,
|
|
|
+ (in6.s6_addr[i] >> 4) & 0xf);
|
|
|
+ }
|
|
|
+ strcpy(qp, "ip6.int");
|
|
|
+#endif /* __UCLIBC_HAS_IPV6__ */
|
|
|
+ }
|
|
|
+
|
|
|
+ addr_list[1] = 0;
|
|
|
|
|
|
for (;;) {
|
|
|
|
|
@@ -1240,8 +1289,16 @@ struct hostent *gethostbyaddr (const void *addr, socklen_t len, int type)
|
|
|
free(packet);
|
|
|
|
|
|
h.h_name = namebuf;
|
|
|
- h.h_addrtype = AF_INET;
|
|
|
- h.h_length = sizeof(in);
|
|
|
+ h.h_addrtype = type;
|
|
|
+
|
|
|
+ if(type == AF_INET) {
|
|
|
+ h.h_length = sizeof(in);
|
|
|
+#ifdef __UCLIBC_HAS_IPV6__
|
|
|
+ } else {
|
|
|
+ h.h_length = sizeof(in6);
|
|
|
+#endif /* __UCLIBC_HAS_IPV6__ */
|
|
|
+ }
|
|
|
+
|
|
|
h.h_addr_list = (char **) addr_list;
|
|
|
break;
|
|
|
} else {
|
|
@@ -1257,7 +1314,7 @@ struct hostent *gethostbyaddr (const void *addr, socklen_t len, int type)
|
|
|
|
|
|
#ifdef L_read_etc_hosts
|
|
|
|
|
|
-struct hostent * read_etc_hosts(const char * name, int ip)
|
|
|
+struct hostent * read_etc_hosts(const char * name, int type, int ip)
|
|
|
{
|
|
|
static struct hostent h;
|
|
|
static struct in_addr in;
|
|
@@ -1308,31 +1365,26 @@ struct hostent * read_etc_hosts(const char * name, int ip)
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
-#ifndef __UCLIBC_HAS_IPV6__
|
|
|
- if (inet_aton(alias[0], &in) == 0)
|
|
|
- break; /* bad ip address */
|
|
|
-#else /* __UCLIBC_HAS_IPV6__ */
|
|
|
- if (inet_aton(alias[0], &in) == 0) {
|
|
|
- if (inet_pton(AF_INET6, alias[0], &in6) == 0) {
|
|
|
- addr_list6[0] = &in6;
|
|
|
- addr_list6[1] = 0;
|
|
|
- h.h_name = alias[1];
|
|
|
- h.h_addrtype = AF_INET6;
|
|
|
- h.h_length = sizeof(in6);
|
|
|
- h.h_addr_list = (char**) addr_list6;
|
|
|
- fclose(fp);
|
|
|
- return(&h);
|
|
|
- } else
|
|
|
- break; /* bad ip address */
|
|
|
- }
|
|
|
+ if (type == AF_INET && inet_pton(AF_INET, alias[0], &in) > 0) {
|
|
|
+ addr_list[0] = ∈
|
|
|
+ addr_list[1] = 0;
|
|
|
+ h.h_name = alias[1];
|
|
|
+ h.h_addrtype = AF_INET;
|
|
|
+ h.h_length = sizeof(in);
|
|
|
+ h.h_addr_list = (char**) addr_list;
|
|
|
+#ifdef __UCLIBC_HAS_IPV6__
|
|
|
+ } else if (type == AF_INET6 && inet_pton(AF_INET6, alias[0], &in6) > 0) {
|
|
|
+ addr_list6[0] = &in6;
|
|
|
+ addr_list6[1] = 0;
|
|
|
+ h.h_name = alias[1];
|
|
|
+ h.h_addrtype = AF_INET6;
|
|
|
+ h.h_length = sizeof(in6);
|
|
|
+ h.h_addr_list = (char**) addr_list6;
|
|
|
#endif /* __UCLIBC_HAS_IPV6__ */
|
|
|
-
|
|
|
- addr_list[0] = ∈
|
|
|
- addr_list[1] = 0;
|
|
|
- h.h_name = alias[1];
|
|
|
- h.h_addrtype = AF_INET;
|
|
|
- h.h_length = sizeof(in);
|
|
|
- h.h_addr_list = (char**) addr_list;
|
|
|
+ } else {
|
|
|
+ break; /* bad ip address */
|
|
|
+ }
|
|
|
+
|
|
|
fclose(fp);
|
|
|
return(&h);
|
|
|
}
|
|
@@ -1344,9 +1396,9 @@ struct hostent * read_etc_hosts(const char * name, int ip)
|
|
|
|
|
|
#ifdef L_get_hosts_byname
|
|
|
|
|
|
-struct hostent * get_hosts_byname(const char * name)
|
|
|
+struct hostent * get_hosts_byname(const char * name, int type)
|
|
|
{
|
|
|
- return(read_etc_hosts(name, 0));
|
|
|
+ return(read_etc_hosts(name, type, 0));
|
|
|
}
|
|
|
#endif
|
|
|
|
|
@@ -1355,14 +1407,218 @@ struct hostent * get_hosts_byname(const char * name)
|
|
|
|
|
|
struct hostent * get_hosts_byaddr(const char * addr, int len, int type)
|
|
|
{
|
|
|
- char ipaddr[20];
|
|
|
+#ifndef __UCLIBC_HAS_IPV6__
|
|
|
+ char ipaddr[INET_ADDRSTRLEN];
|
|
|
+#else
|
|
|
+ char ipaddr[INET6_ADDRSTRLEN];
|
|
|
+#endif /* __UCLIBC_HAS_IPV6__ */
|
|
|
|
|
|
- if (type != AF_INET || len != sizeof(struct in_addr))
|
|
|
- return((struct hostent *) NULL);
|
|
|
+ switch (type) {
|
|
|
+ case AF_INET:
|
|
|
+ if (len != sizeof(struct in_addr))
|
|
|
+ return 0;
|
|
|
+ break;
|
|
|
+#ifdef __UCLIBC_HAS_IPV6__
|
|
|
+ case AF_INET6:
|
|
|
+ if (len != sizeof(struct in6_addr))
|
|
|
+ return 0;
|
|
|
+ break;
|
|
|
+#endif /* __UCLIBC_HAS_IPV6__ */
|
|
|
+ default:
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ inet_ntop(type, addr, ipaddr, sizeof(ipaddr));
|
|
|
|
|
|
- strcpy(ipaddr, inet_ntoa(* (struct in_addr *) addr));
|
|
|
- return(read_etc_hosts(ipaddr, 1));
|
|
|
+ return(read_etc_hosts(ipaddr, type, 1));
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
+#ifdef L_getnameinfo
|
|
|
|
|
|
+int getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host,
|
|
|
+ socklen_t hostlen, char *serv, socklen_t servlen,
|
|
|
+ unsigned int flags)
|
|
|
+{
|
|
|
+ int serrno = errno;
|
|
|
+ int ok = 0;
|
|
|
+ struct hostent *h = NULL;
|
|
|
+ char domain[256];
|
|
|
+
|
|
|
+ if (flags & ~(NI_NUMERICHOST|NI_NUMERICSERV|NI_NOFQDN|NI_NAMEREQD|NI_DGRAM))
|
|
|
+ return EAI_BADFLAGS;
|
|
|
+
|
|
|
+ if (sa == NULL || addrlen < sizeof (sa_family_t))
|
|
|
+ return EAI_FAMILY;
|
|
|
+
|
|
|
+ switch (sa->sa_family) {
|
|
|
+ case AF_LOCAL:
|
|
|
+ break;
|
|
|
+ case AF_INET:
|
|
|
+ if (addrlen < sizeof (struct sockaddr_in))
|
|
|
+ return EAI_FAMILY;
|
|
|
+ break;
|
|
|
+#ifdef __UCLIBC_HAS_IPV6__
|
|
|
+ case AF_INET6:
|
|
|
+ if (addrlen < sizeof (struct sockaddr_in6))
|
|
|
+ return EAI_FAMILY;
|
|
|
+ break;
|
|
|
+#endif /* __UCLIBC_HAS_IPV6__ */
|
|
|
+ default:
|
|
|
+ return EAI_FAMILY;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (host != NULL && hostlen > 0)
|
|
|
+ switch (sa->sa_family) {
|
|
|
+ case AF_INET:
|
|
|
+#ifdef __UCLIBC_HAS_IPV6__
|
|
|
+ case AF_INET6:
|
|
|
+#endif /* __UCLIBC_HAS_IPV6__ */
|
|
|
+ if (!(flags & NI_NUMERICHOST)) {
|
|
|
+#ifdef __UCLIBC_HAS_IPV6__
|
|
|
+ if (sa->sa_family == AF_INET6)
|
|
|
+ h = gethostbyaddr ((const void *) &(((const struct sockaddr_in6 *) sa)->sin6_addr),
|
|
|
+ sizeof(struct in6_addr), AF_INET6);
|
|
|
+ else
|
|
|
+#endif /* __UCLIBC_HAS_IPV6__ */
|
|
|
+ h = gethostbyaddr ((const void *) &(((const struct sockaddr_in *)sa)->sin_addr),
|
|
|
+ sizeof(struct in_addr), AF_INET);
|
|
|
+
|
|
|
+ if (h) {
|
|
|
+ char *c;
|
|
|
+ if ((flags & NI_NOFQDN)
|
|
|
+ && (getdomainname (domain, sizeof(domain)) == 0)
|
|
|
+ && (c = strstr (h->h_name, domain))
|
|
|
+ && (c != h->h_name) && (*(--c) == '.')) {
|
|
|
+ strncpy (host, h->h_name,
|
|
|
+ min(hostlen, (size_t) (c - h->h_name)));
|
|
|
+ host[min(hostlen - 1, (size_t) (c - h->h_name))] = '\0';
|
|
|
+ ok = 1;
|
|
|
+ } else {
|
|
|
+ strncpy (host, h->h_name, hostlen);
|
|
|
+ ok = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!ok) {
|
|
|
+ if (flags & NI_NAMEREQD) {
|
|
|
+ errno = serrno;
|
|
|
+ return EAI_NONAME;
|
|
|
+ } else {
|
|
|
+ const char *c;
|
|
|
+#ifdef __UCLIBC_HAS_IPV6__
|
|
|
+ if (sa->sa_family == AF_INET6) {
|
|
|
+ const struct sockaddr_in6 *sin6p;
|
|
|
+ uint32_t scopeid;
|
|
|
+
|
|
|
+ sin6p = (const struct sockaddr_in6 *) sa;
|
|
|
+
|
|
|
+ c = inet_ntop (AF_INET6,
|
|
|
+ (const void *) &sin6p->sin6_addr, host, hostlen);
|
|
|
+#if 0
|
|
|
+/* Does scope id need to be supported? */
|
|
|
+ scopeid = sin6p->sin6_scope_id;
|
|
|
+ if (scopeid != 0) {
|
|
|
+ /* Buffer is >= IFNAMSIZ+1. */
|
|
|
+ char scopebuf[IFNAMSIZ + 1];
|
|
|
+ char *scopeptr;
|
|
|
+ int ni_numericscope = 0;
|
|
|
+ size_t real_hostlen = __strnlen (host, hostlen);
|
|
|
+ size_t scopelen = 0;
|
|
|
+
|
|
|
+ scopebuf[0] = SCOPE_DELIMITER;
|
|
|
+ scopebuf[1] = '\0';
|
|
|
+ scopeptr = &scopebuf[1];
|
|
|
+
|
|
|
+ if (IN6_IS_ADDR_LINKLOCAL (&sin6p->sin6_addr)
|
|
|
+ || IN6_IS_ADDR_MC_LINKLOCAL (&sin6p->sin6_addr)) {
|
|
|
+ if (if_indextoname (scopeid, scopeptr) == NULL)
|
|
|
+ ++ni_numericscope;
|
|
|
+ else
|
|
|
+ scopelen = strlen (scopebuf);
|
|
|
+ } else {
|
|
|
+ ++ni_numericscope;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ni_numericscope)
|
|
|
+ scopelen = 1 + snprintf (scopeptr,
|
|
|
+ (scopebuf
|
|
|
+ + sizeof scopebuf
|
|
|
+ - scopeptr),
|
|
|
+ "%u", scopeid);
|
|
|
+
|
|
|
+ if (real_hostlen + scopelen + 1 > hostlen)
|
|
|
+ return EAI_SYSTEM;
|
|
|
+ memcpy (host + real_hostlen, scopebuf, scopelen + 1);
|
|
|
+ }
|
|
|
+#endif
|
|
|
+ } else
|
|
|
+#endif /* __UCLIBC_HAS_IPV6__ */
|
|
|
+ c = inet_ntop (AF_INET,
|
|
|
+ (const void *) &(((const struct sockaddr_in *) sa)->sin_addr),
|
|
|
+ host, hostlen);
|
|
|
+
|
|
|
+ if (c == NULL) {
|
|
|
+ errno = serrno;
|
|
|
+ return EAI_SYSTEM;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ok = 1;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case AF_LOCAL:
|
|
|
+ if (!(flags & NI_NUMERICHOST)) {
|
|
|
+ struct utsname utsname;
|
|
|
+
|
|
|
+ if (!uname (&utsname)) {
|
|
|
+ strncpy (host, utsname.nodename, hostlen);
|
|
|
+ break;
|
|
|
+ };
|
|
|
+ };
|
|
|
+
|
|
|
+ if (flags & NI_NAMEREQD) {
|
|
|
+ errno = serrno;
|
|
|
+ return EAI_NONAME;
|
|
|
+ }
|
|
|
+
|
|
|
+ strncpy (host, "localhost", hostlen);
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ return EAI_FAMILY;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (serv && (servlen > 0)) {
|
|
|
+ switch (sa->sa_family) {
|
|
|
+ case AF_INET:
|
|
|
+#ifdef __UCLIBC_HAS_IPV6__
|
|
|
+ case AF_INET6:
|
|
|
+#endif /* __UCLIBC_HAS_IPV6__ */
|
|
|
+ if (!(flags & NI_NUMERICSERV)) {
|
|
|
+ struct servent *s;
|
|
|
+ s = getservbyport (((const struct sockaddr_in *) sa)->sin_port,
|
|
|
+ ((flags & NI_DGRAM) ? "udp" : "tcp"));
|
|
|
+ if (s) {
|
|
|
+ strncpy (serv, s->s_name, servlen);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ snprintf (serv, servlen, "%d",
|
|
|
+ ntohs (((const struct sockaddr_in *) sa)->sin_port));
|
|
|
+ break;
|
|
|
+
|
|
|
+ case AF_LOCAL:
|
|
|
+ strncpy (serv, ((const struct sockaddr_un *) sa)->sun_path, servlen);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (host && (hostlen > 0))
|
|
|
+ host[hostlen-1] = 0;
|
|
|
+ if (serv && (servlen > 0))
|
|
|
+ serv[servlen-1] = 0;
|
|
|
+ errno = serrno;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+#endif
|