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