Mercurial > dropbear
comparison fake-rfc2553.c @ 64:efb5e0b335cf
TCP forwarding works.
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Thu, 12 Aug 2004 13:48:42 +0000 |
parents | |
children | 86725004a0ea |
comparison
equal
deleted
inserted
replaced
63:dcc43965928f | 64:efb5e0b335cf |
---|---|
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.5 2003/09/22 02:08:23 dtucker 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 #ifdef HAVE_CONST_GAI_STRERROR_PROTO | |
81 const char * | |
82 #else | |
83 char * | |
84 #endif | |
85 gai_strerror(int err) | |
86 { | |
87 switch (err) { | |
88 case EAI_NODATA: | |
89 return ("no address associated with name"); | |
90 case EAI_MEMORY: | |
91 return ("memory allocation failure."); | |
92 case EAI_NONAME: | |
93 return ("nodename nor servname provided, or not known"); | |
94 default: | |
95 return ("unknown/invalid error."); | |
96 } | |
97 } | |
98 #endif /* !HAVE_GAI_STRERROR */ | |
99 | |
100 #ifndef HAVE_FREEADDRINFO | |
101 void | |
102 freeaddrinfo(struct addrinfo *ai) | |
103 { | |
104 struct addrinfo *next; | |
105 | |
106 for(; ai != NULL;) { | |
107 next = ai->ai_next; | |
108 free(ai); | |
109 ai = next; | |
110 } | |
111 } | |
112 #endif /* !HAVE_FREEADDRINFO */ | |
113 | |
114 #ifndef HAVE_GETADDRINFO | |
115 static struct | |
116 addrinfo *malloc_ai(int port, u_long addr, const struct addrinfo *hints) | |
117 { | |
118 struct addrinfo *ai; | |
119 | |
120 ai = malloc(sizeof(*ai) + sizeof(struct sockaddr_in)); | |
121 if (ai == NULL) | |
122 return (NULL); | |
123 | |
124 memset(ai, '\0', sizeof(*ai) + sizeof(struct sockaddr_in)); | |
125 | |
126 ai->ai_addr = (struct sockaddr *)(ai + 1); | |
127 /* XXX -- ssh doesn't use sa_len */ | |
128 ai->ai_addrlen = sizeof(struct sockaddr_in); | |
129 ai->ai_addr->sa_family = ai->ai_family = AF_INET; | |
130 | |
131 ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port; | |
132 ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr; | |
133 | |
134 /* XXX: the following is not generally correct, but does what we want */ | |
135 if (hints->ai_socktype) | |
136 ai->ai_socktype = hints->ai_socktype; | |
137 else | |
138 ai->ai_socktype = SOCK_STREAM; | |
139 | |
140 if (hints->ai_protocol) | |
141 ai->ai_protocol = hints->ai_protocol; | |
142 | |
143 return (ai); | |
144 } | |
145 | |
146 int | |
147 getaddrinfo(const char *hostname, const char *servname, | |
148 const struct addrinfo *hints, struct addrinfo **res) | |
149 { | |
150 struct hostent *hp; | |
151 struct servent *sp; | |
152 struct in_addr in; | |
153 int i; | |
154 long int port; | |
155 u_long addr; | |
156 | |
157 port = 0; | |
158 if (servname != NULL) { | |
159 char *cp; | |
160 | |
161 port = strtol(servname, &cp, 10); | |
162 if (port > 0 && port <= 65535 && *cp == '\0') | |
163 port = htons(port); | |
164 else if ((sp = getservbyname(servname, NULL)) != NULL) | |
165 port = sp->s_port; | |
166 else | |
167 port = 0; | |
168 } | |
169 | |
170 if (hints && hints->ai_flags & AI_PASSIVE) { | |
171 addr = htonl(0x00000000); | |
172 if (hostname && inet_aton(hostname, &in) != 0) | |
173 addr = in.s_addr; | |
174 *res = malloc_ai(port, addr, hints); | |
175 if (*res == NULL) | |
176 return (EAI_MEMORY); | |
177 return (0); | |
178 } | |
179 | |
180 if (!hostname) { | |
181 *res = malloc_ai(port, htonl(0x7f000001), hints); | |
182 if (*res == NULL) | |
183 return (EAI_MEMORY); | |
184 return (0); | |
185 } | |
186 | |
187 if (inet_aton(hostname, &in)) { | |
188 *res = malloc_ai(port, in.s_addr, hints); | |
189 if (*res == NULL) | |
190 return (EAI_MEMORY); | |
191 return (0); | |
192 } | |
193 | |
194 /* Don't try DNS if AI_NUMERICHOST is set */ | |
195 if (hints && hints->ai_flags & AI_NUMERICHOST) | |
196 return (EAI_NONAME); | |
197 | |
198 hp = gethostbyname(hostname); | |
199 if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) { | |
200 struct addrinfo *cur, *prev; | |
201 | |
202 cur = prev = *res = NULL; | |
203 for (i = 0; hp->h_addr_list[i]; i++) { | |
204 struct in_addr *in = (struct in_addr *)hp->h_addr_list[i]; | |
205 | |
206 cur = malloc_ai(port, in->s_addr, hints); | |
207 if (cur == NULL) { | |
208 if (*res != NULL) | |
209 freeaddrinfo(*res); | |
210 return (EAI_MEMORY); | |
211 } | |
212 if (prev) | |
213 prev->ai_next = cur; | |
214 else | |
215 *res = cur; | |
216 | |
217 prev = cur; | |
218 } | |
219 return (0); | |
220 } | |
221 | |
222 return (EAI_NODATA); | |
223 } | |
224 #endif /* !HAVE_GETADDRINFO */ |