1238104Sdes/* From openssh 4.3p2 filename openbsd-compat/fake-rfc2553.h */ 2238104Sdes/* 3238104Sdes * Copyright (C) 2000-2003 Damien Miller. All rights reserved. 4238104Sdes * Copyright (C) 1999 WIDE Project. All rights reserved. 5238104Sdes * 6238104Sdes * Redistribution and use in source and binary forms, with or without 7238104Sdes * modification, are permitted provided that the following conditions 8238104Sdes * are met: 9238104Sdes * 1. Redistributions of source code must retain the above copyright 10238104Sdes * notice, this list of conditions and the following disclaimer. 11238104Sdes * 2. Redistributions in binary form must reproduce the above copyright 12238104Sdes * notice, this list of conditions and the following disclaimer in the 13238104Sdes * documentation and/or other materials provided with the distribution. 14238104Sdes * 3. Neither the name of the project nor the names of its contributors 15238104Sdes * may be used to endorse or promote products derived from this software 16238104Sdes * without specific prior written permission. 17238104Sdes * 18238104Sdes * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 19238104Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20238104Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21238104Sdes * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 22238104Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23238104Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24238104Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25238104Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26238104Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27238104Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28238104Sdes * SUCH DAMAGE. 29238104Sdes */ 30238104Sdes 31238104Sdes/* 32238104Sdes * Pseudo-implementation of RFC2553 name / address resolution functions 33238104Sdes * 34238104Sdes * But these functions are not implemented correctly. The minimum subset 35238104Sdes * is implemented for ssh use only. For example, this routine assumes 36238104Sdes * that ai_family is AF_INET. Don't use it for another purpose. 37238104Sdes */ 38238104Sdes 39238104Sdes#include <ldns/config.h> 40238104Sdes#include <ldns/common.h> 41238104Sdes#include <unistd.h> 42238104Sdes#include <string.h> 43238104Sdes#include <stdio.h> 44238104Sdes#include <stdlib.h> 45238104Sdes#include "compat/fake-rfc2553.h" 46238104Sdes 47238104Sdes#ifndef HAVE_GETNAMEINFO 48238104Sdesint getnameinfo(const struct sockaddr *sa, size_t ATTR_UNUSED(salen), char *host, 49238104Sdes size_t hostlen, char *serv, size_t servlen, int flags) 50238104Sdes{ 51238104Sdes struct sockaddr_in *sin = (struct sockaddr_in *)sa; 52238104Sdes struct hostent *hp; 53238104Sdes char tmpserv[16]; 54238104Sdes 55238104Sdes if (serv != NULL) { 56238104Sdes snprintf(tmpserv, sizeof(tmpserv), "%d", ntohs(sin->sin_port)); 57238104Sdes if (strlcpy(serv, tmpserv, servlen) >= servlen) 58238104Sdes return (EAI_MEMORY); 59238104Sdes } 60238104Sdes 61238104Sdes if (host != NULL) { 62238104Sdes if (flags & NI_NUMERICHOST) { 63238104Sdes if (strlcpy(host, inet_ntoa(sin->sin_addr), 64238104Sdes hostlen) >= hostlen) 65238104Sdes return (EAI_MEMORY); 66238104Sdes else 67238104Sdes return (0); 68238104Sdes } else { 69238104Sdes hp = gethostbyaddr((char *)&sin->sin_addr, 70238104Sdes sizeof(struct in_addr), AF_INET); 71238104Sdes if (hp == NULL) 72238104Sdes return (EAI_NODATA); 73238104Sdes 74238104Sdes if (strlcpy(host, hp->h_name, hostlen) >= hostlen) 75238104Sdes return (EAI_MEMORY); 76238104Sdes else 77238104Sdes return (0); 78238104Sdes } 79238104Sdes } 80238104Sdes return (0); 81238104Sdes} 82238104Sdes#endif /* !HAVE_GETNAMEINFO */ 83238104Sdes 84238104Sdes#ifndef HAVE_GAI_STRERROR 85238104Sdes#ifdef HAVE_CONST_GAI_STRERROR_PROTO 86238104Sdesconst char * 87238104Sdes#else 88238104Sdeschar * 89238104Sdes#endif 90238104Sdesgai_strerror(int err) 91238104Sdes{ 92238104Sdes switch (err) { 93238104Sdes case EAI_NODATA: 94238104Sdes return ("no address associated with name"); 95238104Sdes case EAI_MEMORY: 96238104Sdes return ("memory allocation failure."); 97238104Sdes case EAI_NONAME: 98238104Sdes return ("nodename nor servname provided, or not known"); 99238104Sdes default: 100238104Sdes return ("unknown/invalid error."); 101238104Sdes } 102238104Sdes} 103238104Sdes#endif /* !HAVE_GAI_STRERROR */ 104238104Sdes 105238104Sdes#ifndef HAVE_FREEADDRINFO 106238104Sdesvoid 107238104Sdesfreeaddrinfo(struct addrinfo *ai) 108238104Sdes{ 109238104Sdes struct addrinfo *next; 110238104Sdes 111238104Sdes for(; ai != NULL;) { 112238104Sdes next = ai->ai_next; 113238104Sdes free(ai); 114238104Sdes ai = next; 115238104Sdes } 116238104Sdes} 117238104Sdes#endif /* !HAVE_FREEADDRINFO */ 118238104Sdes 119238104Sdes#ifndef HAVE_GETADDRINFO 120238104Sdesstatic struct 121238104Sdesaddrinfo *malloc_ai(int port, u_long addr, const struct addrinfo *hints) 122238104Sdes{ 123238104Sdes struct addrinfo *ai; 124238104Sdes 125238104Sdes ai = malloc(sizeof(*ai) + sizeof(struct sockaddr_in)); 126238104Sdes if (ai == NULL) 127238104Sdes return (NULL); 128238104Sdes 129238104Sdes memset(ai, '\0', sizeof(*ai) + sizeof(struct sockaddr_in)); 130238104Sdes 131238104Sdes ai->ai_addr = (struct sockaddr *)(ai + 1); 132238104Sdes /* XXX -- ssh doesn't use sa_len */ 133238104Sdes ai->ai_addrlen = sizeof(struct sockaddr_in); 134238104Sdes ai->ai_addr->sa_family = ai->ai_family = AF_INET; 135238104Sdes 136238104Sdes ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port; 137238104Sdes ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr; 138238104Sdes 139238104Sdes /* XXX: the following is not generally correct, but does what we want */ 140238104Sdes if (hints->ai_socktype) 141238104Sdes ai->ai_socktype = hints->ai_socktype; 142238104Sdes else 143238104Sdes ai->ai_socktype = SOCK_STREAM; 144238104Sdes 145238104Sdes if (hints->ai_protocol) 146238104Sdes ai->ai_protocol = hints->ai_protocol; 147238104Sdes 148238104Sdes return (ai); 149238104Sdes} 150238104Sdes 151238104Sdesint 152238104Sdesgetaddrinfo(const char *hostname, const char *servname, 153238104Sdes const struct addrinfo *hints, struct addrinfo **res) 154238104Sdes{ 155238104Sdes struct hostent *hp; 156238104Sdes struct servent *sp; 157238104Sdes struct in_addr in; 158238104Sdes int i; 159238104Sdes long int port; 160238104Sdes u_long addr; 161238104Sdes 162238104Sdes port = 0; 163238104Sdes if (servname != NULL) { 164238104Sdes char *cp; 165238104Sdes 166238104Sdes port = strtol(servname, &cp, 10); 167238104Sdes if (port > 0 && port <= 65535 && *cp == '\0') 168238104Sdes port = htons(port); 169238104Sdes else if ((sp = getservbyname(servname, NULL)) != NULL) 170238104Sdes port = sp->s_port; 171238104Sdes else 172238104Sdes port = 0; 173238104Sdes } 174238104Sdes 175238104Sdes if (hints && hints->ai_flags & AI_PASSIVE) { 176238104Sdes addr = htonl(0x00000000); 177238104Sdes if (hostname && inet_aton(hostname, &in) != 0) 178238104Sdes addr = in.s_addr; 179238104Sdes *res = malloc_ai(port, addr, hints); 180238104Sdes if (*res == NULL) 181238104Sdes return (EAI_MEMORY); 182238104Sdes return (0); 183238104Sdes } 184238104Sdes 185238104Sdes if (!hostname) { 186238104Sdes *res = malloc_ai(port, htonl(0x7f000001), hints); 187238104Sdes if (*res == NULL) 188238104Sdes return (EAI_MEMORY); 189238104Sdes return (0); 190238104Sdes } 191238104Sdes 192238104Sdes if (inet_aton(hostname, &in)) { 193238104Sdes *res = malloc_ai(port, in.s_addr, hints); 194238104Sdes if (*res == NULL) 195238104Sdes return (EAI_MEMORY); 196238104Sdes return (0); 197238104Sdes } 198238104Sdes 199238104Sdes /* Don't try DNS if AI_NUMERICHOST is set */ 200238104Sdes if (hints && hints->ai_flags & AI_NUMERICHOST) 201238104Sdes return (EAI_NONAME); 202238104Sdes 203238104Sdes hp = gethostbyname(hostname); 204238104Sdes if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) { 205238104Sdes struct addrinfo *cur, *prev; 206238104Sdes 207238104Sdes cur = prev = *res = NULL; 208238104Sdes for (i = 0; hp->h_addr_list[i]; i++) { 209238104Sdes struct in_addr *in = (struct in_addr *)hp->h_addr_list[i]; 210238104Sdes 211238104Sdes cur = malloc_ai(port, in->s_addr, hints); 212238104Sdes if (cur == NULL) { 213238104Sdes if (*res != NULL) 214238104Sdes freeaddrinfo(*res); 215238104Sdes return (EAI_MEMORY); 216238104Sdes } 217238104Sdes if (prev) 218238104Sdes prev->ai_next = cur; 219238104Sdes else 220238104Sdes *res = cur; 221238104Sdes 222238104Sdes prev = cur; 223238104Sdes } 224238104Sdes return (0); 225238104Sdes } 226238104Sdes 227238104Sdes return (EAI_NODATA); 228238104Sdes} 229238104Sdes#endif /* !HAVE_GETADDRINFO */ 230