1 /*
   2  * fake library for ssh
   3  *
   4  * This file includes getaddrinfo(), freeaddrinfo() and gai_strerror().
   5  * These funtions are defined in rfc2133.
   6  *
   7  * But these functions are not implemented correctly. The minimum subset
   8  * is implemented for ssh use only. For exapmle, this routine assumes
   9  * that ai_family is AF_INET. Don't use it for another purpose.
  10  */
  11 
  12 #include "includes.h"
  13 #include "ssh.h"
  14 
  15 RCSID("$Id: fake-getaddrinfo.c,v 1.2 2001/02/09 01:55:36 djm Exp $");
  16 
  17 #pragma ident   "%Z%%M% %I%     %E% SMI"
  18 
  19 #ifndef HAVE_GAI_STRERROR
  20 char *gai_strerror(int ecode)
  21 {
  22         switch (ecode) {
  23                 case EAI_NODATA:
  24                         return "no address associated with hostname.";
  25                 case EAI_MEMORY:
  26                         return "memory allocation failure.";
  27                 default:
  28                         return "unknown error.";
  29         }
  30 }    
  31 #endif /* !HAVE_GAI_STRERROR */
  32 
  33 #ifndef HAVE_FREEADDRINFO
  34 void freeaddrinfo(struct addrinfo *ai)
  35 {
  36         struct addrinfo *next;
  37 
  38         do {
  39                 next = ai->ai_next;
  40                 free(ai);
  41         } while (NULL != (ai = next));
  42 }
  43 #endif /* !HAVE_FREEADDRINFO */
  44 
  45 #ifndef HAVE_GETADDRINFO
  46 static struct addrinfo *malloc_ai(int port, u_long addr)
  47 {
  48         struct addrinfo *ai;
  49 
  50         ai = malloc(sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
  51         if (ai == NULL)
  52                 return(NULL);
  53         
  54         memset(ai, 0, sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
  55         
  56         ai->ai_addr = (struct sockaddr *)(ai + 1);
  57         /* XXX -- ssh doesn't use sa_len */
  58         ai->ai_addrlen = sizeof(struct sockaddr_in);
  59         ai->ai_addr->sa_family = ai->ai_family = AF_INET;
  60 
  61         ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port;
  62         ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr;
  63         
  64         return(ai);
  65 }
  66 
  67 int getaddrinfo(const char *hostname, const char *servname, 
  68                 const struct addrinfo *hints, struct addrinfo **res)
  69 {
  70         struct addrinfo *cur, *prev = NULL;
  71         struct hostent *hp;
  72         struct in_addr in;
  73         int i, port;
  74 
  75         if (servname)
  76                 port = htons(atoi(servname));
  77         else
  78                 port = 0;
  79 
  80         if (hints && hints->ai_flags & AI_PASSIVE) {
  81                 if (NULL != (*res = malloc_ai(port, htonl(0x00000000))))
  82                         return 0;
  83                 else
  84                         return EAI_MEMORY;
  85         }
  86                 
  87         if (!hostname) {
  88                 if (NULL != (*res = malloc_ai(port, htonl(0x7f000001))))
  89                         return 0;
  90                 else
  91                         return EAI_MEMORY;
  92         }
  93         
  94         if (inet_aton(hostname, &in)) {
  95                 if (NULL != (*res = malloc_ai(port, in.s_addr)))
  96                         return 0;
  97                 else
  98                         return EAI_MEMORY;
  99         }
 100         
 101         hp = gethostbyname(hostname);
 102         if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
 103                 for (i = 0; hp->h_addr_list[i]; i++) {
 104                         cur = malloc_ai(port, ((struct in_addr *)hp->h_addr_list[i])->s_addr);
 105                         if (cur == NULL) {
 106                                 if (*res)
 107                                         freeaddrinfo(*res);
 108                                 return EAI_MEMORY;
 109                         }
 110                         
 111                         if (prev)
 112                                 prev->ai_next = cur;
 113                         else
 114                                 *res = cur;
 115 
 116                         prev = cur;
 117                 }
 118                 return 0;
 119         }
 120         
 121         return EAI_NODATA;
 122 }
 123 #endif /* !HAVE_GETADDRINFO */