1 /* The Inner Net License, Version 2.00
3 The author(s) grant permission for redistribution and use in source and
4 binary forms, with or without modification, of the software and documentation
5 provided that the following conditions are met:
7 0. If you receive a version of the software that is specifically labelled
8 as not being for redistribution (check the version message and/or README),
9 you are not permitted to redistribute that version of the software in any
11 1. All terms of the all other applicable copyrights and licenses must be
13 2. Redistributions of source code must retain the authors' copyright
14 notice(s), this list of conditions, and the following disclaimer.
15 3. Redistributions in binary form must reproduce the authors' copyright
16 notice(s), this list of conditions, and the following disclaimer in the
17 documentation and/or other materials provided with the distribution.
18 4. [The copyright holder has authorized the removal of this clause.]
19 5. Neither the name(s) of the author(s) nor the names of its contributors
20 may be used to endorse or promote products derived from this software
21 without specific prior written permission.
23 THIS SOFTWARE IS PROVIDED BY ITS AUTHORS AND CONTRIBUTORS ``AS IS'' AND ANY
24 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY
27 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
30 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 If these license terms cause you a real problem, contact the author. */
36 /* This software is Copyright 1996 by Craig Metz, All Rights Reserved. */
44 #include <arpa/inet.h>
46 #include <netinet/in.h>
47 #include <sys/param.h>
48 #include <sys/socket.h>
49 #include <sys/types.h>
51 #include <sys/utsname.h>
52 #include <bits/libc-lock.h>
55 # include <libidn/idna.h>
56 extern int __idna_to_unicode_lzlz (const char *input, char **output,
61 # define min(x,y) (((x) > (y)) ? (y) : (x))
64 libc_freeres_ptr (static char *domain);
75 __libc_lock_define_initialized (static, lock);
76 __libc_lock_lock (lock);
81 struct hostent *h, th;
82 size_t tmpbuflen = 1024;
83 char *tmpbuf = alloca (tmpbuflen);
88 while (__gethostbyname_r ("localhost", &th, tmpbuf, tmpbuflen, &h,
91 if (herror == NETDB_INTERNAL && errno == ERANGE)
92 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);
97 if (h && (c = strchr (h->h_name, '.')))
98 domain = __strdup (++c);
101 /* The name contains no domain information. Use the name
102 now to get more information. */
103 while (__gethostname (tmpbuf, tmpbuflen))
104 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);
106 if ((c = strchr (tmpbuf, '.')))
107 domain = __strdup (++c);
110 /* We need to preserve the hostname. */
111 const char *hstname = strdupa (tmpbuf);
113 while (__gethostbyname_r (hstname, &th, tmpbuf, tmpbuflen,
116 if (herror == NETDB_INTERNAL && errno == ERANGE)
117 tmpbuf = extend_alloca (tmpbuf, tmpbuflen,
123 if (h && (c = strchr(h->h_name, '.')))
124 domain = __strdup (++c);
127 struct in_addr in_addr;
129 in_addr.s_addr = htonl (INADDR_LOOPBACK);
131 while (__gethostbyaddr_r ((const char *) &in_addr,
132 sizeof (struct in_addr),
133 AF_INET, &th, tmpbuf,
134 tmpbuflen, &h, &herror))
136 if (herror == NETDB_INTERNAL && errno == ERANGE)
137 tmpbuf = extend_alloca (tmpbuf, tmpbuflen,
143 if (h && (c = strchr (h->h_name, '.')))
144 domain = __strdup (++c);
150 __libc_lock_unlock (lock);
158 getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host,
159 socklen_t hostlen, char *serv, socklen_t servlen,
163 int tmpbuflen = 1024;
165 char *tmpbuf = alloca (tmpbuflen);
169 if (flags & ~(NI_NUMERICHOST|NI_NUMERICSERV|NI_NOFQDN|NI_NAMEREQD|NI_DGRAM
176 if (sa == NULL || addrlen < sizeof (sa_family_t))
179 switch (sa->sa_family)
182 if (addrlen < (socklen_t) (((struct sockaddr_un *) NULL)->sun_path))
186 if (addrlen < sizeof (struct sockaddr_in))
190 if (addrlen < sizeof (struct sockaddr_in6))
197 if (host != NULL && hostlen > 0)
198 switch (sa->sa_family)
202 if (!(flags & NI_NUMERICHOST))
204 struct hostent *h = NULL;
207 if (sa->sa_family == AF_INET6)
209 while (__gethostbyaddr_r ((const void *) &(((const struct sockaddr_in6 *) sa)->sin6_addr),
210 sizeof(struct in6_addr),
211 AF_INET6, &th, tmpbuf, tmpbuflen,
214 if (herrno == NETDB_INTERNAL)
217 tmpbuf = extend_alloca (tmpbuf, tmpbuflen,
221 __set_h_errno (herrno);
222 __set_errno (serrno);
234 while (__gethostbyaddr_r ((const void *) &(((const struct sockaddr_in *)sa)->sin_addr),
235 sizeof(struct in_addr), AF_INET,
236 &th, tmpbuf, tmpbuflen,
240 tmpbuf = extend_alloca (tmpbuf, tmpbuflen,
253 if ((flags & NI_NOFQDN)
254 && (c = nrl_domainname ())
255 && (c = strstr (h->h_name, c))
256 && (c != h->h_name) && (*(--c) == '.'))
257 /* Terminate the string after the prefix. */
261 /* If requested, convert from the IDN format. */
265 int rc = __idna_to_unicode_lzlz (h->h_name, &out, 0);
266 if (rc != IDNA_SUCCESS)
268 if (rc == IDNA_MALLOC_ERROR)
270 if (rc == IDNA_DLOPEN_ERROR)
272 return EAI_IDN_ENCODE;
275 if (out != h->h_name)
277 h->h_name = strdupa (out);
283 size_t len = strlen (h->h_name) + 1;
287 memcpy (host, h->h_name, len);
295 if (flags & NI_NAMEREQD)
297 __set_errno (serrno);
303 if (sa->sa_family == AF_INET6)
305 const struct sockaddr_in6 *sin6p;
308 sin6p = (const struct sockaddr_in6 *) sa;
310 c = inet_ntop (AF_INET6,
311 (const void *) &sin6p->sin6_addr, host, hostlen);
312 scopeid = sin6p->sin6_scope_id;
315 /* Buffer is >= IFNAMSIZ+1. */
316 char scopebuf[IFNAMSIZ + 1];
318 int ni_numericscope = 0;
319 size_t real_hostlen = __strnlen (host, hostlen);
322 scopebuf[0] = SCOPE_DELIMITER;
324 scopeptr = &scopebuf[1];
326 if (IN6_IS_ADDR_LINKLOCAL (&sin6p->sin6_addr)
327 || IN6_IS_ADDR_MC_LINKLOCAL (&sin6p->sin6_addr))
329 if (if_indextoname (scopeid, scopeptr) == NULL)
332 scopelen = strlen (scopebuf);
338 scopelen = 1 + __snprintf (scopeptr,
344 if (real_hostlen + scopelen + 1 > hostlen)
345 /* XXX We should not fail here. Simply enlarge
346 the buffer or return with out of memory. */
348 memcpy (host + real_hostlen, scopebuf, scopelen + 1);
352 c = inet_ntop (AF_INET,
353 (const void *) &(((const struct sockaddr_in *) sa)->sin_addr),
357 __set_errno (serrno);
366 if (!(flags & NI_NUMERICHOST))
368 struct utsname utsname;
370 if (!uname (&utsname))
372 strncpy (host, utsname.nodename, hostlen);
377 if (flags & NI_NAMEREQD)
379 __set_errno (serrno);
383 strncpy (host, "localhost", hostlen);
390 if (serv && (servlen > 0))
391 switch (sa->sa_family)
395 if (!(flags & NI_NUMERICSERV))
397 struct servent *s, ts;
398 while (__getservbyport_r (((const struct sockaddr_in *) sa)->sin_port,
399 ((flags & NI_DGRAM) ? "udp" : "tcp"),
400 &ts, tmpbuf, tmpbuflen, &s))
402 if (herrno == NETDB_INTERNAL)
405 tmpbuf = extend_alloca (tmpbuf, tmpbuflen,
409 __set_errno (serrno);
420 strncpy (serv, s->s_name, servlen);
425 if (__snprintf (serv, servlen, "%d",
426 ntohs (((const struct sockaddr_in *) sa)->sin_port))
433 strncpy (serv, ((const struct sockaddr_un *) sa)->sun_path, servlen);
437 if (host && (hostlen > 0))
439 if (serv && (servlen > 0))
444 libc_hidden_def (getnameinfo)