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