/* Get address information (partial implementation).
- Copyright (C) 1997, 2001, 2002, 2004, 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1997, 2001, 2002, 2004, 2005, 2006, 2007 Free Software
+ Foundation, Inc.
Contributed by Simon Josefsson <simon@josefsson.org>.
This program is free software; you can redistribute it and/or modify
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
+#include <config.h>
#include "getaddrinfo.h"
/* Get calloc. */
#include <stdlib.h>
-/* Get memcpy. */
+/* Get memcpy, strdup. */
#include <string.h>
#include <stdbool.h>
#define _(String) gettext (String)
#define N_(String) String
-#include "strdup.h"
+#include "inet_ntop.h"
+#include "snprintf.h"
+
+/* BeOS has AF_INET, but not PF_INET. */
+#ifndef PF_INET
+# define PF_INET AF_INET
+#endif
+/* BeOS also lacks PF_UNSPEC. */
+#ifndef PF_UNSPEC
+# define PF_UNSPEC 0
+#endif
#if defined _WIN32 || defined __WIN32__
# define WIN32_NATIVE
#endif
#ifdef WIN32_NATIVE
-typedef int WSAAPI (*getaddrinfo_func) (const char*, const char*,
+typedef int (WSAAPI *getaddrinfo_func) (const char*, const char*,
const struct addrinfo*,
struct addrinfo**);
-typedef void WSAAPI (*freeaddrinfo_func) (struct addrinfo*);
-typedef int WSAAPI (*getnameinfo_func) (const struct sockaddr*,
+typedef void (WSAAPI *freeaddrinfo_func) (struct addrinfo*);
+typedef int (WSAAPI *getnameinfo_func) (const struct sockaddr*,
socklen_t, char*, DWORD,
char*, DWORD, int);
if (h)
{
- getaddrinfo_ptr = GetProcAddress (h, "getaddrinfo");
- freeaddrinfo_ptr = GetProcAddress (h, "freeaddrinfo");
- getnameinfo_ptr = GetProcAddress (h, "getnameinfo");
+ getaddrinfo_ptr = (getaddrinfo_func) GetProcAddress (h, "getaddrinfo");
+ freeaddrinfo_ptr = (freeaddrinfo_func) GetProcAddress (h, "freeaddrinfo");
+ getnameinfo_ptr = (getnameinfo_func) GetProcAddress (h, "getnameinfo");
}
/* If either is missing, something is odd. */
return getaddrinfo_ptr (nodename, servname, hints, res);
#endif
- if (hints && (hints->ai_flags & ~AI_CANONNAME))
+ if (hints && (hints->ai_flags & ~(AI_CANONNAME|AI_PASSIVE)))
/* FIXME: Support more flags. */
return EAI_BADFLAGS;
return EAI_SOCKTYPE; /* FIXME: Better return code? */
if (!nodename)
- /* FIXME: Support server bind mode. */
- return EAI_NONAME;
+ {
+ if (!(hints->ai_flags & AI_PASSIVE))
+ return EAI_NONAME;
+
+#ifdef HAVE_IPV6
+ nodename = (hints->ai_family == AF_INET6) ? "::" : "0.0.0.0";
+#else
+ nodename = "0.0.0.0";
+#endif
+ }
if (servname)
{
if (!se)
{
char *c;
- if (!(*servname >= '0' && *servname <= '9))
+ if (!(*servname >= '0' && *servname <= '9'))
return EAI_NONAME;
port = strtoul (servname, &c, 10);
if (*c || port > 0xffff)
{
#ifdef WIN32_NATIVE
if (use_win32_p ())
- return freeaddrinfo_ptr (ai);
+ {
+ freeaddrinfo_ptr (ai);
+ return;
+ }
#endif
while (ai)
char *restrict service, socklen_t servicelen,
int flags)
{
-#if WIN32_NATIVE
+#ifdef WIN32_NATIVE
if (use_win32_p ())
return getnameinfo_ptr (sa, salen, node, nodelen,
service, servicelen, flags);
#if HAVE_IPV6
case AF_INET6:
#endif
- if (snprintf (service, servicelen, "%d",
- ntohs (((const struct sockaddr_in *) sa)->sin_port))
- + 1 > servicelen)
- return EAI_OVERFLOW;
+ {
+ unsigned short int port
+ = ntohs (((const struct sockaddr_in *) sa)->sin_port);
+ if (servicelen <= snprintf (service, servicelen, "%u", port))
+ return EAI_OVERFLOW;
+ }
break;
}