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. */
45 #include <arpa/inet.h>
47 #include <netinet/in.h>
48 #include <sys/param.h>
49 #include <sys/socket.h>
50 #include <sys/types.h>
52 #include <sys/utsname.h>
53 #include <bits/libc-lock.h>
56 # include <libidn/idna.h>
57 extern int __idna_to_unicode_lzlz (const char *input
, char **output
,
62 # define min(x,y) (((x) > (y)) ? (y) : (x))
65 libc_freeres_ptr (static char *domain
);
76 __libc_lock_define_initialized (static, lock
);
77 __libc_lock_lock (lock
);
82 struct hostent
*h
, th
;
83 size_t tmpbuflen
= 1024;
84 char *tmpbuf
= alloca (tmpbuflen
);
89 while (__gethostbyname_r ("localhost", &th
, tmpbuf
, tmpbuflen
, &h
,
92 if (herror
== NETDB_INTERNAL
&& errno
== ERANGE
)
93 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
, 2 * tmpbuflen
);
98 if (h
&& (c
= strchr (h
->h_name
, '.')))
99 domain
= __strdup (++c
);
102 /* The name contains no domain information. Use the name
103 now to get more information. */
104 while (__gethostname (tmpbuf
, tmpbuflen
))
105 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
, 2 * tmpbuflen
);
107 if ((c
= strchr (tmpbuf
, '.')))
108 domain
= __strdup (++c
);
111 /* We need to preserve the hostname. */
112 const char *hstname
= strdupa (tmpbuf
);
114 while (__gethostbyname_r (hstname
, &th
, tmpbuf
, tmpbuflen
,
117 if (herror
== NETDB_INTERNAL
&& errno
== ERANGE
)
118 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
,
124 if (h
&& (c
= strchr(h
->h_name
, '.')))
125 domain
= __strdup (++c
);
128 struct in_addr in_addr
;
130 in_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
132 while (__gethostbyaddr_r ((const char *) &in_addr
,
133 sizeof (struct in_addr
),
134 AF_INET
, &th
, tmpbuf
,
135 tmpbuflen
, &h
, &herror
))
137 if (herror
== NETDB_INTERNAL
&& errno
== ERANGE
)
138 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
,
144 if (h
&& (c
= strchr (h
->h_name
, '.')))
145 domain
= __strdup (++c
);
151 __libc_lock_unlock (lock
);
159 getnameinfo (const struct sockaddr
*sa
, socklen_t addrlen
, char *host
,
160 socklen_t hostlen
, char *serv
, socklen_t servlen
,
164 int tmpbuflen
= 1024;
166 char *tmpbuf
= alloca (tmpbuflen
);
170 if (flags
& ~(NI_NUMERICHOST
|NI_NUMERICSERV
|NI_NOFQDN
|NI_NAMEREQD
|NI_DGRAM
172 |NI_IDN
|NI_IDN_ALLOW_UNASSIGNED
|NI_IDN_USE_STD3_ASCII_RULES
177 if (sa
== NULL
|| addrlen
< sizeof (sa_family_t
))
180 switch (sa
->sa_family
)
183 if (addrlen
< (socklen_t
) (((struct sockaddr_un
*) NULL
)->sun_path
))
187 if (addrlen
< sizeof (struct sockaddr_in
))
191 if (addrlen
< sizeof (struct sockaddr_in6
))
198 if (host
!= NULL
&& hostlen
> 0)
199 switch (sa
->sa_family
)
203 if (!(flags
& NI_NUMERICHOST
))
205 struct hostent
*h
= NULL
;
208 if (sa
->sa_family
== AF_INET6
)
210 while (__gethostbyaddr_r ((const void *) &(((const struct sockaddr_in6
*) sa
)->sin6_addr
),
211 sizeof(struct in6_addr
),
212 AF_INET6
, &th
, tmpbuf
, tmpbuflen
,
215 if (herrno
== NETDB_INTERNAL
)
218 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
,
222 __set_h_errno (herrno
);
223 __set_errno (serrno
);
235 while (__gethostbyaddr_r ((const void *) &(((const struct sockaddr_in
*)sa
)->sin_addr
),
236 sizeof(struct in_addr
), AF_INET
,
237 &th
, tmpbuf
, tmpbuflen
,
241 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
,
254 if ((flags
& NI_NOFQDN
)
255 && (c
= nrl_domainname ())
256 && (c
= strstr (h
->h_name
, c
))
257 && (c
!= h
->h_name
) && (*(--c
) == '.'))
258 /* Terminate the string after the prefix. */
262 /* If requested, convert from the IDN format. */
266 if (flags
& NI_IDN_ALLOW_UNASSIGNED
)
267 idn_flags
|= IDNA_ALLOW_UNASSIGNED
;
268 if (flags
& NI_IDN_USE_STD3_ASCII_RULES
)
269 idn_flags
|= IDNA_USE_STD3_ASCII_RULES
;
272 int rc
= __idna_to_unicode_lzlz (h
->h_name
, &out
,
274 if (rc
!= IDNA_SUCCESS
)
276 if (rc
== IDNA_MALLOC_ERROR
)
278 if (rc
== IDNA_DLOPEN_ERROR
)
280 return EAI_IDN_ENCODE
;
283 if (out
!= h
->h_name
)
285 h
->h_name
= strdupa (out
);
291 size_t len
= strlen (h
->h_name
) + 1;
295 memcpy (host
, h
->h_name
, len
);
303 if (flags
& NI_NAMEREQD
)
305 __set_errno (serrno
);
311 if (sa
->sa_family
== AF_INET6
)
313 const struct sockaddr_in6
*sin6p
;
316 sin6p
= (const struct sockaddr_in6
*) sa
;
318 c
= inet_ntop (AF_INET6
,
319 (const void *) &sin6p
->sin6_addr
, host
, hostlen
);
320 scopeid
= sin6p
->sin6_scope_id
;
323 /* Buffer is >= IFNAMSIZ+1. */
324 char scopebuf
[IFNAMSIZ
+ 1];
326 int ni_numericscope
= 0;
327 size_t real_hostlen
= __strnlen (host
, hostlen
);
330 scopebuf
[0] = SCOPE_DELIMITER
;
332 scopeptr
= &scopebuf
[1];
334 if (IN6_IS_ADDR_LINKLOCAL (&sin6p
->sin6_addr
)
335 || IN6_IS_ADDR_MC_LINKLOCAL (&sin6p
->sin6_addr
))
337 if (if_indextoname (scopeid
, scopeptr
) == NULL
)
340 scopelen
= strlen (scopebuf
);
346 scopelen
= 1 + __snprintf (scopeptr
,
352 if (real_hostlen
+ scopelen
+ 1 > hostlen
)
353 /* XXX We should not fail here. Simply enlarge
354 the buffer or return with out of memory. */
356 memcpy (host
+ real_hostlen
, scopebuf
, scopelen
+ 1);
360 c
= inet_ntop (AF_INET
,
361 (const void *) &(((const struct sockaddr_in
*) sa
)->sin_addr
),
365 __set_errno (serrno
);
374 if (!(flags
& NI_NUMERICHOST
))
376 struct utsname utsname
;
378 if (!uname (&utsname
))
380 strncpy (host
, utsname
.nodename
, hostlen
);
385 if (flags
& NI_NAMEREQD
)
387 __set_errno (serrno
);
391 strncpy (host
, "localhost", hostlen
);
398 if (serv
&& (servlen
> 0))
399 switch (sa
->sa_family
)
403 if (!(flags
& NI_NUMERICSERV
))
405 struct servent
*s
, ts
;
407 while ((e
= __getservbyport_r (((const struct sockaddr_in
*) sa
)->sin_port
,
410 &ts
, tmpbuf
, tmpbuflen
, &s
)))
413 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
, 2 * tmpbuflen
);
419 strncpy (serv
, s
->s_name
, servlen
);
424 if (__snprintf (serv
, servlen
, "%d",
425 ntohs (((const struct sockaddr_in
*) sa
)->sin_port
))
432 strncpy (serv
, ((const struct sockaddr_un
*) sa
)->sun_path
, servlen
);
436 if (host
&& (hostlen
> 0))
438 if (serv
&& (servlen
> 0))
443 libc_hidden_def (getnameinfo
)