1
/*-------------------------------------------------------------------------
4
* Support getaddrinfo() on platforms that don't have it.
6
* We also supply getnameinfo() here, assuming that the platform will have
7
* it if and only if it has getaddrinfo(). If this proves false on some
8
* platform, we'll need to split this file and provide a separate configure
9
* test for getnameinfo().
12
* Copyright (c) 2003-2005, PostgreSQL Global Development Group
15
* $PostgreSQL: pgsql/src/port/getaddrinfo.c,v 1.16 2005-01-01 20:44:33 tgl Exp $
17
*-------------------------------------------------------------------------
20
/* This is intended to be used in both frontend and backend, so use c.h */
23
#ifndef WIN32_CLIENT_ONLY
24
#include <sys/types.h>
25
#include <sys/socket.h>
27
#include <netinet/in.h>
28
#include <arpa/inet.h>
31
#include "getaddrinfo.h"
34
* get address info for ipv4 sockets.
36
* Bugs: - only one addrinfo is set even though hintp is NULL or
38
* - AI_CANONNAME is not supported.
39
* - servname can only be a number, not text.
42
getaddrinfo(const char *node, const char *service,
43
const struct addrinfo * hintp,
44
struct addrinfo ** res)
47
struct sockaddr_in sin,
49
struct addrinfo hints;
53
memset(&hints, 0, sizeof(hints));
54
hints.ai_family = AF_INET;
55
hints.ai_socktype = SOCK_STREAM;
58
memcpy(&hints, hintp, sizeof(hints));
60
if (hints.ai_family != AF_INET && hints.ai_family != AF_UNSPEC)
63
if (hints.ai_socktype == 0)
64
hints.ai_socktype = SOCK_STREAM;
66
if (!node && !service)
69
memset(&sin, 0, sizeof(sin));
71
sin.sin_family = AF_INET;
76
sin.sin_addr.s_addr = htonl(INADDR_ANY);
77
else if (hints.ai_flags & AI_NUMERICHOST)
79
if (!inet_aton(node, &sin.sin_addr))
91
pqGethostbyname(node, &hpstr, buf, sizeof(buf),
94
hp = gethostbyname(node);
110
if (hp->h_addrtype != AF_INET)
113
memcpy(&(sin.sin_addr), hp->h_addr, hp->h_length);
118
if (hints.ai_flags & AI_PASSIVE)
119
sin.sin_addr.s_addr = htonl(INADDR_ANY);
121
sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
125
sin.sin_port = htons((unsigned short) atoi(service));
127
#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
128
sin.sin_len = sizeof(sin);
131
ai = malloc(sizeof(*ai));
135
psin = malloc(sizeof(*psin));
142
memcpy(psin, &sin, sizeof(*psin));
145
ai->ai_family = AF_INET;
146
ai->ai_socktype = hints.ai_socktype;
147
ai->ai_protocol = hints.ai_protocol;
148
ai->ai_addrlen = sizeof(*psin);
149
ai->ai_addr = (struct sockaddr *) psin;
150
ai->ai_canonname = NULL;
160
freeaddrinfo(struct addrinfo * res)
172
gai_strerror(int errcode)
174
#ifdef HAVE_HSTRERROR
180
hcode = HOST_NOT_FOUND;
191
return hstrerror(hcode);
193
#else /* !HAVE_HSTRERROR */
198
return "Unknown host";
200
return "Host name lookup failure";
203
return "Unknown server error";
205
#endif /* HAVE_HSTRERROR */
209
* Convert an ipv4 address to a hostname.
211
* Bugs: - Only supports NI_NUMERICHOST and NI_NUMERICSERV
212
* It will never resolv a hostname.
216
getnameinfo(const struct sockaddr * sa, int salen,
217
char *node, int nodelen,
218
char *service, int servicelen, int flags)
220
/* Invalid arguments. */
221
if (sa == NULL || (node == NULL && service == NULL))
224
/* We don't support those. */
225
if ((node && !(flags & NI_NUMERICHOST))
226
|| (service && !(flags & NI_NUMERICSERV)))
230
if (sa->sa_family == AF_INET6)
238
if (sa->sa_family == AF_INET)
242
p = inet_ntoa(((struct sockaddr_in *) sa)->sin_addr);
243
ret = snprintf(node, nodelen, "%s", p);
245
if (ret == -1 || ret > nodelen)
253
if (sa->sa_family == AF_INET)
255
ret = snprintf(service, servicelen, "%d",
256
ntohs(((struct sockaddr_in *) sa)->sin_port));
258
if (ret == -1 || ret > servicelen)