blob: ca13a40bca1870f04af5358bdc64bd1eca19ee4f [file] [log] [blame]
Damien Miller34132e52000-01-14 15:45:46 +11001/*
Damien Millerc28e38d2003-06-05 18:52:47 +10002 * Pseudo-implementation of RFC2553 name / address resolution functions
Damien Miller34132e52000-01-14 15:45:46 +11003 *
4 * But these functions are not implemented correctly. The minimum subset
5 * is implemented for ssh use only. For exapmle, this routine assumes
6 * that ai_family is AF_INET. Don't use it for another purpose.
Damien Miller34132e52000-01-14 15:45:46 +11007 */
8
Damien Millerc28e38d2003-06-05 18:52:47 +10009RCSID("$Id: fake-rfc2553.c,v 1.1 2003/06/05 08:52:48 djm Exp $");
Damien Miller34132e52000-01-14 15:45:46 +110010
Damien Millerc28e38d2003-06-05 18:52:47 +100011#ifndef HAVE_GETNAMEINFO
12int getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
13 size_t hostlen, char *serv, size_t servlen, int flags)
14{
15 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
16 struct hostent *hp;
17 char tmpserv[16];
18
19 if (serv != NULL) {
20 snprintf(tmpserv, sizeof(tmpserv), "%d", ntohs(sin->sin_port));
21 if (strlcpy(serv, tmpserv, servlen) >= servlen)
22 return (EAI_MEMORY);
23 }
24
25 if (host != NULL) {
26 if (flags & NI_NUMERICHOST) {
27 if (strlcpy(host, inet_ntoa(sin->sin_addr),
28 hostlen) >= hostlen)
29 return (EAI_MEMORY);
30 else
31 return (0);
32 } else {
33 hp = gethostbyaddr((char *)&sin->sin_addr,
34 sizeof(struct in_addr), AF_INET);
35 if (hp == NULL)
36 return (EAI_NODATA);
37
38 if (strlcpy(host, hp->h_name, hostlen) >= hostlen)
39 return (EAI_MEMORY);
40 else
41 return (0);
42 }
43 }
44 return (0);
45}
46#endif /* !HAVE_GETNAMEINFO */
Damien Millere9cf3572001-02-09 12:55:35 +110047
Damien Miller34132e52000-01-14 15:45:46 +110048#ifndef HAVE_GAI_STRERROR
Damien Miller31741252003-05-19 00:13:38 +100049char *
50gai_strerror(int err)
Damien Miller34132e52000-01-14 15:45:46 +110051{
Damien Miller31741252003-05-19 00:13:38 +100052 switch (err) {
53 case EAI_NODATA:
54 return ("no address associated with name");
55 case EAI_MEMORY:
56 return ("memory allocation failure.");
Damien Miller10eac0c2003-06-05 09:48:32 +100057 case EAI_NONAME:
58 return ("nodename nor servname provided, or not known");
Damien Miller31741252003-05-19 00:13:38 +100059 default:
60 return ("unknown/invalid error.");
Damien Miller2f6a0ad2000-05-31 11:20:11 +100061 }
Damien Miller34132e52000-01-14 15:45:46 +110062}
63#endif /* !HAVE_GAI_STRERROR */
64
65#ifndef HAVE_FREEADDRINFO
Damien Miller31741252003-05-19 00:13:38 +100066void
67freeaddrinfo(struct addrinfo *ai)
Damien Miller34132e52000-01-14 15:45:46 +110068{
Damien Miller2f6a0ad2000-05-31 11:20:11 +100069 struct addrinfo *next;
70
Damien Millerc322bba2003-05-19 10:39:37 +100071 for(; ai != NULL;) {
72 next = ai->ai_next;
Damien Miller2f6a0ad2000-05-31 11:20:11 +100073 free(ai);
Damien Miller31741252003-05-19 00:13:38 +100074 ai = next;
75 }
Damien Miller34132e52000-01-14 15:45:46 +110076}
77#endif /* !HAVE_FREEADDRINFO */
78
79#ifndef HAVE_GETADDRINFO
Damien Miller31741252003-05-19 00:13:38 +100080static struct
81addrinfo *malloc_ai(int port, u_long addr, const struct addrinfo *hints)
Damien Miller34132e52000-01-14 15:45:46 +110082{
Damien Miller2f6a0ad2000-05-31 11:20:11 +100083 struct addrinfo *ai;
Damien Miller34132e52000-01-14 15:45:46 +110084
Damien Millerb95bb7f2003-06-05 10:04:12 +100085 ai = malloc(sizeof(*ai) + sizeof(struct sockaddr_in));
86 if (ai == NULL)
87 return (NULL);
Damien Miller2f6a0ad2000-05-31 11:20:11 +100088
Damien Miller31741252003-05-19 00:13:38 +100089 memset(ai, '\0', sizeof(*ai) + sizeof(struct sockaddr_in));
Damien Miller2f6a0ad2000-05-31 11:20:11 +100090
91 ai->ai_addr = (struct sockaddr *)(ai + 1);
92 /* XXX -- ssh doesn't use sa_len */
93 ai->ai_addrlen = sizeof(struct sockaddr_in);
94 ai->ai_addr->sa_family = ai->ai_family = AF_INET;
95
96 ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port;
97 ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr;
98
Darren Tuckerabef5622003-05-14 21:48:51 +100099 /* XXX: the following is not generally correct, but does what we want */
100 if (hints->ai_socktype)
101 ai->ai_socktype = hints->ai_socktype;
102 else
103 ai->ai_socktype = SOCK_STREAM;
104
105 if (hints->ai_protocol)
106 ai->ai_protocol = hints->ai_protocol;
107
Damien Miller31741252003-05-19 00:13:38 +1000108 return (ai);
Damien Miller34132e52000-01-14 15:45:46 +1100109}
110
Damien Miller31741252003-05-19 00:13:38 +1000111int
112getaddrinfo(const char *hostname, const char *servname,
113 const struct addrinfo *hints, struct addrinfo **res)
Damien Miller34132e52000-01-14 15:45:46 +1100114{
Damien Miller2f6a0ad2000-05-31 11:20:11 +1000115 struct hostent *hp;
Damien Miller850b9422003-02-06 10:50:42 +1100116 struct servent *sp;
Damien Miller8e394e72000-07-08 11:50:37 +1000117 struct in_addr in;
Damien Miller850b9422003-02-06 10:50:42 +1100118 int i;
119 long int port;
Damien Miller62b6b172003-03-24 13:35:58 +1100120 u_long addr;
Damien Miller2f6a0ad2000-05-31 11:20:11 +1000121
Damien Miller850b9422003-02-06 10:50:42 +1100122 port = 0;
123 if (servname != NULL) {
124 char *cp;
125
126 port = strtol(servname, &cp, 10);
127 if (port > 0 && port <= 65535 && *cp == '\0')
128 port = htons(port);
129 else if ((sp = getservbyname(servname, NULL)) != NULL)
130 port = sp->s_port;
131 else
132 port = 0;
133 }
Damien Miller2f6a0ad2000-05-31 11:20:11 +1000134
135 if (hints && hints->ai_flags & AI_PASSIVE) {
Damien Miller62b6b172003-03-24 13:35:58 +1100136 addr = htonl(0x00000000);
137 if (hostname && inet_aton(hostname, &in) != 0)
138 addr = in.s_addr;
Damien Miller31741252003-05-19 00:13:38 +1000139 *res = malloc_ai(port, addr, hints);
Damien Millerb95bb7f2003-06-05 10:04:12 +1000140 if (*res == NULL)
141 return (EAI_MEMORY);
Damien Miller31741252003-05-19 00:13:38 +1000142 return (0);
Damien Miller2f6a0ad2000-05-31 11:20:11 +1000143 }
144
145 if (!hostname) {
Damien Miller31741252003-05-19 00:13:38 +1000146 *res = malloc_ai(port, htonl(0x7f000001), hints);
Damien Millerb95bb7f2003-06-05 10:04:12 +1000147 if (*res == NULL)
148 return (EAI_MEMORY);
Damien Miller31741252003-05-19 00:13:38 +1000149 return (0);
Damien Miller2f6a0ad2000-05-31 11:20:11 +1000150 }
151
Damien Miller7a0e5dc2000-07-11 12:15:54 +1000152 if (inet_aton(hostname, &in)) {
Damien Miller31741252003-05-19 00:13:38 +1000153 *res = malloc_ai(port, in.s_addr, hints);
Damien Millerb95bb7f2003-06-05 10:04:12 +1000154 if (*res == NULL)
155 return (EAI_MEMORY);
Damien Miller31741252003-05-19 00:13:38 +1000156 return (0);
Damien Miller2f6a0ad2000-05-31 11:20:11 +1000157 }
158
Damien Miller10eac0c2003-06-05 09:48:32 +1000159 /* Don't try DNS if AI_NUMERICHOST is set */
160 if (hints && hints->ai_flags & AI_NUMERICHOST)
161 return (EAI_NONAME);
162
Damien Miller2f6a0ad2000-05-31 11:20:11 +1000163 hp = gethostbyname(hostname);
164 if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
Damien Miller31741252003-05-19 00:13:38 +1000165 struct addrinfo *cur, *prev;
166
Damien Millerb95bb7f2003-06-05 10:04:12 +1000167 cur = prev = *res = NULL;
Damien Miller2f6a0ad2000-05-31 11:20:11 +1000168 for (i = 0; hp->h_addr_list[i]; i++) {
Damien Miller31741252003-05-19 00:13:38 +1000169 struct in_addr *in = (struct in_addr *)hp->h_addr_list[i];
170
171 cur = malloc_ai(port, in->s_addr, hints);
Damien Millerb95bb7f2003-06-05 10:04:12 +1000172 if (cur == NULL) {
173 if (*res != NULL)
174 freeaddrinfo(*res);
175 return (EAI_MEMORY);
176 }
Damien Miller2f6a0ad2000-05-31 11:20:11 +1000177 if (prev)
178 prev->ai_next = cur;
179 else
180 *res = cur;
181
182 prev = cur;
183 }
Damien Miller31741252003-05-19 00:13:38 +1000184 return (0);
Damien Miller2f6a0ad2000-05-31 11:20:11 +1000185 }
186
Damien Miller31741252003-05-19 00:13:38 +1000187 return (EAI_NODATA);
Damien Miller34132e52000-01-14 15:45:46 +1100188}
189#endif /* !HAVE_GETADDRINFO */