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. */
47 #include <arpa/inet.h>
49 #include <netinet/in.h>
50 #include <sys/param.h>
51 #include <sys/socket.h>
52 #include <sys/types.h>
54 #include <sys/utsname.h>
55 #include <bits/libc-lock.h>
58 # include <libidn/idna.h>
59 extern int __idna_to_unicode_lzlz (const char *input
, char **output
,
64 # define min(x,y) (((x) > (y)) ? (y) : (x))
67 libc_freeres_ptr (static char *domain
);
78 __libc_lock_define_initialized (static, lock
);
79 __libc_lock_lock (lock
);
84 struct hostent
*h
, th
;
85 size_t tmpbuflen
= 1024;
86 char *tmpbuf
= alloca (tmpbuflen
);
91 while (__gethostbyname_r ("localhost", &th
, tmpbuf
, tmpbuflen
, &h
,
94 if (herror
== NETDB_INTERNAL
&& errno
== ERANGE
)
95 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
, 2 * tmpbuflen
);
100 if (h
&& (c
= strchr (h
->h_name
, '.')))
101 domain
= __strdup (++c
);
104 /* The name contains no domain information. Use the name
105 now to get more information. */
106 while (__gethostname (tmpbuf
, tmpbuflen
))
107 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
, 2 * tmpbuflen
);
109 if ((c
= strchr (tmpbuf
, '.')))
110 domain
= __strdup (++c
);
113 /* We need to preserve the hostname. */
114 const char *hstname
= strdupa (tmpbuf
);
116 while (__gethostbyname_r (hstname
, &th
, tmpbuf
, tmpbuflen
,
119 if (herror
== NETDB_INTERNAL
&& errno
== ERANGE
)
120 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
,
126 if (h
&& (c
= strchr(h
->h_name
, '.')))
127 domain
= __strdup (++c
);
130 struct in_addr in_addr
;
132 in_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
134 while (__gethostbyaddr_r ((const char *) &in_addr
,
135 sizeof (struct in_addr
),
136 AF_INET
, &th
, tmpbuf
,
137 tmpbuflen
, &h
, &herror
))
139 if (herror
== NETDB_INTERNAL
&& errno
== ERANGE
)
140 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
,
146 if (h
&& (c
= strchr (h
->h_name
, '.')))
147 domain
= __strdup (++c
);
153 __libc_lock_unlock (lock
);
161 getnameinfo (const struct sockaddr
*sa
, socklen_t addrlen
, char *host
,
162 socklen_t hostlen
, char *serv
, socklen_t servlen
,
166 int tmpbuflen
= 1024;
168 char *tmpbuf
= alloca (tmpbuflen
);
172 if (flags
& ~(NI_NUMERICHOST
|NI_NUMERICSERV
|NI_NOFQDN
|NI_NAMEREQD
|NI_DGRAM
174 |NI_IDN
|NI_IDN_ALLOW_UNASSIGNED
|NI_IDN_USE_STD3_ASCII_RULES
179 if (sa
== NULL
|| addrlen
< sizeof (sa_family_t
))
182 if ((flags
& NI_NAMEREQD
) && host
== NULL
&& serv
== NULL
)
185 switch (sa
->sa_family
)
188 if (addrlen
< (socklen_t
) offsetof (struct sockaddr_un
, sun_path
))
192 if (addrlen
< sizeof (struct sockaddr_in
))
196 if (addrlen
< sizeof (struct sockaddr_in6
))
203 if (host
!= NULL
&& hostlen
> 0)
204 switch (sa
->sa_family
)
208 if (!(flags
& NI_NUMERICHOST
))
210 struct hostent
*h
= NULL
;
211 if (sa
->sa_family
== AF_INET6
)
213 while (__gethostbyaddr_r ((const void *) &(((const struct sockaddr_in6
*) sa
)->sin6_addr
),
214 sizeof(struct in6_addr
),
215 AF_INET6
, &th
, tmpbuf
, tmpbuflen
,
217 if (herrno
== NETDB_INTERNAL
&& errno
== ERANGE
)
218 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
, 2 * tmpbuflen
);
224 while (__gethostbyaddr_r ((const void *) &(((const struct sockaddr_in
*)sa
)->sin_addr
),
225 sizeof(struct in_addr
), AF_INET
,
226 &th
, tmpbuf
, tmpbuflen
,
228 if (herrno
== NETDB_INTERNAL
&& errno
== ERANGE
)
229 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
, 2 * tmpbuflen
);
236 if (herrno
== NETDB_INTERNAL
)
238 __set_h_errno (herrno
);
241 if (herrno
== TRY_AGAIN
)
243 __set_h_errno (herrno
);
251 if ((flags
& NI_NOFQDN
)
252 && (c
= nrl_domainname ())
253 && (c
= strstr (h
->h_name
, c
))
254 && (c
!= h
->h_name
) && (*(--c
) == '.'))
255 /* Terminate the string after the prefix. */
259 /* If requested, convert from the IDN format. */
263 if (flags
& NI_IDN_ALLOW_UNASSIGNED
)
264 idn_flags
|= IDNA_ALLOW_UNASSIGNED
;
265 if (flags
& NI_IDN_USE_STD3_ASCII_RULES
)
266 idn_flags
|= IDNA_USE_STD3_ASCII_RULES
;
269 int rc
= __idna_to_unicode_lzlz (h
->h_name
, &out
,
271 if (rc
!= IDNA_SUCCESS
)
273 if (rc
== IDNA_MALLOC_ERROR
)
275 if (rc
== IDNA_DLOPEN_ERROR
)
277 return EAI_IDN_ENCODE
;
280 if (out
!= h
->h_name
)
282 h
->h_name
= strdupa (out
);
288 size_t len
= strlen (h
->h_name
) + 1;
292 memcpy (host
, h
->h_name
, len
);
300 if (flags
& NI_NAMEREQD
)
302 __set_errno (serrno
);
308 if (sa
->sa_family
== AF_INET6
)
310 const struct sockaddr_in6
*sin6p
;
313 sin6p
= (const struct sockaddr_in6
*) sa
;
315 c
= inet_ntop (AF_INET6
,
316 (const void *) &sin6p
->sin6_addr
, host
, hostlen
);
317 scopeid
= sin6p
->sin6_scope_id
;
320 /* Buffer is >= IFNAMSIZ+1. */
321 char scopebuf
[IFNAMSIZ
+ 1];
323 int ni_numericscope
= 0;
324 size_t real_hostlen
= __strnlen (host
, hostlen
);
327 scopebuf
[0] = SCOPE_DELIMITER
;
329 scopeptr
= &scopebuf
[1];
331 if (IN6_IS_ADDR_LINKLOCAL (&sin6p
->sin6_addr
)
332 || IN6_IS_ADDR_MC_LINKLOCAL (&sin6p
->sin6_addr
))
334 if (if_indextoname (scopeid
, scopeptr
) == NULL
)
337 scopelen
= strlen (scopebuf
);
343 scopelen
= 1 + __snprintf (scopeptr
,
349 if (real_hostlen
+ scopelen
+ 1 > hostlen
)
350 /* Signal the buffer is too small. This is
351 what inet_ntop does. */
354 memcpy (host
+ real_hostlen
, scopebuf
, scopelen
+ 1);
358 c
= inet_ntop (AF_INET
,
359 (const void *) &(((const struct sockaddr_in
*) sa
)->sin_addr
),
369 if (!(flags
& NI_NUMERICHOST
))
371 struct utsname utsname
;
373 if (!uname (&utsname
))
375 strncpy (host
, utsname
.nodename
, hostlen
);
380 if (flags
& NI_NAMEREQD
)
382 __set_errno (serrno
);
386 strncpy (host
, "localhost", hostlen
);
393 if (serv
&& (servlen
> 0))
394 switch (sa
->sa_family
)
398 if (!(flags
& NI_NUMERICSERV
))
400 struct servent
*s
, ts
;
402 while ((e
= __getservbyport_r (((const struct sockaddr_in
*) sa
)->sin_port
,
405 &ts
, tmpbuf
, tmpbuflen
, &s
)))
408 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
, 2 * tmpbuflen
);
414 strncpy (serv
, s
->s_name
, servlen
);
419 if (__snprintf (serv
, servlen
, "%d",
420 ntohs (((const struct sockaddr_in
*) sa
)->sin_port
))
427 strncpy (serv
, ((const struct sockaddr_un
*) sa
)->sun_path
, servlen
);
431 if (host
&& (hostlen
> 0))
433 if (serv
&& (servlen
> 0))
438 libc_hidden_def (getnameinfo
)