]> andersk Git - gssapi-openssh.git/blob - openssh/openbsd-compat/fake-rfc2553.c
o Remove compat package from bundle.
[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 RCSID("$Id$");
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 */
This page took 0.059888 seconds and 5 git commands to generate.