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. */
46 #include <arpa/inet.h>
48 #include <netinet/in.h>
49 #include <sys/param.h>
50 #include <sys/socket.h>
51 #include <sys/types.h>
53 #include <sys/utsname.h>
54 #include <bits/libc-lock.h>
57 # include <libidn/idna.h>
58 extern int __idna_to_unicode_lzlz (const char *input
, char **output
,
63 # define min(x,y) (((x) > (y)) ? (y) : (x))
66 libc_freeres_ptr (static char *domain
);
77 __libc_lock_define_initialized (static, lock
);
78 __libc_lock_lock (lock
);
83 struct hostent
*h
, th
;
84 size_t tmpbuflen
= 1024;
85 char *tmpbuf
= alloca (tmpbuflen
);
90 while (__gethostbyname_r ("localhost", &th
, tmpbuf
, tmpbuflen
, &h
,
93 if (herror
== NETDB_INTERNAL
&& errno
== ERANGE
)
94 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
, 2 * tmpbuflen
);
99 if (h
&& (c
= strchr (h
->h_name
, '.')))
100 domain
= __strdup (++c
);
103 /* The name contains no domain information. Use the name
104 now to get more information. */
105 while (__gethostname (tmpbuf
, tmpbuflen
))
106 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
, 2 * tmpbuflen
);
108 if ((c
= strchr (tmpbuf
, '.')))
109 domain
= __strdup (++c
);
112 /* We need to preserve the hostname. */
113 const char *hstname
= strdupa (tmpbuf
);
115 while (__gethostbyname_r (hstname
, &th
, tmpbuf
, tmpbuflen
,
118 if (herror
== NETDB_INTERNAL
&& errno
== ERANGE
)
119 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
,
125 if (h
&& (c
= strchr(h
->h_name
, '.')))
126 domain
= __strdup (++c
);
129 struct in_addr in_addr
;
131 in_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
133 while (__gethostbyaddr_r ((const char *) &in_addr
,
134 sizeof (struct in_addr
),
135 AF_INET
, &th
, tmpbuf
,
136 tmpbuflen
, &h
, &herror
))
138 if (herror
== NETDB_INTERNAL
&& errno
== ERANGE
)
139 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
,
145 if (h
&& (c
= strchr (h
->h_name
, '.')))
146 domain
= __strdup (++c
);
152 __libc_lock_unlock (lock
);
160 getnameinfo (const struct sockaddr
*sa
, socklen_t addrlen
, char *host
,
161 socklen_t hostlen
, char *serv
, socklen_t servlen
,
165 int tmpbuflen
= 1024;
167 char *tmpbuf
= alloca (tmpbuflen
);
171 if (flags
& ~(NI_NUMERICHOST
|NI_NUMERICSERV
|NI_NOFQDN
|NI_NAMEREQD
|NI_DGRAM
173 |NI_IDN
|NI_IDN_ALLOW_UNASSIGNED
|NI_IDN_USE_STD3_ASCII_RULES
178 if (sa
== NULL
|| addrlen
< sizeof (sa_family_t
))
181 switch (sa
->sa_family
)
184 if (addrlen
< (socklen_t
) offsetof (struct sockaddr_un
, sun_path
))
188 if (addrlen
< sizeof (struct sockaddr_in
))
192 if (addrlen
< sizeof (struct sockaddr_in6
))
199 if (host
!= NULL
&& hostlen
> 0)
200 switch (sa
->sa_family
)
204 if (!(flags
& NI_NUMERICHOST
))
206 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
,
213 if (herrno
== NETDB_INTERNAL
&& errno
== ERANGE
)
214 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
, 2 * tmpbuflen
);
220 while (__gethostbyaddr_r ((const void *) &(((const struct sockaddr_in
*)sa
)->sin_addr
),
221 sizeof(struct in_addr
), AF_INET
,
222 &th
, tmpbuf
, tmpbuflen
,
224 if (herrno
== NETDB_INTERNAL
&& errno
== ERANGE
)
225 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
, 2 * tmpbuflen
);
232 if (herrno
== NETDB_INTERNAL
)
234 __set_h_errno (herrno
);
237 if (herrno
== TRY_AGAIN
)
239 __set_h_errno (herrno
);
247 if ((flags
& NI_NOFQDN
)
248 && (c
= nrl_domainname ())
249 && (c
= strstr (h
->h_name
, c
))
250 && (c
!= h
->h_name
) && (*(--c
) == '.'))
251 /* Terminate the string after the prefix. */
255 /* If requested, convert from the IDN format. */
259 if (flags
& NI_IDN_ALLOW_UNASSIGNED
)
260 idn_flags
|= IDNA_ALLOW_UNASSIGNED
;
261 if (flags
& NI_IDN_USE_STD3_ASCII_RULES
)
262 idn_flags
|= IDNA_USE_STD3_ASCII_RULES
;
265 int rc
= __idna_to_unicode_lzlz (h
->h_name
, &out
,
267 if (rc
!= IDNA_SUCCESS
)
269 if (rc
== IDNA_MALLOC_ERROR
)
271 if (rc
== IDNA_DLOPEN_ERROR
)
273 return EAI_IDN_ENCODE
;
276 if (out
!= h
->h_name
)
278 h
->h_name
= strdupa (out
);
284 size_t len
= strlen (h
->h_name
) + 1;
288 memcpy (host
, h
->h_name
, len
);
296 if (flags
& NI_NAMEREQD
)
298 __set_errno (serrno
);
304 if (sa
->sa_family
== AF_INET6
)
306 const struct sockaddr_in6
*sin6p
;
309 sin6p
= (const struct sockaddr_in6
*) sa
;
311 c
= inet_ntop (AF_INET6
,
312 (const void *) &sin6p
->sin6_addr
, host
, hostlen
);
313 scopeid
= sin6p
->sin6_scope_id
;
316 /* Buffer is >= IFNAMSIZ+1. */
317 char scopebuf
[IFNAMSIZ
+ 1];
319 int ni_numericscope
= 0;
320 size_t real_hostlen
= __strnlen (host
, hostlen
);
323 scopebuf
[0] = SCOPE_DELIMITER
;
325 scopeptr
= &scopebuf
[1];
327 if (IN6_IS_ADDR_LINKLOCAL (&sin6p
->sin6_addr
)
328 || IN6_IS_ADDR_MC_LINKLOCAL (&sin6p
->sin6_addr
))
330 if (if_indextoname (scopeid
, scopeptr
) == NULL
)
333 scopelen
= strlen (scopebuf
);
339 scopelen
= 1 + __snprintf (scopeptr
,
345 if (real_hostlen
+ scopelen
+ 1 > hostlen
)
346 /* XXX We should not fail here. Simply enlarge
347 the buffer or return with out of memory. */
349 memcpy (host
+ real_hostlen
, scopebuf
, scopelen
+ 1);
353 c
= inet_ntop (AF_INET
,
354 (const void *) &(((const struct sockaddr_in
*) sa
)->sin_addr
),
364 if (!(flags
& NI_NUMERICHOST
))
366 struct utsname utsname
;
368 if (!uname (&utsname
))
370 strncpy (host
, utsname
.nodename
, hostlen
);
375 if (flags
& NI_NAMEREQD
)
377 __set_errno (serrno
);
381 strncpy (host
, "localhost", hostlen
);
388 if (serv
&& (servlen
> 0))
389 switch (sa
->sa_family
)
393 if (!(flags
& NI_NUMERICSERV
))
395 struct servent
*s
, ts
;
397 while ((e
= __getservbyport_r (((const struct sockaddr_in
*) sa
)->sin_port
,
400 &ts
, tmpbuf
, tmpbuflen
, &s
)))
403 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
, 2 * tmpbuflen
);
409 strncpy (serv
, s
->s_name
, servlen
);
414 if (__snprintf (serv
, servlen
, "%d",
415 ntohs (((const struct sockaddr_in
*) sa
)->sin_port
))
422 strncpy (serv
, ((const struct sockaddr_un
*) sa
)->sun_path
, servlen
);
426 if (host
&& (hostlen
> 0))
428 if (serv
&& (servlen
> 0))
433 libc_hidden_def (getnameinfo
)