]> granicus.if.org Git - postgresql/blob - src/port/getaddrinfo.c
Simplify the socket handling code by supplying a replacement getaddrinfo()
[postgresql] / src / port / getaddrinfo.c
1 /* $Header: /cvsroot/pgsql/src/port/getaddrinfo.c,v 1.1 2003/03/29 11:31:52 petere Exp $ */
2
3 #include "c.h"
4 #include "getaddrinfo.h"
5 #include <netdb.h>
6 #include <sys/socket.h>
7 #include <netinet/in.h>
8 #include <arpa/inet.h>
9
10
11 int
12 getaddrinfo(const char *node, const char *service,
13                         const struct addrinfo *hints,
14                         struct addrinfo **res)
15 {
16         struct addrinfo *ai;
17         struct sockaddr_in sin, *psin;
18
19         if (!hints || (hints->ai_family != AF_INET && hints->ai_family != AF_UNSPEC))
20                 return EAI_FAMILY;
21
22         if (hints->ai_socktype != SOCK_STREAM)
23                 return EAI_SOCKTYPE;
24
25         if (!node && !service)
26                 return EAI_NONAME;
27
28         if (node)
29         {
30                 if (node[0] == '\0')
31                         sin.sin_addr.s_addr = htonl(INADDR_ANY);
32                 else if (hints->ai_flags & AI_NUMERICHOST)
33                 {
34                         inet_aton(node, &sin.sin_addr);
35                 }
36                 else
37                 {
38                         struct hostent *hp;
39
40                         hp = gethostbyname(node);
41                         if (hp == NULL)
42                         {
43                                 switch (h_errno)
44                                 {
45                                         case HOST_NOT_FOUND:
46                                                 return EAI_NONAME;
47                                         case NO_DATA:
48                                                 return EAI_NODATA;
49                                         case TRY_AGAIN:
50                                                 return EAI_AGAIN;
51                                         case NO_RECOVERY:
52                                         default:
53                                                 return EAI_FAIL;
54                                 }
55                         }
56                         if (hp->h_addrtype != AF_INET)
57                                 return EAI_ADDRFAMILY;
58
59                         memmove(&(sin.sin_addr), hp->h_addr, hp->h_length);
60                 }
61         }
62         else
63         {
64                 if (hints->ai_flags & AI_PASSIVE)
65                         sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
66         }
67
68         if (service)
69                 sin.sin_port = htons((unsigned short)atoi(service));
70
71         ai = malloc(sizeof(*ai));
72         if (!ai)
73                 return EAI_MEMORY;
74         psin = malloc(sizeof(*psin));
75         if (!psin)
76         {
77                 free(ai);
78                 return EAI_MEMORY;
79         }
80
81         memcpy(psin, &sin, sizeof(sin));
82
83         ai->ai_family = hints->ai_family;
84         ai->ai_socktype = hints->ai_socktype;
85         ai->ai_protocol = hints->ai_protocol;
86         ai->ai_addrlen = sizeof(*psin);
87         ai->ai_addr = (struct sockaddr *) psin;
88         ai->ai_canonname = NULL;
89         ai->ai_next = NULL;
90
91         *res = ai;
92
93         return 0;
94 }
95
96
97 void
98 freeaddrinfo(struct addrinfo *res)
99 {
100         if (res)
101         {
102                 if (res->ai_addr)
103                         free(res->ai_addr);
104                 free(res);
105         }
106 }
107
108
109 const char*
110 gai_strerror(int errcode)
111 {
112         int hcode;
113
114         switch (errcode)
115         {
116                 case EAI_NONAME:
117                         hcode = HOST_NOT_FOUND;
118                         break;
119                 case EAI_NODATA:
120                         hcode = NO_DATA;
121                         break;
122                 case EAI_AGAIN:
123                         hcode = TRY_AGAIN;
124                         break;
125                 case EAI_FAIL:
126                 default:
127                         hcode = NO_RECOVERY;
128                         break;
129         }
130
131         return hstrerror(hcode);
132 }