1 /* $NetBSD: resolver.c,v 1.4 2014/12/10 04:37:56 christos Exp $ */
4 static char *rcsid
= "Id: resolver.c,v 1.1 2003/06/04 00:27:12 marka Exp ";
8 * Copyright (c) 2001 Japan Network Information Center. All rights reserved.
10 * By using this file, you agree to the terms and conditions set forth bellow.
12 * LICENSE TERMS AND CONDITIONS
14 * The following License Terms and Conditions apply, unless a different
15 * license is obtained from Japan Network Information Center ("JPNIC"),
16 * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
17 * Chiyoda-ku, Tokyo 101-0047, Japan.
19 * 1. Use, Modification and Redistribution (including distribution of any
20 * modified or derived work) in source and/or binary forms is permitted
21 * under this License Terms and Conditions.
23 * 2. Redistribution of source code must retain the copyright notices as they
24 * appear in each source code file, this License Terms and Conditions.
26 * 3. Redistribution in binary form must reproduce the Copyright Notice,
27 * this License Terms and Conditions, in the documentation and/or other
28 * materials provided with the distribution. For the purposes of binary
29 * distribution the "Copyright Notice" refers to the following language:
30 * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
32 * 4. The name of JPNIC may not be used to endorse or promote products
33 * derived from this Software without specific prior written approval of
36 * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
37 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
38 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
39 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
40 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
41 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
42 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
46 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
56 #include <sys/types.h>
57 #include <sys/socket.h>
63 #include <idn/logmacro.h>
64 #include <idn/debug.h>
68 * This file is specially compiled for runidn.
69 * runidn replaces existing resolver functions dynamically with ones
70 * with IDN processing (encoding conversion and normalization).
71 * So entry names must be same as the system's one.
75 #define ENTRY(name) name
76 #define REAL(name) idn_stub_ ## name
79 * For normal use. All the entry names are prefixed with "idn_resolver_".
80 * <idn/resolver.h> has bunch of #defines to substitute the standard
81 * name resolver functions with ones provided here.
87 #undef gethostbyname_r
88 #undef gethostbyname2_r
89 #undef gethostbyaddr_r
90 #undef getipnodebyname
91 #undef getipnodebyaddr
95 #define ENTRY(name) idn_resolver_ ## name
96 #define REAL(name) name
99 #define IDN_NAME_SIZE 512
101 #define IDN_HOSTBUF_SIZE 2048
103 char *dummy_for_alignment
;
104 char data
[IDN_HOSTBUF_SIZE
];
107 typedef struct obj_lock
{
109 struct obj_lock
*next
;
112 #define OBJLOCKHASH_SIZE 127
113 static obj_lock_t
*obj_lock_hash
[OBJLOCKHASH_SIZE
];
116 * This variable is to prevent IDN processing occuring more than once for
117 * a single name resolution. This will happen if some resolver function
118 * is implemented using another function (e.g. gethostbyname() implemented
119 * using gethostbyname2()).
120 * No, using the static variable is not a correct thing to do for a multi-
121 * threading environment, but I don't think of a better solution..
123 static int idn_isprocessing
= 0;
125 static int obj_hash(void *key
);
126 static int obj_islocked(void *key
);
127 static void obj_lock(void *key
);
128 static void obj_unlock(void *key
);
129 static struct hostent
*copy_decode_hostent_static(struct hostent
*hp
,
130 struct hostent
*newhp
,
131 char *buf
, size_t buflen
,
133 static char *decode_name_dynamic(const char *name
);
134 static struct hostent
*copy_decode_hostent_dynamic(struct hostent
*hp
,
136 static void free_copied_hostent(struct hostent
*hp
);
137 #ifdef HAVE_GETADDRINFO
138 static struct addrinfo
*copy_decode_addrinfo_dynamic(struct addrinfo
*aip
);
140 #ifdef HAVE_FREEADDRINFO
141 static void free_copied_addrinfo(struct addrinfo
*aip
);
145 * Object locking facility.
149 obj_hash(void *key
) {
151 * Hash function for obj_*.
152 * 'key' is supposed to be an address.
154 unsigned long v
= (unsigned long)key
;
156 return ((v
>> 3) % OBJLOCKHASH_SIZE
);
160 obj_islocked(void *key
)
163 * Check if the object specified by 'key' is locked.
164 * Return 1 if so, 0 otherwise.
166 int h
= obj_hash(key
);
167 obj_lock_t
*olp
= obj_lock_hash
[h
];
169 while (olp
!= NULL
) {
181 * Lock an object specified by 'key'.
183 int h
= obj_hash(key
);
186 olp
= malloc(sizeof(obj_lock_t
));
189 olp
->next
= obj_lock_hash
[h
];
190 obj_lock_hash
[h
] = olp
;
195 obj_unlock(void *key
)
198 * Unlock an object specified by 'key'.
200 int h
= obj_hash(key
);
201 obj_lock_t
*olp
, *olp0
;
203 olp
= obj_lock_hash
[h
];
205 while (olp
!= NULL
) {
206 if (olp
->key
== key
) {
208 obj_lock_hash
[h
] = olp
->next
;
210 olp0
->next
= olp
->next
;
219 static struct hostent
*
220 copy_decode_hostent_static(struct hostent
*hp
, struct hostent
*newhp
,
221 char *buf
, size_t buflen
, int *errp
)
224 * Copy "struct hostent" data referenced by 'hp' to 'newhp'.
225 * It's a deep-copy, meaning all the data referenced by 'hp' are
226 * also copied. They are copied into 'buf', whose length is 'buflen'.
227 * The domain names ('hp->h_name' and 'hp->h_aliases') are
228 * decoded from ACE to the local encoding before they are copied.
229 * If 'buf' is too small to hold all the data, NULL will be
230 * returned and '*errp' is set to NO_RECOVERY.
240 if (hp
->h_aliases
!= NULL
) {
242 * Allocate aliase table in 'buf'.
246 while (hp
->h_aliases
[naliases
] != NULL
)
249 newhp
->h_aliases
= (char **)buf
;
250 sz
= sizeof(char *) * (naliases
+ 1);
259 if (hp
->h_addr_list
!= NULL
) {
261 * Allocate address table in 'buf'.
266 while (hp
->h_addr_list
[naddrs
] != NULL
)
269 newhp
->h_addr_list
= (char **)buf
;
270 sz
= sizeof(char *) * (naddrs
+ 1);
279 * Copy the addresses.
281 sz
= hp
->h_length
* naddrs
;
285 for (i
= 0; i
< naddrs
; i
++) {
286 newhp
->h_addr_list
[i
] = buf
;
287 memcpy(buf
, hp
->h_addr_list
[i
], hp
->h_length
);
290 newhp
->h_addr_list
[naddrs
] = NULL
;
296 if (hp
->h_name
!= NULL
) {
298 * Decode the name in h_name.
305 r
= idn_decodename(IDN_DECODE_APP
, hp
->h_name
,
312 /* Copy hp->h_name verbatim. */
313 if (strlen(hp
->h_name
) + 1 <= buflen
) {
315 strcpy(buf
, hp
->h_name
);
319 case idn_buffer_overflow
:
323 slen
= strlen(buf
) + 1;
328 if (hp
->h_aliases
!= NULL
) {
330 * Decode the names in h_aliases.
332 char **aliases
= hp
->h_aliases
;
333 char **newaliases
= newhp
->h_aliases
;
336 for (i
= 0; i
< naliases
; i
++) {
342 r
= idn_decodename(IDN_DECODE_APP
, aliases
[i
],
350 /* Copy hp->h_name verbatim. */
351 if (strlen(aliases
[i
]) + 1 <= buflen
) {
353 strcpy(buf
, aliases
[i
]);
357 case idn_buffer_overflow
:
361 slen
= strlen(buf
) + 1;
365 newaliases
[naliases
] = NULL
;
376 decode_name_dynamic(const char *name
) {
378 char buf
[IDN_NAME_SIZE
];
383 r
= idn_decodename(IDN_DECODE_APP
, name
, buf
, sizeof(buf
));
384 if (r
== idn_success
) {
387 s
= malloc(strlen(name
) + 1);
391 return (strcpy(s
, name
));
394 static struct hostent
*
395 copy_decode_hostent_dynamic(struct hostent
*hp
, int *errp
) {
397 * Make a deep-copy of the data referenced by 'hp', and return
398 * a pointer to the copied data.
399 * All the data are dynamically allocated using malloc().
400 * The domain names ('hp->h_name' and 'hp->h_aliases') are
401 * decoded from ACE to the local encoding before they are copied.
402 * If malloc() fails, NULL will be returned and '*errp' is set to
405 struct hostent
*newhp
;
415 if (hp
->h_aliases
!= NULL
) {
416 while (hp
->h_aliases
[naliases
] != NULL
)
420 if (hp
->h_addr_list
!= NULL
) {
421 while (hp
->h_addr_list
[naddrs
] != NULL
)
425 alloc_size
= sizeof(struct hostent
) +
426 sizeof(char *) * (naliases
+ 1) +
427 sizeof(char *) * (naddrs
+ 1) +
428 hp
->h_length
* naddrs
;
430 if ((newhp
= malloc(alloc_size
)) == NULL
) {
434 memset(newhp
, 0, alloc_size
);
436 pp
= (char **)(newhp
+ 1);
438 if (hp
->h_name
!= NULL
) {
439 newhp
->h_name
= decode_name_dynamic(hp
->h_name
);
440 if (newhp
->h_name
== NULL
)
444 newhp
->h_addrtype
= hp
->h_addrtype
;
445 newhp
->h_length
= hp
->h_length
;
447 if (hp
->h_aliases
!= NULL
) {
448 newhp
->h_aliases
= pp
;
449 for (i
= 0; i
< naliases
; i
++) {
450 newhp
->h_aliases
[i
] =
451 decode_name_dynamic(hp
->h_aliases
[i
]);
452 if (newhp
->h_aliases
[i
] == NULL
)
455 newhp
->h_aliases
[naliases
] = NULL
;
459 if (hp
->h_addr_list
!= NULL
) {
462 newhp
->h_addr_list
= pp
;
466 for (i
= 0; i
< naddrs
; i
++) {
467 newhp
->h_addr_list
[i
] = p
;
468 memcpy(p
, hp
->h_addr_list
[i
], hp
->h_length
);
471 newhp
->h_addr_list
[naddrs
] = NULL
;
477 free_copied_hostent(hp
);
483 free_copied_hostent(struct hostent
*hp
) {
485 * Free all the memory allocated by copy_decode_hostent_dynamic().
487 if (hp
->h_name
!= NULL
)
489 if (hp
->h_aliases
!= NULL
) {
490 char **pp
= hp
->h_aliases
;
497 #ifdef HAVE_GETNAMEINFO
498 static struct addrinfo
*
499 copy_decode_addrinfo_dynamic(struct addrinfo
*aip
) {
500 struct addrinfo
*newaip
;
505 newaip
= malloc(sizeof(struct addrinfo
) + aip
->ai_addrlen
);
510 newaip
->ai_addr
= (struct sockaddr
*)(newaip
+ 1);
511 memcpy(newaip
->ai_addr
, aip
->ai_addr
, aip
->ai_addrlen
);
513 if (newaip
->ai_canonname
!= NULL
)
514 newaip
->ai_canonname
= decode_name_dynamic(aip
->ai_canonname
);
516 newaip
->ai_next
= copy_decode_addrinfo_dynamic(aip
->ai_next
);
521 #ifdef HAVE_FREEADDRINFO
523 free_copied_addrinfo(struct addrinfo
*aip
) {
524 while (aip
!= NULL
) {
525 struct addrinfo
*next
= aip
->ai_next
;
527 if (aip
->ai_canonname
!= NULL
)
528 free(aip
->ai_canonname
);
535 #ifdef HAVE_GETHOSTBYNAME
537 ENTRY(gethostbyname
)(const char *name
) {
538 static hostbuf_t buf
;
539 static struct hostent he
;
543 if (idn_isprocessing
)
544 return (REAL(gethostbyname
)(name
));
546 TRACE(("gethostbyname(name=%s)\n", idn__debug_xstring(name
, 60)));
548 idn_isprocessing
= 1;
551 r
= idn_encodename(IDN_ENCODE_APP
, name
, buf
.data
, sizeof(buf
));
552 if (r
== idn_success
)
555 hp
= copy_decode_hostent_static(REAL(gethostbyname
)(name
),
556 &he
, buf
.data
, sizeof(buf
),
558 idn_isprocessing
= 0;
563 #ifdef HAVE_GETHOSTBYNAME2
565 ENTRY(gethostbyname2
)(const char *name
, int af
) {
566 static hostbuf_t buf
;
567 static struct hostent he
;
571 if (idn_isprocessing
)
572 return (REAL(gethostbyname2
)(name
, af
));
574 TRACE(("gethostbyname2(name=%s)\n", idn__debug_xstring(name
, 60), af
));
576 idn_isprocessing
= 1;
579 r
= idn_encodename(IDN_ENCODE_APP
, name
, buf
.data
, sizeof(buf
));
580 if (r
== idn_success
)
583 hp
= copy_decode_hostent_static(REAL(gethostbyname2
)(name
, af
),
584 &he
, buf
.data
, sizeof(buf
),
586 idn_isprocessing
= 0;
591 #ifdef HAVE_GETHOSTBYADDR
593 ENTRY(gethostbyaddr
)(GHBA_ADDR_T addr
, GHBA_ADDRLEN_T len
, int type
) {
594 static hostbuf_t buf
;
595 static struct hostent he
;
598 if (idn_isprocessing
)
599 return (REAL(gethostbyaddr
)(addr
, len
, type
));
601 TRACE(("gethostbyaddr()\n"));
603 idn_isprocessing
= 1;
604 hp
= copy_decode_hostent_static(REAL(gethostbyaddr
)(addr
, len
, type
),
605 &he
, buf
.data
, sizeof(buf
),
607 idn_isprocessing
= 0;
612 #ifdef GETHOST_R_GLIBC_FLAVOR
614 #ifdef HAVE_GETHOSTBYNAME_R
616 ENTRY(gethostbyname_r
)(const char *name
, struct hostent
*result
,
617 char *buffer
, size_t buflen
,
618 struct hostent
**rp
, int *errp
)
620 char namebuf
[IDN_NAME_SIZE
];
628 if (idn_isprocessing
)
629 return (REAL(gethostbyname_r
)(name
, result
, buffer
,
632 TRACE(("gethostbyname_r(name=%s,buflen=%d)\n",
633 idn__debug_xstring(name
, 60), buflen
));
635 if (buflen
<= sizeof(buf
)) {
637 datalen
= sizeof(buf
);
639 data
= malloc(buflen
);
647 idn_isprocessing
= 1;
650 r
= idn_encodename(IDN_ENCODE_APP
, name
, namebuf
, sizeof(namebuf
));
651 if (r
== idn_success
)
655 n
= REAL(gethostbyname_r
)(name
, &he
, data
, datalen
, rp
, errp
);
657 if (n
== 0 && *rp
!= NULL
)
658 *rp
= copy_decode_hostent_static(*rp
, result
, buffer
, buflen
,
660 idn_isprocessing
= 0;
662 if (data
!= buf
.data
)
666 n
= EINVAL
; /* XXX */
672 #ifdef HAVE_GETHOSTBYNAME2_R
674 ENTRY(gethostbyname2_r
)(const char *name
, int af
, struct hostent
*result
,
675 char *buffer
, size_t buflen
,
676 struct hostent
**rp
, int *errp
)
678 char namebuf
[IDN_NAME_SIZE
];
686 if (idn_isprocessing
)
687 return (REAL(gethostbyname2_r
)(name
, af
, result
, buffer
,
690 TRACE(("gethostbyname2_r(name=%s,buflen=%d)\n",
691 idn__debug_xstring(name
, 60), buflen
));
693 if (buflen
<= sizeof(buf
)) {
695 datalen
= sizeof(buf
);
697 data
= malloc(buflen
);
705 idn_isprocessing
= 1;
708 r
= idn_encodename(IDN_ENCODE_APP
, name
, namebuf
, sizeof(namebuf
));
709 if (r
== idn_success
)
712 n
= REAL(gethostbyname2_r
)(name
, af
, &he
, data
, datalen
, rp
, errp
);
714 if (n
== 0 && *rp
!= NULL
)
715 *rp
= copy_decode_hostent_static(*rp
, result
, buffer
, buflen
,
717 idn_isprocessing
= 0;
719 if (data
!= buf
.data
)
723 n
= EINVAL
; /* XXX */
729 #ifdef HAVE_GETHOSTBYADDR_R
731 ENTRY(gethostbyaddr_r
)(GHBA_ADDR_T addr
, GHBA_ADDRLEN_T len
, int type
,
732 struct hostent
*result
,
733 char *buffer
, size_t buflen
,
734 struct hostent
**rp
, int *errp
)
742 if (idn_isprocessing
) {
743 return (REAL(gethostbyaddr_r
)(addr
, len
, type
, result
,
744 buffer
, buflen
, rp
, errp
));
747 TRACE(("gethostbyaddr_r(buflen=%d)\n", buflen
));
749 if (buflen
<= sizeof(buf
)) {
751 datalen
= sizeof(buf
);
753 data
= malloc(buflen
);
761 idn_isprocessing
= 1;
762 n
= REAL(gethostbyaddr_r
)(addr
, len
, type
, &he
,
763 data
, datalen
, rp
, errp
);
765 if (n
== 0 && *rp
!= NULL
)
766 *rp
= copy_decode_hostent_static(*rp
, result
, buffer
, buflen
,
768 idn_isprocessing
= 0;
770 if (data
!= buf
.data
)
774 n
= EINVAL
; /* XXX */
780 #else /* GETHOST_R_GLIBC_FLAVOR */
782 #ifdef HAVE_GETHOSTBYNAME_R
784 ENTRY(gethostbyname_r
)(const char *name
, struct hostent
*result
,
785 char *buffer
, int buflen
, int *errp
)
787 char namebuf
[IDN_NAME_SIZE
];
791 struct hostent
*hp
, he
;
794 if (idn_isprocessing
)
795 return (REAL(gethostbyname_r
)(name
, result
, buffer
,
798 TRACE(("gethostbyname_r(name=%s,buflen=%d)\n",
799 idn__debug_xstring(name
, 60), buflen
));
801 if (buflen
<= sizeof(buf
)) {
803 datalen
= sizeof(buf
);
805 data
= malloc(buflen
);
813 idn_isprocessing
= 1;
816 r
= idn_encodename(IDN_ENCODE_APP
, name
, namebuf
, sizeof(namebuf
));
817 if (r
== idn_success
)
820 hp
= REAL(gethostbyname_r
)(name
, &he
, data
, datalen
, errp
);
823 hp
= copy_decode_hostent_static(hp
, result
, buffer
, buflen
,
825 idn_isprocessing
= 0;
827 if (data
!= buf
.data
)
834 #ifdef HAVE_GETHOSTBYADDR_R
836 ENTRY(gethostbyaddr_r
)(GHBA_ADDR_T addr
, GHBA_ADDRLEN_T len
, int type
,
837 struct hostent
*result
,
838 char *buffer
, int buflen
, int *errp
)
842 struct hostent
*hp
, he
;
845 if (idn_isprocessing
) {
846 return (REAL(gethostbyaddr_r
)(addr
, len
, type
, result
,
847 buffer
, buflen
, errp
));
850 TRACE(("gethostbyaddr_r(buflen=%d)\n", buflen
));
852 if (buflen
<= sizeof(buf
)) {
854 datalen
= sizeof(buf
);
856 data
= malloc(buflen
);
864 idn_isprocessing
= 1;
865 hp
= REAL(gethostbyaddr_r
)(addr
, len
, type
, &he
, data
, datalen
, errp
);
868 hp
= copy_decode_hostent_static(hp
, result
, buffer
, buflen
,
870 idn_isprocessing
= 0;
872 if (data
!= buf
.data
)
879 #endif /* GETHOST_R_GLIBC_FLAVOR */
881 #ifdef HAVE_GETIPNODEBYNAME
883 ENTRY(getipnodebyname
)(const char *name
, int af
, int flags
, int *errp
) {
884 char namebuf
[IDN_NAME_SIZE
];
888 if (idn_isprocessing
)
889 return (REAL(getipnodebyname
)(name
, af
, flags
, errp
));
891 TRACE(("getipnodebyname(name=%s)\n", idn__debug_xstring(name
, 60), af
));
893 idn_isprocessing
= 1;
896 r
= idn_encodename(IDN_ENCODE_APP
, name
, namebuf
, sizeof(namebuf
));
897 if (r
== idn_success
)
900 hp
= REAL(getipnodebyname
)(name
, af
, flags
, errp
);
902 struct hostent
*newhp
= copy_decode_hostent_dynamic(hp
, errp
);
904 REAL(freehostent
)(hp
);
909 idn_isprocessing
= 0;
914 #ifdef HAVE_GETIPNODEBYADDR
916 ENTRY(getipnodebyaddr
)(const void *src
, size_t len
, int af
, int *errp
) {
919 if (idn_isprocessing
)
920 return (REAL(getipnodebyaddr
)(src
, len
, af
, errp
));
922 TRACE(("getipnodebyaddr()\n"));
924 idn_isprocessing
= 1;
925 hp
= REAL(getipnodebyaddr
)(src
, len
, af
, errp
);
927 struct hostent
*newhp
= copy_decode_hostent_dynamic(hp
, errp
);
929 REAL(freehostent
)(hp
);
934 idn_isprocessing
= 0;
939 #ifdef HAVE_FREEHOSTENT
941 ENTRY(freehostent
)(struct hostent
*hp
) {
942 TRACE(("freehostent(hp=%p)\n", (void *)hp
));
944 if (obj_islocked(hp
)) {
946 * We allocated the data.
949 free_copied_hostent(hp
);
952 * It was allocated the original getipnodeby*().
954 REAL(freehostent
)(hp
);
959 #ifdef HAVE_GETADDRINFO
961 ENTRY(getaddrinfo
)(const char *nodename
, const char *servname
,
962 const struct addrinfo
*hints
, struct addrinfo
**res
)
964 char namebuf
[IDN_NAME_SIZE
];
966 struct addrinfo
*aip
;
969 if (nodename
== NULL
|| idn_isprocessing
)
970 return (REAL(getaddrinfo
)(nodename
, servname
, hints
, res
));
972 TRACE(("getaddrinfo(nodename=%s)\n", idn__debug_xstring(nodename
, 60)));
974 idn_isprocessing
= 1;
977 r
= idn_encodename(IDN_ENCODE_APP
, nodename
,
978 namebuf
, sizeof(namebuf
));
979 if (r
== idn_success
)
982 err
= REAL(getaddrinfo
)(nodename
, servname
, hints
, &aip
);
983 if (err
== 0 && aip
!= NULL
) {
984 *res
= copy_decode_addrinfo_dynamic(aip
);
990 REAL(freeaddrinfo
)(aip
);
992 idn_isprocessing
= 0;
997 #ifdef HAVE_FREEADDRINFO
999 ENTRY(freeaddrinfo
)(struct addrinfo
*aip
) {
1000 TRACE(("freeaddrinfo(aip=%p)\n", (void *)aip
));
1002 if (obj_islocked(aip
)) {
1004 * We allocated the data.
1007 free_copied_addrinfo(aip
);
1010 * It was allocated the original getaddrinfo().
1012 REAL(freeaddrinfo
)(aip
);
1017 #ifdef HAVE_GETNAMEINFO
1019 ENTRY(getnameinfo
)(const struct sockaddr
*sa
, GNI_SALEN_T salen
,
1020 char *host
, GNI_HOSTLEN_T hostlen
, char *serv
,
1021 GNI_SERVLEN_T servlen
, GNI_FLAGS_T flags
)
1023 char name
[IDN_NAME_SIZE
];
1024 size_t namelen
= sizeof(name
);
1028 if (host
== NULL
|| hostlen
== 0 || idn_isprocessing
) {
1029 return (REAL(getnameinfo
)(sa
, salen
, host
, hostlen
,
1030 serv
, servlen
, flags
));
1033 TRACE(("getnameinfo(hostlen=%u)\n", hostlen
));
1035 idn_isprocessing
= 1;
1036 code
= REAL(getnameinfo
)(sa
, salen
, name
, namelen
,
1037 serv
, servlen
, flags
);
1038 if (code
== 0 && name
[0] != '\0') {
1041 r
= idn_decodename(IDN_DECODE_APP
, name
, host
, hostlen
);
1046 case idn_buffer_overflow
:
1055 idn_isprocessing
= 0;