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