]> andersk Git - gssapi-openssh.git/blob - openssh/openbsd-compat/fake-rfc2553.c
b6ea3d21e3425c2a2a070e2ea006e1a562895fff
[gssapi-openssh.git] / openssh / openbsd-compat / fake-rfc2553.c
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 #include <stdlib.h>
41 #include <string.h>
42
43 #include <netinet/in.h>
44 #include <arpa/inet.h>
45
46 #ifndef HAVE_GETNAMEINFO
47 int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, 
48                 size_t hostlen, char *serv, size_t servlen, int flags)
49 {
50         struct sockaddr_in *sin = (struct sockaddr_in *)sa;
51         struct hostent *hp;
52         char tmpserv[16];
53
54         if (serv != NULL) {
55                 snprintf(tmpserv, sizeof(tmpserv), "%d", ntohs(sin->sin_port));
56                 if (strlcpy(serv, tmpserv, servlen) >= servlen)
57                         return (EAI_MEMORY);
58         }
59
60         if (host != NULL) {
61                 if (flags & NI_NUMERICHOST) {
62                         if (strlcpy(host, inet_ntoa(sin->sin_addr),
63                             hostlen) >= hostlen)
64                                 return (EAI_MEMORY);
65                         else
66                                 return (0);
67                 } else {
68                         hp = gethostbyaddr((char *)&sin->sin_addr, 
69                             sizeof(struct in_addr), AF_INET);
70                         if (hp == NULL)
71                                 return (EAI_NODATA);
72                         
73                         if (strlcpy(host, hp->h_name, hostlen) >= hostlen)
74                                 return (EAI_MEMORY);
75                         else
76                                 return (0);
77                 }
78         }
79         return (0);
80 }
81 #endif /* !HAVE_GETNAMEINFO */
82
83 #ifndef HAVE_GAI_STRERROR
84 #ifdef HAVE_CONST_GAI_STRERROR_PROTO
85 const char *
86 #else
87 char *
88 #endif
89 gai_strerror(int err)
90 {
91         switch (err) {
92         case EAI_NODATA:
93                 return ("no address associated with name");
94         case EAI_MEMORY:
95                 return ("memory allocation failure.");
96         case EAI_NONAME:
97                 return ("nodename nor servname provided, or not known");
98         default:
99                 return ("unknown/invalid error.");
100         }
101 }    
102 #endif /* !HAVE_GAI_STRERROR */
103
104 #ifndef HAVE_FREEADDRINFO
105 void
106 freeaddrinfo(struct addrinfo *ai)
107 {
108         struct addrinfo *next;
109
110         for(; ai != NULL;) {
111                 next = ai->ai_next;
112                 free(ai);
113                 ai = next;
114         }
115 }
116 #endif /* !HAVE_FREEADDRINFO */
117
118 #ifndef HAVE_GETADDRINFO
119 static struct
120 addrinfo *malloc_ai(int port, u_long addr, const struct addrinfo *hints)
121 {
122         struct addrinfo *ai;
123
124         ai = malloc(sizeof(*ai) + sizeof(struct sockaddr_in));
125         if (ai == NULL)
126                 return (NULL);
127         
128         memset(ai, '\0', sizeof(*ai) + sizeof(struct sockaddr_in));
129         
130         ai->ai_addr = (struct sockaddr *)(ai + 1);
131         /* XXX -- ssh doesn't use sa_len */
132         ai->ai_addrlen = sizeof(struct sockaddr_in);
133         ai->ai_addr->sa_family = ai->ai_family = AF_INET;
134
135         ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port;
136         ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr;
137         
138         /* XXX: the following is not generally correct, but does what we want */
139         if (hints->ai_socktype)
140                 ai->ai_socktype = hints->ai_socktype;
141         else
142                 ai->ai_socktype = SOCK_STREAM;
143
144         if (hints->ai_protocol)
145                 ai->ai_protocol = hints->ai_protocol;
146
147         return (ai);
148 }
149
150 int
151 getaddrinfo(const char *hostname, const char *servname, 
152     const struct addrinfo *hints, struct addrinfo **res)
153 {
154         struct hostent *hp;
155         struct servent *sp;
156         struct in_addr in;
157         int i;
158         long int port;
159         u_long addr;
160
161         port = 0;
162         if (servname != NULL) {
163                 char *cp;
164
165                 port = strtol(servname, &cp, 10);
166                 if (port > 0 && port <= 65535 && *cp == '\0')
167                         port = htons(port);
168                 else if ((sp = getservbyname(servname, NULL)) != NULL)
169                         port = sp->s_port;
170                 else
171                         port = 0;
172         }
173
174         if (hints && hints->ai_flags & AI_PASSIVE) {
175                 addr = htonl(0x00000000);
176                 if (hostname && inet_aton(hostname, &in) != 0)
177                         addr = in.s_addr;
178                 *res = malloc_ai(port, addr, hints);
179                 if (*res == NULL) 
180                         return (EAI_MEMORY);
181                 return (0);
182         }
183                 
184         if (!hostname) {
185                 *res = malloc_ai(port, htonl(0x7f000001), hints);
186                 if (*res == NULL) 
187                         return (EAI_MEMORY);
188                 return (0);
189         }
190         
191         if (inet_aton(hostname, &in)) {
192                 *res = malloc_ai(port, in.s_addr, hints);
193                 if (*res == NULL) 
194                         return (EAI_MEMORY);
195                 return (0);
196         }
197         
198         /* Don't try DNS if AI_NUMERICHOST is set */
199         if (hints && hints->ai_flags & AI_NUMERICHOST)
200                 return (EAI_NONAME);
201         
202         hp = gethostbyname(hostname);
203         if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
204                 struct addrinfo *cur, *prev;
205
206                 cur = prev = *res = NULL;
207                 for (i = 0; hp->h_addr_list[i]; i++) {
208                         struct in_addr *in = (struct in_addr *)hp->h_addr_list[i];
209
210                         cur = malloc_ai(port, in->s_addr, hints);
211                         if (cur == NULL) {
212                                 if (*res != NULL)
213                                         freeaddrinfo(*res);
214                                 return (EAI_MEMORY);
215                         }
216                         if (prev)
217                                 prev->ai_next = cur;
218                         else
219                                 *res = cur;
220
221                         prev = cur;
222                 }
223                 return (0);
224         }
225         
226         return (EAI_NODATA);
227 }
228 #endif /* !HAVE_GETADDRINFO */
This page took 0.039534 seconds and 3 git commands to generate.