blob: 7e6044a53899ec31fa2ac8c944d700d29c72ad6f [file] [log] [blame]
Damien Miller34132e52000-01-14 15:45:46 +11001/*
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.
Damien Miller34132e52000-01-14 15:45:46 +110010 */
11
12#include "includes.h"
Damien Miller31741252003-05-19 00:13:38 +100013#include "xmalloc.h"
Damien Miller34132e52000-01-14 15:45:46 +110014#include "ssh.h"
15
Damien Millerc322bba2003-05-19 10:39:37 +100016RCSID("$Id: fake-getaddrinfo.c,v 1.8 2003/05/19 00:39:37 djm Exp $");
Damien Millere9cf3572001-02-09 12:55:35 +110017
Damien Miller34132e52000-01-14 15:45:46 +110018#ifndef HAVE_GAI_STRERROR
Damien Miller31741252003-05-19 00:13:38 +100019char *
20gai_strerror(int err)
Damien Miller34132e52000-01-14 15:45:46 +110021{
Damien Miller31741252003-05-19 00:13:38 +100022 switch (err) {
23 case EAI_NODATA:
24 return ("no address associated with name");
25 case EAI_MEMORY:
26 return ("memory allocation failure.");
27 default:
28 return ("unknown/invalid error.");
Damien Miller2f6a0ad2000-05-31 11:20:11 +100029 }
Damien Miller34132e52000-01-14 15:45:46 +110030}
31#endif /* !HAVE_GAI_STRERROR */
32
33#ifndef HAVE_FREEADDRINFO
Damien Miller31741252003-05-19 00:13:38 +100034void
35freeaddrinfo(struct addrinfo *ai)
Damien Miller34132e52000-01-14 15:45:46 +110036{
Damien Miller2f6a0ad2000-05-31 11:20:11 +100037 struct addrinfo *next;
38
Damien Millerc322bba2003-05-19 10:39:37 +100039 for(; ai != NULL;) {
40 next = ai->ai_next;
Damien Miller2f6a0ad2000-05-31 11:20:11 +100041 free(ai);
Damien Miller31741252003-05-19 00:13:38 +100042 ai = next;
43 }
Damien Miller34132e52000-01-14 15:45:46 +110044}
45#endif /* !HAVE_FREEADDRINFO */
46
47#ifndef HAVE_GETADDRINFO
Damien Miller31741252003-05-19 00:13:38 +100048static struct
49addrinfo *malloc_ai(int port, u_long addr, const struct addrinfo *hints)
Damien Miller34132e52000-01-14 15:45:46 +110050{
Damien Miller2f6a0ad2000-05-31 11:20:11 +100051 struct addrinfo *ai;
Damien Miller34132e52000-01-14 15:45:46 +110052
Damien Miller31741252003-05-19 00:13:38 +100053 ai = xmalloc(sizeof(*ai) + sizeof(struct sockaddr_in));
Damien Miller2f6a0ad2000-05-31 11:20:11 +100054
Damien Miller31741252003-05-19 00:13:38 +100055 memset(ai, '\0', sizeof(*ai) + sizeof(struct sockaddr_in));
Damien Miller2f6a0ad2000-05-31 11:20:11 +100056
57 ai->ai_addr = (struct sockaddr *)(ai + 1);
58 /* XXX -- ssh doesn't use sa_len */
59 ai->ai_addrlen = sizeof(struct sockaddr_in);
60 ai->ai_addr->sa_family = ai->ai_family = AF_INET;
61
62 ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port;
63 ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr;
64
Darren Tuckerabef5622003-05-14 21:48:51 +100065 /* XXX: the following is not generally correct, but does what we want */
66 if (hints->ai_socktype)
67 ai->ai_socktype = hints->ai_socktype;
68 else
69 ai->ai_socktype = SOCK_STREAM;
70
71 if (hints->ai_protocol)
72 ai->ai_protocol = hints->ai_protocol;
73
Damien Miller31741252003-05-19 00:13:38 +100074 return (ai);
Damien Miller34132e52000-01-14 15:45:46 +110075}
76
Damien Miller31741252003-05-19 00:13:38 +100077int
78getaddrinfo(const char *hostname, const char *servname,
79 const struct addrinfo *hints, struct addrinfo **res)
Damien Miller34132e52000-01-14 15:45:46 +110080{
Damien Miller2f6a0ad2000-05-31 11:20:11 +100081 struct hostent *hp;
Damien Miller850b9422003-02-06 10:50:42 +110082 struct servent *sp;
Damien Miller8e394e72000-07-08 11:50:37 +100083 struct in_addr in;
Damien Miller850b9422003-02-06 10:50:42 +110084 int i;
85 long int port;
Damien Miller62b6b172003-03-24 13:35:58 +110086 u_long addr;
Damien Miller2f6a0ad2000-05-31 11:20:11 +100087
Damien Miller850b9422003-02-06 10:50:42 +110088 port = 0;
89 if (servname != NULL) {
90 char *cp;
91
92 port = strtol(servname, &cp, 10);
93 if (port > 0 && port <= 65535 && *cp == '\0')
94 port = htons(port);
95 else if ((sp = getservbyname(servname, NULL)) != NULL)
96 port = sp->s_port;
97 else
98 port = 0;
99 }
Damien Miller2f6a0ad2000-05-31 11:20:11 +1000100
101 if (hints && hints->ai_flags & AI_PASSIVE) {
Damien Miller62b6b172003-03-24 13:35:58 +1100102 addr = htonl(0x00000000);
103 if (hostname && inet_aton(hostname, &in) != 0)
104 addr = in.s_addr;
Damien Miller31741252003-05-19 00:13:38 +1000105 *res = malloc_ai(port, addr, hints);
106 return (0);
Damien Miller2f6a0ad2000-05-31 11:20:11 +1000107 }
108
109 if (!hostname) {
Damien Miller31741252003-05-19 00:13:38 +1000110 *res = malloc_ai(port, htonl(0x7f000001), hints);
111 return (0);
Damien Miller2f6a0ad2000-05-31 11:20:11 +1000112 }
113
Damien Miller7a0e5dc2000-07-11 12:15:54 +1000114 if (inet_aton(hostname, &in)) {
Damien Miller31741252003-05-19 00:13:38 +1000115 *res = malloc_ai(port, in.s_addr, hints);
116 return (0);
Damien Miller2f6a0ad2000-05-31 11:20:11 +1000117 }
118
119 hp = gethostbyname(hostname);
120 if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
Damien Miller31741252003-05-19 00:13:38 +1000121 struct addrinfo *cur, *prev;
122
123 cur = prev = NULL;
Damien Miller2f6a0ad2000-05-31 11:20:11 +1000124 for (i = 0; hp->h_addr_list[i]; i++) {
Damien Miller31741252003-05-19 00:13:38 +1000125 struct in_addr *in = (struct in_addr *)hp->h_addr_list[i];
126
127 cur = malloc_ai(port, in->s_addr, hints);
Damien Miller2f6a0ad2000-05-31 11:20:11 +1000128 if (prev)
129 prev->ai_next = cur;
130 else
131 *res = cur;
132
133 prev = cur;
134 }
Damien Miller31741252003-05-19 00:13:38 +1000135 return (0);
Damien Miller2f6a0ad2000-05-31 11:20:11 +1000136 }
137
Damien Miller31741252003-05-19 00:13:38 +1000138 return (EAI_NODATA);
Damien Miller34132e52000-01-14 15:45:46 +1100139}
140#endif /* !HAVE_GETADDRINFO */