1/* 2 * Mar 8, 2000 by Hajimu UMEMOTO <ume@mahoroba.org> 3 * $Id: getaddrinfo.c,v 1.9 2006/01/24 00:16:04 snsimon Exp $ 4 * 5 * This module is besed on ssh-1.2.27-IPv6-1.5 written by 6 * KIKUCHI Takahiro <kick@kyoto.wide.ad.jp> 7 */ 8/* 9 * Copyright (c) 1998-2003 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 "saslauthd.h" 62#ifndef macintosh 63#include <sys/param.h> 64#include <arpa/inet.h> 65#endif 66#include <ctype.h> 67 68static struct addrinfo * 69malloc_ai(int port, u_long addr, int socktype, int proto) 70{ 71 struct addrinfo *ai; 72 73 ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) + 74 sizeof(struct sockaddr_in)); 75 if (ai) { 76 memset(ai, 0, sizeof(struct addrinfo) + sizeof(struct sockaddr_in)); 77 ai->ai_addr = (struct sockaddr *)(ai + 1); 78 /* XXX -- ssh doesn't use sa_len */ 79 ai->ai_addrlen = sizeof(struct sockaddr_in); 80#ifdef HAVE_SOCKADDR_SA_LEN 81 ai->ai_addr->sa_len = sizeof(struct sockaddr_in); 82#endif 83 ai->ai_addr->sa_family = ai->ai_family = AF_INET; 84 ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port; 85 ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr; 86 ai->ai_socktype = socktype; 87 ai->ai_protocol = proto; 88 return ai; 89 } else { 90 return NULL; 91 } 92} 93 94char * 95gai_strerror(int ecode) 96{ 97 switch (ecode) { 98 case EAI_NODATA: 99 return "no address associated with hostname."; 100 case EAI_MEMORY: 101 return "memory allocation failure."; 102 case EAI_FAMILY: 103 return "ai_family not supported."; 104 case EAI_SERVICE: 105 return "servname not supported for ai_socktype."; 106 default: 107 return "unknown error."; 108 } 109} 110 111void 112freeaddrinfo(struct addrinfo *ai) 113{ 114 struct addrinfo *next; 115 116 if (ai->ai_canonname) 117 free(ai->ai_canonname); 118 do { 119 next = ai->ai_next; 120 free(ai); 121 } while ((ai = next) != NULL); 122} 123 124int 125getaddrinfo(const char *hostname, const char *servname, 126 const struct addrinfo *hints, struct addrinfo **res) 127{ 128 struct addrinfo *cur, *prev = NULL; 129 struct hostent *hp; 130 struct in_addr in; 131 int i, port = 0, socktype, proto; 132 133 if (hints && hints->ai_family != PF_INET && hints->ai_family != PF_UNSPEC) 134 return EAI_FAMILY; 135 136 socktype = (hints && hints->ai_socktype) ? hints->ai_socktype 137 : SOCK_STREAM; 138 if (hints && hints->ai_protocol) 139 proto = hints->ai_protocol; 140 else { 141 switch (socktype) { 142 case SOCK_DGRAM: 143 proto = IPPROTO_UDP; 144 break; 145 case SOCK_STREAM: 146 proto = IPPROTO_TCP; 147 break; 148 default: 149 proto = 0; 150 break; 151 } 152 } 153 if (servname) { 154 if (isdigit((int)*servname)) 155 port = htons(atoi(servname)); 156 else { 157 struct servent *se; 158 char *pe_proto; 159 160 switch (socktype) { 161 case SOCK_DGRAM: 162 pe_proto = "udp"; 163 break; 164 case SOCK_STREAM: 165 pe_proto = "tcp"; 166 break; 167 default: 168 pe_proto = NULL; 169 break; 170 } 171 if ((se = getservbyname(servname, pe_proto)) == NULL) 172 return EAI_SERVICE; 173 port = se->s_port; 174 } 175 } 176 if (!hostname) { 177 if (hints && hints->ai_flags & AI_PASSIVE) 178 *res = malloc_ai(port, htonl(0x00000000), socktype, proto); 179 else 180 *res = malloc_ai(port, htonl(0x7f000001), socktype, proto); 181 if (*res) 182 return 0; 183 else 184 return EAI_MEMORY; 185 } 186 if (inet_aton(hostname, &in)) { 187 *res = malloc_ai(port, in.s_addr, socktype, proto); 188 if (*res) 189 return 0; 190 else 191 return EAI_MEMORY; 192 } 193 if (hints && hints->ai_flags & AI_NUMERICHOST) 194 return EAI_NODATA; 195#ifndef macintosh 196 if ((hp = gethostbyname(hostname)) && 197 hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) { 198 for (i = 0; hp->h_addr_list[i]; i++) { 199 if ((cur = malloc_ai(port, 200 ((struct in_addr *)hp->h_addr_list[i])->s_addr, 201 socktype, proto)) == NULL) { 202 if (*res) 203 freeaddrinfo(*res); 204 return EAI_MEMORY; 205 } 206 if (prev) 207 prev->ai_next = cur; 208 else 209 *res = cur; 210 prev = cur; 211 } 212 if (hints && hints->ai_flags & AI_CANONNAME && *res) { 213 /* NOT sasl_strdup for compatibility */ 214 if (((*res)->ai_canonname = strdup(hp->h_name)) == NULL) { 215 freeaddrinfo(*res); 216 return EAI_MEMORY; 217 } 218 } 219 return 0; 220 } 221#endif 222 return EAI_NODATA; 223} 224