2 * These functions are used to avoid sprinkling of ifdefs
6 * Mar 8, 2000 by Hajimu UMEMOTO <ume@mahoroba.org>
8 * This file is based on ssh-1.2.27-IPv6-1.5 written by
9 * KIKUCHI Takahiro <kick@kyoto.wide.ad.jp>
12 * fake library for ssh
14 * This file includes getaddrinfo(), freeaddrinfo(), gai_strerror()
17 * But these functions are not implemented correctly. The minimum subset
18 * is implemented for ssh use only. For exapmle, this routine assumes
19 * that ai_family is AF_INET. Don't use it for another purpose.
21 * In the case not using 'configure --enable-ipv6', this getaddrinfo.c
22 * will be used if you have broken getaddrinfo or no getaddrinfo.
31 #include <sys/types.h>
32 #include <sys/socket.h>
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
36 #include <sys/param.h>
40 #ifndef HAVE_GETADDRINFO
41 static struct addrinfo *
42 malloc_ai(int port, u_long addr, int socktype, int proto)
46 ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) +
47 sizeof(struct sockaddr_in));
49 memset(ai, 0, sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
50 ai->ai_addr = (struct sockaddr *)(ai + 1);
51 ai->ai_addrlen = sizeof(struct sockaddr_in);
52 #ifdef HAVE_SOCKADDR_SA_LEN
53 ai->ai_addr->sa_len = sizeof(struct sockaddr_in);
55 ai->ai_addr->sa_family = ai->ai_family = AF_INET;
56 ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port;
57 ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr;
58 ai->ai_socktype = socktype;
59 ai->ai_protocol = proto;
67 gai_strerror(int ecode)
71 return "memory allocation failure.";
73 return "ai_family not supported.";
75 return "hostname nor servname provided, or not known.";
77 return "servname not supported for ai_socktype.";
79 return "unknown error.";
84 freeaddrinfo(struct addrinfo *ai)
86 struct addrinfo *next;
89 free(ai->ai_canonname);
93 } while ((ai = next) != NULL);
97 getaddrinfo(const char *hostname, const char *servname,
98 const struct addrinfo *hints, struct addrinfo **res)
100 struct addrinfo *cur, *prev = NULL;
103 int i, port = 0, socktype, proto;
105 if (hints && hints->ai_family != PF_INET && hints->ai_family != PF_UNSPEC)
108 socktype = (hints && hints->ai_socktype) ? hints->ai_socktype
110 if (hints && hints->ai_protocol)
111 proto = hints->ai_protocol;
126 if (isdigit((int)*servname))
127 port = htons(atoi(servname));
143 if ((se = getservbyname(servname, pe_proto)) == NULL)
149 if (hints && hints->ai_flags & AI_PASSIVE)
150 *res = malloc_ai(port, htonl(0x00000000), socktype, proto);
152 *res = malloc_ai(port, htonl(0x7f000001), socktype, proto);
158 if (inet_aton(hostname, &in)) {
159 *res = malloc_ai(port, in.s_addr, socktype, proto);
165 if (hints && hints->ai_flags & AI_NUMERICHOST)
167 if ((hp = gethostbyname(hostname)) &&
168 hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
169 for (i = 0; hp->h_addr_list[i]; i++) {
170 if ((cur = malloc_ai(port,
171 ((struct in_addr *)hp->h_addr_list[i])->s_addr,
172 socktype, proto)) == NULL) {
183 if (hints && hints->ai_flags & AI_CANONNAME && *res) {
184 if (((*res)->ai_canonname = strdup(hp->h_name)) == NULL) {
193 #endif /* HAVE_GETADDRINFO */
195 #ifndef HAVE_GETNAMEINFO
197 getnameinfo(const struct sockaddr *sa, socklen_t salen,
198 char *host, size_t hostlen,
199 char *serv, size_t servlen,
202 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
207 snprintf(tmpserv, sizeof(tmpserv), "%d", ntohs(sin->sin_port));
208 if (strlen(tmpserv) > servlen)
211 strcpy(serv, tmpserv);
214 if (flags & NI_NUMERICHOST) {
215 if (flags & NI_NAMEREQD)
217 if (strlen(inet_ntoa(sin->sin_addr)) >= hostlen)
220 strcpy(host, inet_ntoa(sin->sin_addr));
224 hp = gethostbyaddr((char *)&sin->sin_addr,
225 sizeof(struct in_addr), AF_INET);
227 if (strlen(hp->h_name) >= hostlen)
230 strcpy(host, hp->h_name);
233 else if (flags & NI_NAMEREQD)
235 else if (strlen(inet_ntoa(sin->sin_addr)) >= hostlen)
238 strcpy(host, inet_ntoa(sin->sin_addr));
245 #endif /* HAVE_GETNAMEINFO */