1*d83a80eeSchristos /* From openssh 4.3p2 filename openbsd-compat/fake-rfc2553.h */
2*d83a80eeSchristos /*
3*d83a80eeSchristos * Copyright (C) 2000-2003 Damien Miller. All rights reserved.
4*d83a80eeSchristos * Copyright (C) 1999 WIDE Project. All rights reserved.
5*d83a80eeSchristos *
6*d83a80eeSchristos * Redistribution and use in source and binary forms, with or without
7*d83a80eeSchristos * modification, are permitted provided that the following conditions
8*d83a80eeSchristos * are met:
9*d83a80eeSchristos * 1. Redistributions of source code must retain the above copyright
10*d83a80eeSchristos * notice, this list of conditions and the following disclaimer.
11*d83a80eeSchristos * 2. Redistributions in binary form must reproduce the above copyright
12*d83a80eeSchristos * notice, this list of conditions and the following disclaimer in the
13*d83a80eeSchristos * documentation and/or other materials provided with the distribution.
14*d83a80eeSchristos * 3. Neither the name of the project nor the names of its contributors
15*d83a80eeSchristos * may be used to endorse or promote products derived from this software
16*d83a80eeSchristos * without specific prior written permission.
17*d83a80eeSchristos *
18*d83a80eeSchristos * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
19*d83a80eeSchristos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20*d83a80eeSchristos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*d83a80eeSchristos * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
22*d83a80eeSchristos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23*d83a80eeSchristos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24*d83a80eeSchristos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25*d83a80eeSchristos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26*d83a80eeSchristos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27*d83a80eeSchristos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28*d83a80eeSchristos * SUCH DAMAGE.
29*d83a80eeSchristos */
30*d83a80eeSchristos
31*d83a80eeSchristos /*
32*d83a80eeSchristos * Pseudo-implementation of RFC2553 name / address resolution functions
33*d83a80eeSchristos *
34*d83a80eeSchristos * But these functions are not implemented correctly. The minimum subset
35*d83a80eeSchristos * is implemented for ssh use only. For example, this routine assumes
36*d83a80eeSchristos * that ai_family is AF_INET. Don't use it for another purpose.
37*d83a80eeSchristos */
38*d83a80eeSchristos
39*d83a80eeSchristos #include <unistd.h>
40*d83a80eeSchristos #include <string.h>
41*d83a80eeSchristos #include <stdio.h>
42*d83a80eeSchristos #include <stdlib.h>
43*d83a80eeSchristos #include "compat/fake-rfc2553.h"
44*d83a80eeSchristos
45*d83a80eeSchristos #ifndef HAVE_GETNAMEINFO
getnameinfo(const struct sockaddr * sa,size_t ATTR_UNUSED (salen),char * host,size_t hostlen,char * serv,size_t servlen,int flags)46*d83a80eeSchristos int getnameinfo(const struct sockaddr *sa, size_t ATTR_UNUSED(salen), char *host,
47*d83a80eeSchristos size_t hostlen, char *serv, size_t servlen, int flags)
48*d83a80eeSchristos {
49*d83a80eeSchristos struct sockaddr_in *sin = (struct sockaddr_in *)sa;
50*d83a80eeSchristos struct hostent *hp;
51*d83a80eeSchristos char tmpserv[16];
52*d83a80eeSchristos
53*d83a80eeSchristos if (serv != NULL) {
54*d83a80eeSchristos snprintf(tmpserv, sizeof(tmpserv), "%d", ntohs(sin->sin_port));
55*d83a80eeSchristos if (strlcpy(serv, tmpserv, servlen) >= servlen)
56*d83a80eeSchristos return (EAI_MEMORY);
57*d83a80eeSchristos }
58*d83a80eeSchristos
59*d83a80eeSchristos if (host != NULL) {
60*d83a80eeSchristos if (flags & NI_NUMERICHOST) {
61*d83a80eeSchristos if (strlcpy(host, inet_ntoa(sin->sin_addr),
62*d83a80eeSchristos hostlen) >= hostlen)
63*d83a80eeSchristos return (EAI_MEMORY);
64*d83a80eeSchristos else
65*d83a80eeSchristos return (0);
66*d83a80eeSchristos } else {
67*d83a80eeSchristos hp = gethostbyaddr((char *)&sin->sin_addr,
68*d83a80eeSchristos sizeof(struct in_addr), AF_INET);
69*d83a80eeSchristos if (hp == NULL)
70*d83a80eeSchristos return (EAI_NODATA);
71*d83a80eeSchristos
72*d83a80eeSchristos if (strlcpy(host, hp->h_name, hostlen) >= hostlen)
73*d83a80eeSchristos return (EAI_MEMORY);
74*d83a80eeSchristos else
75*d83a80eeSchristos return (0);
76*d83a80eeSchristos }
77*d83a80eeSchristos }
78*d83a80eeSchristos return (0);
79*d83a80eeSchristos }
80*d83a80eeSchristos #endif /* !HAVE_GETNAMEINFO */
81*d83a80eeSchristos
82*d83a80eeSchristos #ifndef HAVE_GAI_STRERROR
83*d83a80eeSchristos #ifdef HAVE_CONST_GAI_STRERROR_PROTO
84*d83a80eeSchristos const char *
85*d83a80eeSchristos #else
86*d83a80eeSchristos char *
87*d83a80eeSchristos #endif
gai_strerror(int err)88*d83a80eeSchristos gai_strerror(int err)
89*d83a80eeSchristos {
90*d83a80eeSchristos switch (err) {
91*d83a80eeSchristos case EAI_NODATA:
92*d83a80eeSchristos return ("no address associated with name");
93*d83a80eeSchristos case EAI_MEMORY:
94*d83a80eeSchristos return ("memory allocation failure.");
95*d83a80eeSchristos case EAI_NONAME:
96*d83a80eeSchristos return ("nodename nor servname provided, or not known");
97*d83a80eeSchristos default:
98*d83a80eeSchristos return ("unknown/invalid error.");
99*d83a80eeSchristos }
100*d83a80eeSchristos }
101*d83a80eeSchristos #endif /* !HAVE_GAI_STRERROR */
102*d83a80eeSchristos
103*d83a80eeSchristos #ifndef HAVE_FREEADDRINFO
104*d83a80eeSchristos void
freeaddrinfo(struct addrinfo * ai)105*d83a80eeSchristos freeaddrinfo(struct addrinfo *ai)
106*d83a80eeSchristos {
107*d83a80eeSchristos struct addrinfo *next;
108*d83a80eeSchristos
109*d83a80eeSchristos for(; ai != NULL;) {
110*d83a80eeSchristos next = ai->ai_next;
111*d83a80eeSchristos free(ai);
112*d83a80eeSchristos ai = next;
113*d83a80eeSchristos }
114*d83a80eeSchristos }
115*d83a80eeSchristos #endif /* !HAVE_FREEADDRINFO */
116*d83a80eeSchristos
117*d83a80eeSchristos #ifndef HAVE_GETADDRINFO
118*d83a80eeSchristos static struct
malloc_ai(int port,u_long addr,const struct addrinfo * hints)119*d83a80eeSchristos addrinfo *malloc_ai(int port, u_long addr, const struct addrinfo *hints)
120*d83a80eeSchristos {
121*d83a80eeSchristos struct addrinfo *ai;
122*d83a80eeSchristos
123*d83a80eeSchristos ai = calloc(1, sizeof(*ai) + sizeof(struct sockaddr_in));
124*d83a80eeSchristos if (ai == NULL)
125*d83a80eeSchristos return (NULL);
126*d83a80eeSchristos
127*d83a80eeSchristos ai->ai_addr = (struct sockaddr *)(ai + 1);
128*d83a80eeSchristos /* XXX -- ssh doesn't use sa_len */
129*d83a80eeSchristos ai->ai_addrlen = sizeof(struct sockaddr_in);
130*d83a80eeSchristos ai->ai_addr->sa_family = ai->ai_family = AF_INET;
131*d83a80eeSchristos
132*d83a80eeSchristos ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port;
133*d83a80eeSchristos ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr;
134*d83a80eeSchristos
135*d83a80eeSchristos /* XXX: the following is not generally correct, but does what we want */
136*d83a80eeSchristos if (hints->ai_socktype)
137*d83a80eeSchristos ai->ai_socktype = hints->ai_socktype;
138*d83a80eeSchristos else
139*d83a80eeSchristos ai->ai_socktype = SOCK_STREAM;
140*d83a80eeSchristos
141*d83a80eeSchristos if (hints->ai_protocol)
142*d83a80eeSchristos ai->ai_protocol = hints->ai_protocol;
143*d83a80eeSchristos
144*d83a80eeSchristos return (ai);
145*d83a80eeSchristos }
146*d83a80eeSchristos
147*d83a80eeSchristos int
getaddrinfo(const char * hostname,const char * servname,const struct addrinfo * hints,struct addrinfo ** res)148*d83a80eeSchristos getaddrinfo(const char *hostname, const char *servname,
149*d83a80eeSchristos const struct addrinfo *hints, struct addrinfo **res)
150*d83a80eeSchristos {
151*d83a80eeSchristos struct hostent *hp;
152*d83a80eeSchristos struct servent *sp;
153*d83a80eeSchristos struct in_addr in;
154*d83a80eeSchristos int i;
155*d83a80eeSchristos long int port;
156*d83a80eeSchristos u_long addr;
157*d83a80eeSchristos
158*d83a80eeSchristos port = 0;
159*d83a80eeSchristos if (servname != NULL) {
160*d83a80eeSchristos char *cp;
161*d83a80eeSchristos
162*d83a80eeSchristos port = strtol(servname, &cp, 10);
163*d83a80eeSchristos if (port > 0 && port <= 65535 && *cp == '\0')
164*d83a80eeSchristos port = htons(port);
165*d83a80eeSchristos else if ((sp = getservbyname(servname, NULL)) != NULL)
166*d83a80eeSchristos port = sp->s_port;
167*d83a80eeSchristos else
168*d83a80eeSchristos port = 0;
169*d83a80eeSchristos }
170*d83a80eeSchristos
171*d83a80eeSchristos if (hints && hints->ai_flags & AI_PASSIVE) {
172*d83a80eeSchristos addr = htonl(0x00000000);
173*d83a80eeSchristos if (hostname && inet_aton(hostname, &in) != 0)
174*d83a80eeSchristos addr = in.s_addr;
175*d83a80eeSchristos *res = malloc_ai(port, addr, hints);
176*d83a80eeSchristos if (*res == NULL)
177*d83a80eeSchristos return (EAI_MEMORY);
178*d83a80eeSchristos return (0);
179*d83a80eeSchristos }
180*d83a80eeSchristos
181*d83a80eeSchristos if (!hostname) {
182*d83a80eeSchristos *res = malloc_ai(port, htonl(0x7f000001), hints);
183*d83a80eeSchristos if (*res == NULL)
184*d83a80eeSchristos return (EAI_MEMORY);
185*d83a80eeSchristos return (0);
186*d83a80eeSchristos }
187*d83a80eeSchristos
188*d83a80eeSchristos if (inet_aton(hostname, &in)) {
189*d83a80eeSchristos *res = malloc_ai(port, in.s_addr, hints);
190*d83a80eeSchristos if (*res == NULL)
191*d83a80eeSchristos return (EAI_MEMORY);
192*d83a80eeSchristos return (0);
193*d83a80eeSchristos }
194*d83a80eeSchristos
195*d83a80eeSchristos /* Don't try DNS if AI_NUMERICHOST is set */
196*d83a80eeSchristos if (hints && hints->ai_flags & AI_NUMERICHOST)
197*d83a80eeSchristos return (EAI_NONAME);
198*d83a80eeSchristos
199*d83a80eeSchristos hp = gethostbyname(hostname);
200*d83a80eeSchristos if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
201*d83a80eeSchristos struct addrinfo *cur, *prev;
202*d83a80eeSchristos
203*d83a80eeSchristos cur = prev = *res = NULL;
204*d83a80eeSchristos for (i = 0; hp->h_addr_list[i]; i++) {
205*d83a80eeSchristos struct in_addr *in = (struct in_addr *)hp->h_addr_list[i];
206*d83a80eeSchristos
207*d83a80eeSchristos cur = malloc_ai(port, in->s_addr, hints);
208*d83a80eeSchristos if (cur == NULL) {
209*d83a80eeSchristos if (*res != NULL)
210*d83a80eeSchristos freeaddrinfo(*res);
211*d83a80eeSchristos return (EAI_MEMORY);
212*d83a80eeSchristos }
213*d83a80eeSchristos if (prev)
214*d83a80eeSchristos prev->ai_next = cur;
215*d83a80eeSchristos else
216*d83a80eeSchristos *res = cur;
217*d83a80eeSchristos
218*d83a80eeSchristos prev = cur;
219*d83a80eeSchristos }
220*d83a80eeSchristos return (0);
221*d83a80eeSchristos }
222*d83a80eeSchristos
223*d83a80eeSchristos return (EAI_NODATA);
224*d83a80eeSchristos }
225*d83a80eeSchristos #endif /* !HAVE_GETADDRINFO */
226