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 if ((flags
& NI_NAMEREQD
) && host
== NULL
&& serv
== NULL
)
184 switch (sa
->sa_family
)
187 if (addrlen
< (socklen_t
) offsetof (struct sockaddr_un
, sun_path
))
191 if (addrlen
< sizeof (struct sockaddr_in
))
195 if (addrlen
< sizeof (struct sockaddr_in6
))
202 if (host
!= NULL
&& hostlen
> 0)
203 switch (sa
->sa_family
)
207 if (!(flags
& NI_NUMERICHOST
))
209 struct hostent
*h
= NULL
;
210 if (sa
->sa_family
== AF_INET6
)
212 while (__gethostbyaddr_r ((const void *) &(((const struct sockaddr_in6
*) sa
)->sin6_addr
),
213 sizeof(struct in6_addr
),
214 AF_INET6
, &th
, tmpbuf
, tmpbuflen
,
216 if (herrno
== NETDB_INTERNAL
&& errno
== ERANGE
)
217 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
, 2 * tmpbuflen
);
223 while (__gethostbyaddr_r ((const void *) &(((const struct sockaddr_in
*)sa
)->sin_addr
),
224 sizeof(struct in_addr
), AF_INET
,
225 &th
, tmpbuf
, tmpbuflen
,
227 if (herrno
== NETDB_INTERNAL
&& errno
== ERANGE
)
228 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
, 2 * tmpbuflen
);
235 if (herrno
== NETDB_INTERNAL
)
237 __set_h_errno (herrno
);
240 if (herrno
== TRY_AGAIN
)
242 __set_h_errno (herrno
);
250 if ((flags
& NI_NOFQDN
)
251 && (c
= nrl_domainname ())
252 && (c
= strstr (h
->h_name
, c
))
253 && (c
!= h
->h_name
) && (*(--c
) == '.'))
254 /* Terminate the string after the prefix. */
258 /* If requested, convert from the IDN format. */
262 if (flags
& NI_IDN_ALLOW_UNASSIGNED
)
263 idn_flags
|= IDNA_ALLOW_UNASSIGNED
;
264 if (flags
& NI_IDN_USE_STD3_ASCII_RULES
)
265 idn_flags
|= IDNA_USE_STD3_ASCII_RULES
;
268 int rc
= __idna_to_unicode_lzlz (h
->h_name
, &out
,
270 if (rc
!= IDNA_SUCCESS
)
272 if (rc
== IDNA_MALLOC_ERROR
)
274 if (rc
== IDNA_DLOPEN_ERROR
)
276 return EAI_IDN_ENCODE
;
279 if (out
!= h
->h_name
)
281 h
->h_name
= strdupa (out
);
287 size_t len
= strlen (h
->h_name
) + 1;
291 memcpy (host
, h
->h_name
, len
);
299 if (flags
& NI_NAMEREQD
)
301 __set_errno (serrno
);
307 if (sa
->sa_family
== AF_INET6
)
309 const struct sockaddr_in6
*sin6p
;
312 sin6p
= (const struct sockaddr_in6
*) sa
;
314 c
= inet_ntop (AF_INET6
,
315 (const void *) &sin6p
->sin6_addr
, host
, hostlen
);
316 scopeid
= sin6p
->sin6_scope_id
;
319 /* Buffer is >= IFNAMSIZ+1. */
320 char scopebuf
[IFNAMSIZ
+ 1];
322 int ni_numericscope
= 0;
323 size_t real_hostlen
= __strnlen (host
, hostlen
);
326 scopebuf
[0] = SCOPE_DELIMITER
;
328 scopeptr
= &scopebuf
[1];
330 if (IN6_IS_ADDR_LINKLOCAL (&sin6p
->sin6_addr
)
331 || IN6_IS_ADDR_MC_LINKLOCAL (&sin6p
->sin6_addr
))
333 if (if_indextoname (scopeid
, scopeptr
) == NULL
)
336 scopelen
= strlen (scopebuf
);
342 scopelen
= 1 + __snprintf (scopeptr
,
348 if (real_hostlen
+ scopelen
+ 1 > hostlen
)
349 /* XXX We should not fail here. Simply enlarge
350 the buffer or return with out of memory. */
352 memcpy (host
+ real_hostlen
, scopebuf
, scopelen
+ 1);
356 c
= inet_ntop (AF_INET
,
357 (const void *) &(((const struct sockaddr_in
*) sa
)->sin_addr
),
367 if (!(flags
& NI_NUMERICHOST
))
369 struct utsname utsname
;
371 if (!uname (&utsname
))
373 strncpy (host
, utsname
.nodename
, hostlen
);
378 if (flags
& NI_NAMEREQD
)
380 __set_errno (serrno
);
384 strncpy (host
, "localhost", hostlen
);
391 if (serv
&& (servlen
> 0))
392 switch (sa
->sa_family
)
396 if (!(flags
& NI_NUMERICSERV
))
398 struct servent
*s
, ts
;
400 while ((e
= __getservbyport_r (((const struct sockaddr_in
*) sa
)->sin_port
,
403 &ts
, tmpbuf
, tmpbuflen
, &s
)))
406 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
, 2 * tmpbuflen
);
412 strncpy (serv
, s
->s_name
, servlen
);
417 if (__snprintf (serv
, servlen
, "%d",
418 ntohs (((const struct sockaddr_in
*) sa
)->sin_port
))
425 strncpy (serv
, ((const struct sockaddr_un
*) sa
)->sun_path
, servlen
);
429 if (host
&& (hostlen
> 0))
431 if (serv
&& (servlen
> 0))
436 libc_hidden_def (getnameinfo
)