1 /* IDNA functions, forwarding to implementations in libidn2.
2 Copyright (C) 2018-2022 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
19 #include <allocate_once.h>
21 #include <inet/net-internal.h>
25 /* Use the soname and version to locate libidn2, to ensure a
27 #define LIBIDN2_SONAME "libidn2.so.0"
28 #define LIBIDN2_VERSION "IDN2_0.0.0"
30 /* Return codes from libidn2. */
37 /* Functions from libidn2. */
41 int (*lookup_ul
) (const char *src
, char **result
, int flags
);
42 int (*to_unicode_lzlz
) (const char *name
, char **result
, int flags
);
46 functions_allocate (void *closure
)
48 struct functions
*result
= malloc (sizeof (*result
));
52 void *handle
= __libc_dlopen (LIBIDN2_SONAME
);
54 /* Do not cache open failures. The library may appear
62 = __libc_dlvsym (handle
, "idn2_lookup_ul", LIBIDN2_VERSION
);
63 void *ptr_to_unicode_lzlz
64 = __libc_dlvsym (handle
, "idn2_to_unicode_lzlz", LIBIDN2_VERSION
);
65 if (ptr_lookup_ul
== NULL
|| ptr_to_unicode_lzlz
== NULL
)
67 __libc_dlclose (handle
);
72 result
->handle
= handle
;
73 result
->lookup_ul
= ptr_lookup_ul
;
74 result
->to_unicode_lzlz
= ptr_to_unicode_lzlz
;
76 PTR_MANGLE (result
->lookup_ul
);
77 PTR_MANGLE (result
->to_unicode_lzlz
);
84 functions_deallocate (void *closure
, void *ptr
)
86 struct functions
*functions
= ptr
;
87 __libc_dlclose (functions
->handle
);
91 /* Ensure that *functions is initialized and return the value of the
92 pointer. If the library cannot be loaded, return NULL. */
93 static inline struct functions
*
96 static void *functions
;
97 return allocate_once (&functions
, functions_allocate
, functions_deallocate
,
101 /* strdup with an EAI_* error code. */
103 gai_strdup (const char *name
, char **result
)
105 char *ptr
= __strdup (name
);
113 __idna_to_dns_encoding (const char *name
, char **result
)
115 switch (__idna_name_classify (name
))
117 case idna_name_ascii
:
118 /* Nothing to convert. */
119 return gai_strdup (name
, result
);
120 case idna_name_nonascii
:
121 /* Encoding needed. Handled below. */
123 case idna_name_nonascii_backslash
:
124 case idna_name_encoding_error
:
125 return EAI_IDN_ENCODE
;
126 case idna_name_memory_error
:
128 case idna_name_error
:
132 struct functions
*functions
= get_functions ();
133 if (functions
== NULL
)
134 /* We report this as an encoding error (assuming that libidn2 is
135 not installed), although the root cause may be a temporary
136 error condition due to resource shortage. */
137 return EAI_IDN_ENCODE
;
139 __typeof__ (functions
->lookup_ul
) fptr
= functions
->lookup_ul
;
143 int ret
= fptr (name
, &ptr
, 0);
146 /* Assume that idn2_free is equivalent to free. */
150 else if (ret
== IDN2_MALLOC
)
153 return EAI_IDN_ENCODE
;
155 libc_hidden_def (__idna_to_dns_encoding
)
158 __idna_from_dns_encoding (const char *name
, char **result
)
160 struct functions
*functions
= get_functions ();
161 if (functions
== NULL
)
162 /* Simply use the encoded name, assuming that it is not punycode
163 (but even a punycode name would be syntactically valid). */
164 return gai_strdup (name
, result
);
166 __typeof__ (functions
->to_unicode_lzlz
) fptr
= functions
->to_unicode_lzlz
;
170 int ret
= fptr (name
, &ptr
, 0);
173 /* Assume that idn2_free is equivalent to free. */
177 else if (ret
== IDN2_MALLOC
)
180 return EAI_IDN_ENCODE
;
182 libc_hidden_def (__idna_from_dns_encoding
)