source: trunk/third/cyrus-sasl/lib/getaddrinfo.c @ 18842

Revision 18842, 6.8 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18841, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * Mar  8, 2000 by Hajimu UMEMOTO <ume@mahoroba.org>
3 * $Id: getaddrinfo.c,v 1.1.1.2 2003-02-12 22:33:35 ghudson Exp $
4 *
5 * This module is based on ssh-1.2.27-IPv6-1.5 written by
6 * KIKUCHI Takahiro <kick@kyoto.wide.ad.jp>
7 */
8/*
9 * Copyright (c) 2001 Carnegie Mellon University.  All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright
16 *    notice, this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright
19 *    notice, this list of conditions and the following disclaimer in
20 *    the documentation and/or other materials provided with the
21 *    distribution.
22 *
23 * 3. The name "Carnegie Mellon University" must not be used to
24 *    endorse or promote products derived from this software without
25 *    prior written permission. For permission or any other legal
26 *    details, please contact 
27 *      Office of Technology Transfer
28 *      Carnegie Mellon University
29 *      5000 Forbes Avenue
30 *      Pittsburgh, PA  15213-3890
31 *      (412) 268-4387, fax: (412) 268-7395
32 *      tech-transfer@andrew.cmu.edu
33 *
34 * 4. Redistributions of any form whatsoever must retain the following
35 *    acknowledgment:
36 *    "This product includes software developed by Computing Services
37 *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
38 *
39 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
40 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
41 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
42 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
43 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
44 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
45 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
46 */
47/*
48 * fake library for ssh
49 *
50 * This file includes getaddrinfo(), freeaddrinfo() and gai_strerror().
51 * These funtions are defined in rfc2133.
52 *
53 * But these functions are not implemented correctly. The minimum subset
54 * is implemented for ssh use only. For exapmle, this routine assumes
55 * that ai_family is AF_INET. Don't use it for another purpose.
56 *
57 * In the case not using 'configure --enable-ipv6', this getaddrinfo.c
58 * will be used if you have broken getaddrinfo or no getaddrinfo.
59 */
60
61#include "config.h"
62#ifndef WIN32
63#include <sys/param.h>
64# ifndef macintosh
65#  include <arpa/inet.h>
66# endif /* macintosh */
67#endif /* WIN32 */
68#include <ctype.h>
69
70#ifdef WIN32
71/* : Windows socket library is missing inet_aton, emulate it with
72   : inet_addr. inet_aton return 0 if the address is uncorrect, a non zero
73   : value otherwise */
74int
75inet_aton (const char *cp, struct in_addr *inp)
76{
77    if (cp == NULL || inp == NULL) {
78        return (0);
79    }
80
81    /* : handle special case */
82    if (strcmp (cp, "255.255.255.255") == 0) {
83        inp->s_addr = (unsigned int) 0xFFFFFFFF;
84        return (1);
85    }
86
87    inp->s_addr = inet_addr (cp);
88    return (1);
89}
90#endif /* WIN32 */
91
92static struct addrinfo *
93malloc_ai(int port, unsigned long addr, int socktype, int proto)
94{
95    struct addrinfo *ai;
96
97    ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) +
98                                   sizeof(struct sockaddr_in));
99    if (ai) {
100        memset(ai, 0, sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
101        ai->ai_addr = (struct sockaddr *)(ai + 1);
102        /* XXX -- ssh doesn't use sa_len */
103        ai->ai_addrlen = sizeof(struct sockaddr_in);
104#ifdef HAVE_SOCKADDR_SA_LEN
105        ai->ai_addr->sa_len = sizeof(struct sockaddr_in);
106#endif
107        ai->ai_addr->sa_family = ai->ai_family = AF_INET;
108        ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port;
109        ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr;
110        ai->ai_socktype = socktype;
111        ai->ai_protocol = proto;
112        return ai;
113    } else {
114        return NULL;
115    }
116}
117
118char *
119gai_strerror(int ecode)
120{
121    switch (ecode) {
122    case EAI_NODATA:
123        return "no address associated with hostname.";
124    case EAI_MEMORY:
125        return "memory allocation failure.";
126    case EAI_FAMILY:
127        return "ai_family not supported.";
128    case EAI_SERVICE:
129        return "servname not supported for ai_socktype.";
130    default:
131        return "unknown error.";
132    }
133}
134
135void
136freeaddrinfo(struct addrinfo *ai)
137{
138    struct addrinfo *next;
139
140    if (ai->ai_canonname)
141        free(ai->ai_canonname);
142    do {
143        next = ai->ai_next;
144        free(ai);
145    } while ((ai = next) != NULL);
146}
147
148int
149getaddrinfo(const char *hostname, const char *servname,
150            const struct addrinfo *hints, struct addrinfo **res)
151{
152    struct addrinfo *cur, *prev = NULL;
153    struct hostent *hp;
154    struct in_addr in;
155    int i, port = 0, socktype, proto;
156
157    if (hints && hints->ai_family != PF_INET && hints->ai_family != PF_UNSPEC)
158        return EAI_FAMILY;
159
160    socktype = (hints && hints->ai_socktype) ? hints->ai_socktype
161                                             : SOCK_STREAM;
162    if (hints && hints->ai_protocol)
163        proto = hints->ai_protocol;
164    else {
165        switch (socktype) {
166        case SOCK_DGRAM:
167            proto = IPPROTO_UDP;
168            break;
169        case SOCK_STREAM:
170            proto = IPPROTO_TCP;
171            break;
172        default:
173            proto = 0;
174            break;
175        }
176    }
177    if (servname) {
178        if (isdigit((int)*servname))
179            port = htons((short) atoi(servname));
180        else {
181            struct servent *se;
182            char *pe_proto;
183
184            switch (socktype) {
185            case SOCK_DGRAM:
186                pe_proto = "udp";
187                break;
188            case SOCK_STREAM:
189                pe_proto = "tcp";
190                break;
191            default:
192                pe_proto = NULL;
193                break;
194            }
195            if ((se = getservbyname(servname, pe_proto)) == NULL)
196                return EAI_SERVICE;
197            port = se->s_port;
198        }
199    }
200    if (!hostname) {
201        if (hints && hints->ai_flags & AI_PASSIVE)
202            *res = malloc_ai(port, htonl(0x00000000), socktype, proto);
203        else
204            *res = malloc_ai(port, htonl(0x7f000001), socktype, proto);
205        if (*res)
206            return 0;
207        else
208            return EAI_MEMORY;
209    }
210#if HAVE_INET_ATON
211    if (inet_aton(hostname, &in))
212#else
213    if ((in.s_addr = inet_addr(hostname)) != -1)
214#endif
215    {
216        *res = malloc_ai(port, in.s_addr, socktype, proto);
217        if (*res)
218            return 0;
219        else
220            return EAI_MEMORY;
221    }
222    if (hints && hints->ai_flags & AI_NUMERICHOST)
223        return EAI_NODATA;
224#ifndef macintosh
225    if ((hp = gethostbyname(hostname)) &&
226        hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
227        for (i = 0; hp->h_addr_list[i]; i++) {
228            if ((cur = malloc_ai(port,
229                                ((struct in_addr *)hp->h_addr_list[i])->s_addr,
230                                socktype, proto)) == NULL) {
231                if (*res)
232                    freeaddrinfo(*res);
233                return EAI_MEMORY;
234            }
235            if (prev)
236                prev->ai_next = cur;
237            else
238                *res = cur;
239            prev = cur;
240        }
241        if (hints && hints->ai_flags & AI_CANONNAME && *res) {
242            /* NOT sasl_strdup for compatibility */
243            if (((*res)->ai_canonname = strdup(hp->h_name)) == NULL) {
244                freeaddrinfo(*res);
245                return EAI_MEMORY;
246            }
247        }
248        return 0;
249    }
250#endif
251    return EAI_NODATA;
252}
Note: See TracBrowser for help on using the repository browser.