Fixed passive connect waiting bug
[ntk/apt.git] / methods / rfc2553emu.cc
CommitLineData
934b6582
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
b819effd 3// $Id: rfc2553emu.cc,v 1.6 1999/12/11 02:11:10 jgg Exp $
934b6582
AL
4/* ######################################################################
5
6 RFC 2553 Emulation - Provides emulation for RFC 2553 getaddrinfo,
7 freeaddrinfo and getnameinfo
6d13bbca
AL
8
9 This is really C code, it just has a .cc extensions to play nicer with
10 the rest of APT.
934b6582
AL
11
12 Originally written by Jason Gunthorpe <jgg@debian.org> and placed into
13 the Public Domain, do with it what you will.
6d13bbca 14
934b6582
AL
15 ##################################################################### */
16 /*}}}*/
17#include "rfc2553emu.h"
18#include <stdlib.h>
19#include <arpa/inet.h>
b819effd 20#include <netinet/in.h>
533151d3
AL
21#include <string.h>
22#include <stdio.h>
934b6582
AL
23
24#ifndef HAVE_GETADDRINFO
533151d3
AL
25// getaddrinfo - Resolve a hostname /*{{{*/
26// ---------------------------------------------------------------------
27/* */
934b6582
AL
28int getaddrinfo(const char *nodename, const char *servname,
29 const struct addrinfo *hints,
30 struct addrinfo **res)
31{
d955fe80 32 struct addrinfo **Result = res;
934b6582
AL
33 hostent *Addr;
34 unsigned int Port;
35 int Proto;
36 const char *End;
37 char **CurAddr;
38
39 Addr = gethostbyname(nodename);
40 if (Addr == 0)
41 {
42 if (h_errno == TRY_AGAIN)
43 return EAI_AGAIN;
44 if (h_errno == NO_RECOVERY)
45 return EAI_FAIL;
46 return EAI_NONAME;
47 }
48
49 // No A records
50 if (Addr->h_addr_list[0] == 0)
51 return EAI_NONAME;
52
53 // Try to convert the service as a number
54 Port = htons(strtol(servname,(char **)&End,0));
55 Proto = SOCK_STREAM;
56
57 if (hints != 0 && hints->ai_socktype != 0)
58 Proto = hints->ai_socktype;
59
60 // Not a number, must be a name.
f93d1355 61 if (End != servname + strlen(servname))
934b6582
AL
62 {
63 struct servent *Srv = 0;
64
65 // Do a lookup in the service database
66 if (hints == 0 || hints->ai_socktype == SOCK_STREAM)
67 Srv = getservbyname(servname,"tcp");
68 if (hints != 0 && hints->ai_socktype == SOCK_DGRAM)
69 Srv = getservbyname(servname,"udp");
70 if (Srv == 0)
71 return EAI_NONAME;
72
73 // Get the right protocol
74 Port = Srv->s_port;
75 if (strcmp(Srv->s_proto,"tcp") == 0)
76 Proto = SOCK_STREAM;
77 else
78 {
79 if (strcmp(Srv->s_proto,"udp") == 0)
80 Proto = SOCK_DGRAM;
81 else
82 return EAI_NONAME;
83 }
84
85 if (hints != 0 && hints->ai_socktype != Proto &&
86 hints->ai_socktype != 0)
87 return EAI_SERVICE;
88 }
89
90 // Start constructing the linked list
91 *res = 0;
92 for (CurAddr = Addr->h_addr_list; *CurAddr != 0; CurAddr++)
93 {
94 // New result structure
95 *Result = (struct addrinfo *)calloc(sizeof(**Result),1);
96 if (*Result == 0)
97 {
98 freeaddrinfo(*res);
99 return EAI_MEMORY;
100 }
101 if (*res == 0)
102 *res = *Result;
103
104 (*Result)->ai_family = AF_INET;
105 (*Result)->ai_socktype = Proto;
106
107 // If we have the IPPROTO defines we can set the protocol field
108 #ifdef IPPROTO_TCP
109 if (Proto == SOCK_STREAM)
110 (*Result)->ai_protocol = IPPROTO_TCP;
111 if (Proto == SOCK_DGRAM)
112 (*Result)->ai_protocol = IPPROTO_UDP;
113 #endif
114
115 // Allocate space for the address
116 (*Result)->ai_addrlen = sizeof(struct sockaddr_in);
117 (*Result)->ai_addr = (struct sockaddr *)calloc(sizeof(sockaddr_in),1);
118 if ((*Result)->ai_addr == 0)
119 {
120 freeaddrinfo(*res);
121 return EAI_MEMORY;
122 }
123
124 // Set the address
125 ((struct sockaddr_in *)(*Result)->ai_addr)->sin_family = AF_INET;
126 ((struct sockaddr_in *)(*Result)->ai_addr)->sin_port = Port;
127 ((struct sockaddr_in *)(*Result)->ai_addr)->sin_addr = *(in_addr *)(*CurAddr);
128
129 Result = &(*Result)->ai_next;
130 }
131
132 return 0;
133}
533151d3
AL
134 /*}}}*/
135// freeaddrinfo - Free the result of getaddrinfo /*{{{*/
136// ---------------------------------------------------------------------
137/* */
934b6582
AL
138void freeaddrinfo(struct addrinfo *ai)
139{
140 struct addrinfo *Tmp;
141 while (ai != 0)
142 {
143 free(ai->ai_addr);
144 Tmp = ai;
145 ai = ai->ai_next;
146 free(ai);
147 }
148}
533151d3 149 /*}}}*/
934b6582 150#endif // HAVE_GETADDRINFO
533151d3
AL
151
152#ifndef HAVE_GETNAMEINFO
153// getnameinfo - Convert a sockaddr to a string /*{{{*/
154// ---------------------------------------------------------------------
155/* */
156int getnameinfo(const struct sockaddr *sa, socklen_t salen,
157 char *host, size_t hostlen,
158 char *serv, size_t servlen,
159 int flags)
160{
161 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
162
6d13bbca 163 // This routine only supports internet addresses
533151d3
AL
164 if (sa->sa_family != AF_INET)
165 return EAI_ADDRFAMILY;
166
167 if (host != 0)
168 {
169 // Try to resolve the hostname
170 if ((flags & NI_NUMERICHOST) != NI_NUMERICHOST)
171 {
172 struct hostent *Ent = gethostbyaddr((char *)&sin->sin_addr,sizeof(sin->sin_addr),
173 AF_INET);
174 if (Ent != 0)
175 strncpy(host,Ent->h_name,hostlen);
176 else
177 {
178 if ((flags & NI_NAMEREQD) == NI_NAMEREQD)
179 {
180 if (h_errno == TRY_AGAIN)
181 return EAI_AGAIN;
182 if (h_errno == NO_RECOVERY)
183 return EAI_FAIL;
184 return EAI_NONAME;
185 }
186
187 flags |= NI_NUMERICHOST;
188 }
189 }
190
191 // Resolve as a plain numberic
192 if ((flags & NI_NUMERICHOST) == NI_NUMERICHOST)
193 {
194 strncpy(host,inet_ntoa(sin->sin_addr),hostlen);
195 }
196 }
197
198 if (serv != 0)
199 {
200 // Try to resolve the hostname
201 if ((flags & NI_NUMERICSERV) != NI_NUMERICSERV)
202 {
203 struct servent *Ent;
204 if ((flags & NI_DATAGRAM) == NI_DATAGRAM)
205 Ent = getservbyport(sin->sin_port,"udp");
206 else
207 Ent = getservbyport(sin->sin_port,"tcp");
208
209 if (Ent != 0)
210 strncpy(serv,Ent->s_name,servlen);
211 else
212 {
213 if ((flags & NI_NAMEREQD) == NI_NAMEREQD)
214 return EAI_NONAME;
215
216 flags |= NI_NUMERICSERV;
217 }
218 }
219
220 // Resolve as a plain numberic
221 if ((flags & NI_NUMERICSERV) == NI_NUMERICSERV)
222 {
223 snprintf(serv,servlen,"%u",sin->sin_port);
224 }
225 }
226
227 return 0;
228}
229 /*}}}*/
230#endif // HAVE_GETNAMEINFO