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