/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* - Thread safe-ness must be checked
* - Return values. There seems to be no standard for return value (RFC2553)
* but INRIA implementation returns EAI_xxx defined for getaddrinfo().
+ * - RFC2553 says that we should raise error on short buffer. X/Open says
+ * we need to truncate the result. We obey RFC2553 (and X/Open should be
+ * modified).
*/
#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+#include <config.h>
+#endif
#include <sys/types.h>
#include <sys/socket.h>
#include <resolv.h>
#include <string.h>
#include <stddef.h>
+#include <errno.h>
-#ifndef HAVE_PORTABLE_PROTOTYPE
-#include "cdecl_ext.h"
-#endif
-
-#ifndef HAVE_ADDRINFO
+#ifdef NEED_ADDRINFO_H
#include "addrinfo.h"
#endif
u_short port;
int family, i;
char *addr, *p;
- u_long v4a;
+ uint32_t v4a;
int h_error;
char numserv[512];
char numaddr[512];
if (sa->sa_len != salen)
return ENI_SALEN;
#endif
-
+
family = sa->sa_family;
for (i = 0; afdl[i].a_af; i++)
if (afdl[i].a_af == family) {
goto found;
}
return ENI_FAMILY;
-
+
found:
if (salen != afd->a_socklen)
return ENI_SALEN;
-
+
port = ((struct sockinet *)sa)->si_port; /* network byte order */
addr = (char *)sa + afd->a_off;
if (serv == NULL || servlen == 0) {
- /* what we should do? */
+ /*
+ * do nothing in this case.
+ * in case you are wondering if "&&" is more correct than
+ * "||" here: RFC2553 says that serv == NULL OR servlen == 0
+ * means that the caller does not want the result.
+ */
} else {
if (flags & NI_NUMERICSERV)
sp = NULL;
(flags & NI_DGRAM) ? "udp" : "tcp");
}
if (sp) {
- if (strlen(sp->s_name) > servlen)
+ if (strlen(sp->s_name) + 1 > servlen)
return ENI_MEMORY;
strcpy(serv, sp->s_name);
} else {
snprintf(numserv, sizeof(numserv), "%d", ntohs(port));
- if (strlen(numserv) > servlen)
+ if (strlen(numserv) + 1 > servlen)
return ENI_MEMORY;
strcpy(serv, numserv);
}
switch (sa->sa_family) {
case AF_INET:
- v4a = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr);
+ v4a = (uint32_t)
+ ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr);
if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
flags |= NI_NUMERICHOST;
v4a >>= IN_CLASSA_NSHIFT;
- if (v4a == 0 || v4a == IN_LOOPBACKNET)
- flags |= NI_NUMERICHOST;
+ if (v4a == 0)
+ flags |= NI_NUMERICHOST;
break;
#ifdef INET6
case AF_INET6:
#endif
}
if (host == NULL || hostlen == 0) {
- /* what should we do? */
+ /*
+ * do nothing in this case.
+ * in case you are wondering if "&&" is more correct than
+ * "||" here: RFC2553 says that host == NULL OR hostlen == 0
+ * means that the caller does not want the result.
+ */
} else if (flags & NI_NUMERICHOST) {
/* NUMERICHOST and NAMEREQD conflicts with each other */
if (flags & NI_NAMEREQD)
if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
== NULL)
return ENI_SYSTEM;
- if (strlen(numaddr) > hostlen)
+ if (strlen(numaddr) + 1 > hostlen)
return ENI_MEMORY;
strcpy(host, numaddr);
-#ifdef INET6
+#if defined(INET6) && defined(NI_WITHSCOPEID)
if (afd->a_af == AF_INET6 &&
(IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)addr) ||
IN6_IS_ADDR_MULTICAST((struct in6_addr *)addr)) &&
hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
#else
hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
+#ifdef HAVE_H_ERRNO
h_error = h_errno;
+#else
+ h_error = EINVAL;
+#endif
#endif
if (hp) {
p = strchr(hp->h_name, '.');
if (p) *p = '\0';
}
- if (strlen(hp->h_name) > hostlen) {
+ if (strlen(hp->h_name) + 1 > hostlen) {
#ifdef USE_GETIPNODEBY
freehostent(hp);
#endif
if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
== NULL)
return ENI_NOHOSTNAME;
- if (strlen(numaddr) > hostlen)
+ if (strlen(numaddr) + 1 > hostlen)
return ENI_MEMORY;
strcpy(host, numaddr);
}