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