1 /*-------------------------------------------------------------------------
4 * Support getaddrinfo() on platforms that don't have it.
7 * Copyright (c) 2003, PostgreSQL Global Development Group
11 * $Header: /cvsroot/pgsql/src/port/getaddrinfo.c,v 1.9 2003/06/23 23:52:00 momjian Exp $
13 *-------------------------------------------------------------------------
16 /* This is intended to be used in both frontend and backend, so use c.h */
19 #if !defined(_MSC_VER) && !defined(__BORLANDC__)
20 #include <sys/types.h>
21 #include <sys/socket.h>
23 #include <netinet/in.h>
24 #include <arpa/inet.h>
25 #ifdef HAVE_UNIX_SOCKETS
30 #include "getaddrinfo.h"
33 * get address info for ipv4 sockets.
35 * Bugs: - only one addrinfo is set even though hintp is NULL or
37 * - AI_CANONNAME is not supported.
38 * - servname can only be a number, not text.
41 getaddrinfo(const char *node, const char *service,
42 const struct addrinfo *hintp,
43 struct addrinfo **res)
46 struct sockaddr_in sin, *psin;
47 struct addrinfo hints;
51 memset(&hints, 0, sizeof(hints));
52 hints.ai_family = AF_INET;
53 hints.ai_socktype = SOCK_STREAM;
57 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))
92 pqGethostbyname(node, &hpstr, buf, sizeof(buf),
95 hp = gethostbyname(node);
111 if (hp->h_addrtype != AF_INET)
114 memcpy(&(sin.sin_addr), hp->h_addr, hp->h_length);
119 if (hints.ai_flags & AI_PASSIVE)
120 sin.sin_addr.s_addr = htonl(INADDR_ANY);
122 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
126 sin.sin_port = htons((unsigned short) atoi(service));
128 sin.sin_len = sizeof(sin);
131 ai = malloc(sizeof(*ai));
137 psin = malloc(sizeof(*psin));
144 memcpy(psin, &sin, sizeof(*psin));
147 ai->ai_family = AF_INET;
148 ai->ai_socktype = hints.ai_socktype;
149 ai->ai_protocol = hints.ai_protocol;
150 ai->ai_addrlen = sizeof(*psin);
151 ai->ai_addr = (struct sockaddr *) psin;
152 ai->ai_canonname = NULL;
162 freeaddrinfo(struct addrinfo *res)
174 gai_strerror(int errcode)
176 #ifdef HAVE_HSTRERROR
182 hcode = HOST_NOT_FOUND;
193 return hstrerror(hcode);
195 #else /* !HAVE_HSTRERROR */
200 return "Unknown host";
202 return "Host name lookup failure";
205 return "Unknown server error";
208 #endif /* HAVE_HSTRERROR */
212 * Convert an address to a hostname.
214 * Bugs: - Only supports NI_NUMERICHOST and NI_NUMERICSERV
215 * It will never resolv a hostname.
219 getnameinfo(const struct sockaddr *sa, int salen,
220 char *node, int nodelen,
221 char *service, int servicelen, int flags)
225 /* Invalid arguments. */
226 if (sa == NULL || (node == NULL && service == NULL))
231 /* We don't support those. */
232 if ((node && !(flags & NI_NUMERICHOST))
233 || (service && !(flags & NI_NUMERICSERV)))
239 if (sa->sa_family == AF_INET6)
247 if (sa->sa_family == AF_INET)
249 ret = snprintf(service, servicelen, "%d",
250 ntohs(((struct sockaddr_in *)sa)->sin_port));
252 #ifdef HAVE_UNIX_SOCKETS
253 else if (sa->sa_family == AF_UNIX)
255 ret = snprintf(service, servicelen, "%s",
256 ((struct sockaddr_un *)sa)->sun_path);
259 if (ret == -1 || ret > servicelen)
267 if (sa->sa_family == AF_INET)
270 p = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr);
271 ret = snprintf(node, nodelen, "%s", p);
273 #ifdef HAVE_UNIX_SOCKETS
274 else if (sa->sa_family == AF_UNIX)
276 ret = snprintf(node, nodelen, "%s", "localhost");
279 if (ret == -1 || ret > nodelen)