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.7 2003/06/12 08:15:29 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))
88 hp = gethostbyname(node);
103 if (hp->h_addrtype != AF_INET)
106 memcpy(&(sin.sin_addr), hp->h_addr, hp->h_length);
111 if (hints.ai_flags & AI_PASSIVE)
112 sin.sin_addr.s_addr = htonl(INADDR_ANY);
114 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
118 sin.sin_port = htons((unsigned short) atoi(service));
120 sin.sin_len = sizeof(sin);
123 ai = malloc(sizeof(*ai));
129 psin = malloc(sizeof(*psin));
136 memcpy(psin, &sin, sizeof(*psin));
139 ai->ai_family = AF_INET;
140 ai->ai_socktype = hints.ai_socktype;
141 ai->ai_protocol = hints.ai_protocol;
142 ai->ai_addrlen = sizeof(*psin);
143 ai->ai_addr = (struct sockaddr *) psin;
144 ai->ai_canonname = NULL;
154 freeaddrinfo(struct addrinfo *res)
166 gai_strerror(int errcode)
168 #ifdef HAVE_HSTRERROR
174 hcode = HOST_NOT_FOUND;
185 return hstrerror(hcode);
187 #else /* !HAVE_HSTRERROR */
192 return "Unknown host";
194 return "Host name lookup failure";
197 return "Unknown server error";
200 #endif /* HAVE_HSTRERROR */
204 * Convert an address to a hostname.
206 * Bugs: - Only supports NI_NUMERICHOST and NI_NUMERICSERV
207 * It will never resolv a hostname.
211 getnameinfo(const struct sockaddr *sa, int salen,
212 char *node, int nodelen,
213 char *service, int servicelen, int flags)
218 /* Invalid arguments. */
219 if (sa == NULL || (node == NULL && service == NULL))
224 /* We don't support those. */
225 if ((node && !(flags & NI_NUMERICHOST))
226 || (service && !(flags & NI_NUMERICSERV)))
231 family = sa->sa_family;
233 if (family == AF_INET6)
241 if (family == AF_INET)
243 ret = snprintf(service, servicelen, "%d",
244 ntohs(((struct sockaddr_in *)sa)->sin_port));
246 #ifdef HAVE_UNIX_SOCKETS
247 else if (family == AF_UNIX)
249 ret = snprintf(service, servicelen, "%s",
250 ((struct sockaddr_un *)sa)->sun_path);
253 if (ret == -1 || ret > servicelen)
261 if (family == AF_INET)
264 p = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr);
265 ret = snprintf(node, nodelen, "%s", p);
267 #ifdef HAVE_UNIX_SOCKETS
268 else if (family == AF_UNIX)
270 ret = snprintf(node, nodelen, "%s", "localhost");
273 if (ret == -1 || ret > nodelen)