1 /* Common code for AI_IDN/NI_IDN tests.
2    Copyright (C) 2018-2022 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
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.
9 
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.
14 
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/>.  */
18 
19 /* Before including this file, TEST_USE_UTF8 must be defined to 1 or
20    0, depending on whether a UTF-8 locale is used or a Latin-1
21    locale.  */
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <support/check.h>
27 #include <support/check_nss.h>
28 #include <support/resolv_test.h>
29 #include <support/support.h>
30 
31 /* Name of the shared object for libidn2.  */
32 #define LIBIDN2_SONAME "libidn2.so.0"
33 
34 #if TEST_USE_UTF8
35 /* UTF-8 encoding of "nämchen" (German for “namelet”).  */
36 # define NAEMCHEN "n\xC3\xA4mchen"
37 
38 /* UTF-8 encoding of "שם" (Hebrew for “name”).  */
39 # define SHEM "\xD7\xA9\xD7\x9D"
40 
41 /* UTF-8 encoding of "buße" (German for “penance”).  This used to be
42    encoded as "busse" (“busses”) in IDNA2003.  */
43 # define BUSSE "bu\xC3\x9F""e"
44 
45 #else
46 /* Latin-1 encodings, as far as they are available.  */
47 
48 # define NAEMCHEN "n\xE4mchen"
49 # define BUSSE "bu\xDF""e"
50 
51 #endif
52 
53 /* IDNA encoding of NAEMCHEN.  */
54 #define NAEMCHEN_IDNA "xn--nmchen-bua"
55 
56 /* IDNA encoding of NAEMCHEN "_zwo".  */
57 #define NAEMCHEN_ZWO_IDNA "xn--nmchen_zwo-q5a"
58 
59 /* IDNA encoding of SHEM.  */
60 #define SHEM_IDNA "xn--iebx"
61 
62 /* IDNA encoding of BUSSE.  */
63 #define BUSSE_IDNA "xn--bue-6ka"
64 
65 /* IDNA encoding of "שם1".  */
66 #define SHEM1_IDNA "xn--1-qic9a"
67 
68 /* Another IDNA name.  */
69 #define ANDERES_NAEMCHEN "anderes-" NAEMCHEN
70 #define ANDERES_NAEMCHEN_IDNA "xn--anderes-nmchen-eib"
71 
72 /* Controls the kind of test data in a PTR lookup response.  */
73 enum gni_test
74   {
75     gni_non_idn_name,
76     gni_non_idn_cname_to_non_idn_name,
77     gni_non_idn_cname_to_idn_name,
78     gni_idn_name,
79     gni_idn_shem,
80     gni_idn_shem1,
81     gni_idn_cname_to_non_idn_name,
82     gni_idn_cname_to_idn_name,
83     gni_invalid_idn_1,
84     gni_invalid_idn_2,
85   };
86 
87 /* Called from response below.  The LSB (first byte) controls what
88    goes into the response, see enum gni_test.  */
89 static void
response_ptr(const struct resolv_response_context * ctx,struct resolv_response_builder * b,const char * qname)90 response_ptr (const struct resolv_response_context *ctx,
91               struct resolv_response_builder *b, const char *qname)
92 {
93   int comp[4] = { 0 };
94   TEST_COMPARE (sscanf (qname, "%d.%d.%d.%d.in-addr.arpa",
95                         &comp[0], &comp[1], &comp[2], &comp[3]), 4);
96   const char *next_name;
97   switch ((enum gni_test) comp[0])
98     {
99     /* First name in response is non-IDN name.  */
100     case gni_non_idn_name:
101       resolv_response_open_record (b, qname, C_IN, T_PTR, 0);
102       resolv_response_add_name (b, "non-idn.example");
103       resolv_response_close_record (b);
104       return;
105     case gni_non_idn_cname_to_non_idn_name:
106       resolv_response_open_record (b, qname, C_IN, T_CNAME, 0);
107       next_name = "non-idn-cname.example";
108       resolv_response_add_name (b, next_name);
109       resolv_response_close_record (b);
110       resolv_response_open_record (b, next_name, C_IN, T_PTR, 0);
111       resolv_response_add_name (b, "non-idn-name.example");
112       resolv_response_close_record (b);
113       return;
114     case gni_non_idn_cname_to_idn_name:
115       resolv_response_open_record (b, qname, C_IN, T_CNAME, 0);
116       next_name = "non-idn-cname.example";
117       resolv_response_add_name (b, next_name);
118       resolv_response_close_record (b);
119       resolv_response_open_record (b, next_name, C_IN, T_PTR, 0);
120       resolv_response_add_name (b, NAEMCHEN_IDNA ".example");
121       resolv_response_close_record (b);
122       return;
123 
124     /* First name in response is IDN name.  */
125     case gni_idn_name:
126       resolv_response_open_record (b, qname, C_IN, T_PTR, 0);
127       resolv_response_add_name (b, "xn--nmchen-bua.example");
128       resolv_response_close_record (b);
129       return;
130     case gni_idn_shem:
131       resolv_response_open_record (b, qname, C_IN, T_PTR, 0);
132       resolv_response_add_name (b, SHEM_IDNA ".example");
133       resolv_response_close_record (b);
134       return;
135     case gni_idn_shem1:
136       resolv_response_open_record (b, qname, C_IN, T_PTR, 0);
137       resolv_response_add_name (b, SHEM1_IDNA ".example");
138       resolv_response_close_record (b);
139       return;
140     case gni_idn_cname_to_non_idn_name:
141       resolv_response_open_record (b, qname, C_IN, T_CNAME, 0);
142       next_name = NAEMCHEN_IDNA ".example";
143       resolv_response_add_name (b, next_name);
144       resolv_response_close_record (b);
145       resolv_response_open_record (b, next_name, C_IN, T_PTR, 0);
146       resolv_response_add_name (b, "non-idn-name.example");
147       resolv_response_close_record (b);
148       return;
149     case gni_idn_cname_to_idn_name:
150       resolv_response_open_record (b, qname, C_IN, T_CNAME, 0);
151       next_name = NAEMCHEN_IDNA ".example";
152       resolv_response_add_name (b, next_name);
153       resolv_response_close_record (b);
154       resolv_response_open_record (b, next_name, C_IN, T_PTR, 0);
155       resolv_response_add_name (b, ANDERES_NAEMCHEN_IDNA ".example");
156       resolv_response_close_record (b);
157       return;
158 
159     /* Invalid IDN encodings.  */
160     case gni_invalid_idn_1:
161       resolv_response_open_record (b, qname, C_IN, T_PTR, 0);
162       resolv_response_add_name (b, "xn---.example");
163       resolv_response_close_record (b);
164       return;
165     case gni_invalid_idn_2:
166       resolv_response_open_record (b, qname, C_IN, T_PTR, 0);
167       resolv_response_add_name (b, "xn--x.example");
168       resolv_response_close_record (b);
169       return;
170     }
171   FAIL_EXIT1 ("invalid PTR query: %s", qname);
172 }
173 
174 /* For PTR responses, see above.  A/AAAA queries can request
175    additional CNAMEs in the response by include ".cname." and
176    ".idn-cname." in the query.  The LSB in the address contains the
177    first byte of the QNAME.  */
178 static void
response(const struct resolv_response_context * ctx,struct resolv_response_builder * b,const char * qname,uint16_t qclass,uint16_t qtype)179 response (const struct resolv_response_context *ctx,
180           struct resolv_response_builder *b,
181           const char *qname, uint16_t qclass, uint16_t qtype)
182 {
183   TEST_VERIFY_EXIT (qclass == C_IN);
184 
185   for (const char *p = qname; *p != '\0'; ++p)
186     if (!(('0' <= *p && *p <= '9')
187           || ('a' <= *p && *p <= 'z')
188           || ('A' <= *p && *p <= 'Z')
189           || *p == '.' || *p == '-' || *p == '_'))
190       {
191         /* Non-ASCII query.  Reply with NXDOMAIN.  */
192         struct resolv_response_flags flags = { .rcode = 3 };
193         resolv_response_init (b, flags);
194         resolv_response_add_question (b, qname, qclass, qtype);
195         return;
196       }
197 
198   struct resolv_response_flags flags = { 0 };
199   resolv_response_init (b, flags);
200   resolv_response_add_question (b, qname, qclass, qtype);
201   resolv_response_section (b, ns_s_an);
202 
203   if (qtype == T_PTR)
204     {
205       response_ptr (ctx, b, qname);
206       return;
207     }
208 
209   bool with_cname = strstr (qname, ".cname.") != NULL;
210   bool with_idn_cname = strstr (qname, ".idn-cname.") != NULL;
211 
212   const char *next_name = qname;
213   if (with_cname)
214     {
215       next_name = "non-idn-cname.example";
216       resolv_response_open_record (b, qname, C_IN, T_CNAME, 0);
217       resolv_response_add_name (b, next_name);
218       resolv_response_close_record (b);
219     }
220   if (with_idn_cname)
221     {
222       const char *previous_name = next_name;
223       next_name = ANDERES_NAEMCHEN_IDNA ".example";
224       resolv_response_open_record (b, previous_name, C_IN, T_CNAME, 0);
225       resolv_response_add_name (b, next_name);
226       resolv_response_close_record (b);
227     }
228 
229   resolv_response_open_record (b, next_name, C_IN, qtype, 0);
230   switch (qtype)
231     {
232     case T_A:
233       {
234         char addr[4] = { 192, 0, 2, qname[0] };
235         resolv_response_add_data (b, &addr, sizeof (addr));
236       }
237       break;
238     case T_AAAA:
239       {
240         char addr[16]
241           = { 0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
242               qname[0] };
243         resolv_response_add_data (b, &addr, sizeof (addr));
244       }
245       break;
246     default:
247       FAIL_EXIT1 ("invalid qtype: %d", qtype);
248     }
249   resolv_response_close_record (b);
250 }
251 
252 /* Check the result of a getaddrinfo call.  */
253 static void
check_ai(const char * name,int ai_flags,const char * expected)254 check_ai (const char *name, int ai_flags, const char *expected)
255 {
256   struct addrinfo hints =
257     {
258       .ai_flags = ai_flags,
259       .ai_family = AF_INET,
260       .ai_socktype = SOCK_STREAM,
261     };
262   struct addrinfo *ai;
263   char *query = xasprintf ("%s:80 AF_INET/0x%x", name, ai_flags);
264   int ret = getaddrinfo (name, "80", &hints, &ai);
265   check_addrinfo (query, ai, ret, expected);
266   if (ret == 0)
267     freeaddrinfo (ai);
268   free (query);
269 }
270 
271 /* Run one getnameinfo test.  FLAGS is automatically augmented with
272    NI_NUMERICSERV.  */
273 static void
gni_test(enum gni_test code,unsigned int flags,const char * expected)274 gni_test (enum gni_test code, unsigned int flags, const char *expected)
275 {
276   struct sockaddr_in sin =
277     {
278       .sin_family = AF_INET,
279       .sin_port = htons (80),
280       .sin_addr = { htonl (0xc0000200 | code) }, /* 192.0.2.0/24 network.  */
281     };
282   char host[1024];
283   char service[1024];
284   int ret = getnameinfo ((const struct sockaddr *) &sin, sizeof (sin),
285                          host, sizeof (host), service, sizeof (service),
286                          flags| NI_NUMERICSERV);
287   if (ret != 0)
288     {
289       if (expected == NULL)
290         TEST_COMPARE (ret, EAI_IDN_ENCODE);
291       else
292         {
293           support_record_failure ();
294           printf ("error: getnameinfo failed (code %d, flags 0x%x): %s (%d)\n",
295                   (int) code, flags, gai_strerror (ret), ret);
296         }
297     }
298   else if (ret == 0 && expected == NULL)
299     {
300       support_record_failure ();
301       printf ("error: getnameinfo unexpected success (code %d, flags 0x%x)\n",
302               (int) code, flags);
303     }
304   else if (strcmp (host, expected) != 0 || strcmp (service, "80") != 0)
305     {
306       support_record_failure ();
307       printf ("error: getnameinfo test failure (code %d, flags 0x%x)\n"
308               "  expected host:    \"%s\"\n"
309               "  expected service: \"80\"\n"
310               "  actual host:      \"%s\"\n"
311               "  actual service:   \"%s\"\n",
312               (int) code, flags, expected, host, service);
313     }
314 }
315 
316 /* Tests for getaddrinfo which assume a working libidn2 library.  */
317 __attribute__ ((unused))
318 static void
gai_tests_with_libidn2(void)319 gai_tests_with_libidn2 (void)
320 {
321   /* No CNAME.  */
322   check_ai ("non-idn.example", 0,
323             "address: STREAM/TCP 192.0.2.110 80\n");
324   check_ai ("non-idn.example", AI_IDN,
325             "flags: AI_IDN\n"
326             "address: STREAM/TCP 192.0.2.110 80\n");
327   check_ai ("non-idn.example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
328             "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
329             "canonname: non-idn.example\n"
330             "address: STREAM/TCP 192.0.2.110 80\n");
331 
332   check_ai (NAEMCHEN ".example", 0,
333             "error: Name or service not known\n");
334   check_ai (NAEMCHEN ".example", AI_IDN,
335             "flags: AI_IDN\n"
336             "address: STREAM/TCP 192.0.2.120 80\n");
337   check_ai (NAEMCHEN ".example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
338             "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
339             "canonname: " NAEMCHEN ".example\n"
340             "address: STREAM/TCP 192.0.2.120 80\n");
341 
342 #if TEST_USE_UTF8
343   check_ai (SHEM ".example", 0,
344             "error: Name or service not known\n");
345   check_ai (SHEM ".example", AI_IDN,
346             "flags: AI_IDN\n"
347             "address: STREAM/TCP 192.0.2.120 80\n");
348   check_ai (SHEM ".example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
349             "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
350             "canonname: " SHEM ".example\n"
351             "address: STREAM/TCP 192.0.2.120 80\n");
352   check_ai (SHEM ".example", AI_IDN | AI_CANONNAME,
353             "flags: AI_CANONNAME AI_IDN\n"
354             "canonname: " SHEM_IDNA ".example\n"
355             "address: STREAM/TCP 192.0.2.120 80\n");
356   check_ai (SHEM "1.example", AI_IDN,
357             "flags: AI_IDN\n"
358             "address: STREAM/TCP 192.0.2.120 80\n");
359   check_ai (SHEM "1.example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
360             "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
361             "canonname: " SHEM "1.example\n"
362             "address: STREAM/TCP 192.0.2.120 80\n");
363   check_ai (SHEM "1.example", AI_IDN | AI_CANONNAME,
364             "flags: AI_CANONNAME AI_IDN\n"
365             "canonname: " SHEM1_IDNA ".example\n"
366             "address: STREAM/TCP 192.0.2.120 80\n");
367 #endif
368 
369   /* Check that non-transitional mode is active.  German sharp S
370      should not turn into SS.  */
371   check_ai (BUSSE ".example", 0,
372             "error: Name or service not known\n");
373   check_ai (BUSSE ".example", AI_IDN,
374             "flags: AI_IDN\n"
375             "address: STREAM/TCP 192.0.2.120 80\n");
376   check_ai (BUSSE ".example", AI_IDN | AI_CANONNAME,
377             "flags: AI_CANONNAME AI_IDN\n"
378             "canonname: " BUSSE_IDNA ".example\n"
379             "address: STREAM/TCP 192.0.2.120 80\n");
380   check_ai (BUSSE ".example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
381             "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
382             "canonname: " BUSSE ".example\n"
383             "address: STREAM/TCP 192.0.2.120 80\n");
384 
385   /* Check that Unicode TR 46 mode is active.  Underscores should be
386      permitted in IDNA components.  */
387   check_ai (NAEMCHEN "_zwo.example", 0,
388             "error: Name or service not known\n");
389   check_ai (NAEMCHEN "_zwo.example", AI_IDN,
390             "flags: AI_IDN\n"
391             "address: STREAM/TCP 192.0.2.120 80\n");
392   check_ai (NAEMCHEN "_zwo.example", AI_IDN | AI_CANONNAME,
393             "flags: AI_CANONNAME AI_IDN\n"
394             "canonname: " NAEMCHEN_ZWO_IDNA ".example\n"
395             "address: STREAM/TCP 192.0.2.120 80\n");
396   check_ai (NAEMCHEN "_zwo.example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
397             "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
398             "canonname: " NAEMCHEN "_zwo.example\n"
399             "address: STREAM/TCP 192.0.2.120 80\n");
400 
401   /* No CNAME, but already IDN-encoded.  */
402   check_ai (NAEMCHEN_IDNA ".example", 0,
403             "address: STREAM/TCP 192.0.2.120 80\n");
404   check_ai (NAEMCHEN_IDNA ".example", AI_IDN,
405             "flags: AI_IDN\n"
406             "address: STREAM/TCP 192.0.2.120 80\n");
407   check_ai (NAEMCHEN_IDNA ".example", AI_IDN | AI_CANONNAME,
408             "flags: AI_CANONNAME AI_IDN\n"
409             "canonname: " NAEMCHEN_IDNA ".example\n"
410             "address: STREAM/TCP 192.0.2.120 80\n");
411   check_ai (NAEMCHEN_IDNA ".example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
412             "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
413             "canonname: " NAEMCHEN ".example\n"
414             "address: STREAM/TCP 192.0.2.120 80\n");
415   check_ai (SHEM_IDNA ".example", 0,
416             "address: STREAM/TCP 192.0.2.120 80\n");
417   check_ai (SHEM_IDNA ".example", AI_IDN,
418             "flags: AI_IDN\n"
419             "address: STREAM/TCP 192.0.2.120 80\n");
420   check_ai (SHEM_IDNA ".example", AI_IDN | AI_CANONNAME,
421             "flags: AI_CANONNAME AI_IDN\n"
422             "canonname: " SHEM_IDNA ".example\n"
423             "address: STREAM/TCP 192.0.2.120 80\n");
424 #if TEST_USE_UTF8
425   check_ai (SHEM_IDNA ".example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
426             "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
427             "canonname: " SHEM ".example\n"
428             "address: STREAM/TCP 192.0.2.120 80\n");
429 #else
430   check_ai (SHEM_IDNA ".example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
431             "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
432             "canonname: " SHEM_IDNA ".example\n"
433             "address: STREAM/TCP 192.0.2.120 80\n");
434 #endif
435 
436   /* Invalid IDNA canonical name is returned as-is.  */
437   check_ai ("xn---.example", AI_CANONNAME | AI_CANONIDN,
438             "flags: AI_CANONNAME AI_CANONIDN\n"
439             "canonname: xn---.example\n"
440             "address: STREAM/TCP 192.0.2.120 80\n");
441 
442   /* Non-IDN CNAME.  */
443   check_ai ("with.cname.example", 0,
444             "address: STREAM/TCP 192.0.2.119 80\n");
445   check_ai ("with.cname.example", AI_IDN,
446             "flags: AI_IDN\n"
447             "address: STREAM/TCP 192.0.2.119 80\n");
448   check_ai ("with.cname.example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
449             "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
450             "canonname: non-idn-cname.example\n"
451             "address: STREAM/TCP 192.0.2.119 80\n");
452 
453   check_ai ("with.cname." NAEMCHEN ".example", 0,
454             "error: Name or service not known\n");
455   check_ai ("with.cname." NAEMCHEN ".example", AI_IDN,
456             "flags: AI_IDN\n"
457             "address: STREAM/TCP 192.0.2.119 80\n");
458   check_ai ("with.cname." NAEMCHEN ".example", AI_IDN | AI_CANONNAME,
459             "flags: AI_CANONNAME AI_IDN\n"
460             "canonname: non-idn-cname.example\n"
461             "address: STREAM/TCP 192.0.2.119 80\n");
462   check_ai ("with.cname." NAEMCHEN ".example",
463             AI_IDN | AI_CANONNAME | AI_CANONIDN,
464             "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
465             "canonname: non-idn-cname.example\n"
466             "address: STREAM/TCP 192.0.2.119 80\n");
467 
468   /* IDN CNAME.  */
469   check_ai ("With.idn-cname.example", 0,
470             "address: STREAM/TCP 192.0.2.87 80\n");
471   check_ai ("With.idn-cname.example", AI_IDN,
472             "flags: AI_IDN\n"
473             "address: STREAM/TCP 192.0.2.87 80\n");
474   check_ai ("With.idn-cname.example", AI_IDN | AI_CANONNAME,
475             "flags: AI_CANONNAME AI_IDN\n"
476             "canonname: " ANDERES_NAEMCHEN_IDNA ".example\n"
477             "address: STREAM/TCP 192.0.2.87 80\n");
478   check_ai ("With.idn-cname.example",
479             AI_IDN | AI_CANONNAME | AI_CANONIDN,
480             "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
481             "canonname: " ANDERES_NAEMCHEN ".example\n"
482             "address: STREAM/TCP 192.0.2.87 80\n");
483 
484   check_ai ("With.idn-cname." NAEMCHEN ".example", 0,
485             "error: Name or service not known\n");
486   check_ai ("With.idn-cname." NAEMCHEN ".example", AI_IDN,
487             "flags: AI_IDN\n"
488             "address: STREAM/TCP 192.0.2.119 80\n");
489   check_ai ("With.idn-cname." NAEMCHEN ".example", AI_IDN | AI_CANONNAME,
490             "flags: AI_CANONNAME AI_IDN\n"
491             "canonname: " ANDERES_NAEMCHEN_IDNA ".example\n"
492             "address: STREAM/TCP 192.0.2.119 80\n");
493   check_ai ("With.idn-cname." NAEMCHEN ".example",
494             AI_IDN | AI_CANONNAME | AI_CANONIDN,
495             "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
496             "canonname: " ANDERES_NAEMCHEN ".example\n"
497             "address: STREAM/TCP 192.0.2.119 80\n");
498 
499   /* Non-IDN to IDN CNAME chain.  */
500   check_ai ("both.cname.idn-cname.example", 0,
501             "address: STREAM/TCP 192.0.2.98 80\n");
502   check_ai ("both.cname.idn-cname.example", AI_IDN,
503             "flags: AI_IDN\n"
504             "address: STREAM/TCP 192.0.2.98 80\n");
505   check_ai ("both.cname.idn-cname.example", AI_IDN | AI_CANONNAME,
506             "flags: AI_CANONNAME AI_IDN\n"
507             "canonname: " ANDERES_NAEMCHEN_IDNA ".example\n"
508             "address: STREAM/TCP 192.0.2.98 80\n");
509   check_ai ("both.cname.idn-cname.example",
510             AI_IDN | AI_CANONNAME | AI_CANONIDN,
511             "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
512             "canonname: " ANDERES_NAEMCHEN ".example\n"
513             "address: STREAM/TCP 192.0.2.98 80\n");
514 
515   check_ai ("both.cname.idn-cname." NAEMCHEN ".example", 0,
516             "error: Name or service not known\n");
517   check_ai ("both.cname.idn-cname." NAEMCHEN ".example", AI_IDN,
518             "flags: AI_IDN\n"
519             "address: STREAM/TCP 192.0.2.98 80\n");
520   check_ai ("both.cname.idn-cname." NAEMCHEN ".example",
521             AI_IDN | AI_CANONNAME,
522             "flags: AI_CANONNAME AI_IDN\n"
523             "canonname: " ANDERES_NAEMCHEN_IDNA ".example\n"
524             "address: STREAM/TCP 192.0.2.98 80\n");
525   check_ai ("both.cname.idn-cname." NAEMCHEN ".example",
526             AI_IDN | AI_CANONNAME | AI_CANONIDN,
527             "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
528             "canonname: " ANDERES_NAEMCHEN ".example\n"
529             "address: STREAM/TCP 192.0.2.98 80\n");
530 }
531 
532 /* Tests for getnameinfo which assume a working libidn2 library.  */
533 __attribute__ ((unused))
534 static void
gni_tests_with_libidn2(void)535 gni_tests_with_libidn2 (void)
536 {
537   gni_test (gni_non_idn_name, 0, "non-idn.example");
538   gni_test (gni_non_idn_name, NI_IDN, "non-idn.example");
539   gni_test (gni_non_idn_name, NI_NUMERICHOST, "192.0.2.0");
540   gni_test (gni_non_idn_name, NI_NUMERICHOST | NI_IDN, "192.0.2.0");
541 
542   gni_test (gni_non_idn_cname_to_non_idn_name, 0, "non-idn-name.example");
543   gni_test (gni_non_idn_cname_to_non_idn_name, NI_IDN, "non-idn-name.example");
544 
545   gni_test (gni_non_idn_cname_to_idn_name, 0, NAEMCHEN_IDNA ".example");
546   gni_test (gni_non_idn_cname_to_idn_name, NI_IDN, NAEMCHEN ".example");
547 
548   gni_test (gni_idn_name, 0, NAEMCHEN_IDNA ".example");
549   gni_test (gni_idn_name, NI_IDN, NAEMCHEN ".example");
550   gni_test (gni_idn_shem, 0, SHEM_IDNA ".example");
551   gni_test (gni_idn_shem1, 0, SHEM1_IDNA ".example");
552 #if TEST_USE_UTF8
553   gni_test (gni_idn_shem, NI_IDN, SHEM ".example");
554   gni_test (gni_idn_shem1, NI_IDN, SHEM "1.example");
555 #else
556   gni_test (gni_idn_shem, NI_IDN, SHEM_IDNA ".example");
557   gni_test (gni_idn_shem1, NI_IDN, SHEM1_IDNA ".example");
558 #endif
559 
560   gni_test (gni_idn_cname_to_non_idn_name, 0, "non-idn-name.example");
561   gni_test (gni_idn_cname_to_non_idn_name, NI_IDN, "non-idn-name.example");
562 
563   gni_test (gni_idn_cname_to_idn_name, 0, ANDERES_NAEMCHEN_IDNA ".example");
564   gni_test (gni_idn_cname_to_idn_name, NI_IDN, ANDERES_NAEMCHEN ".example");
565 
566   /* Test encoding errors.  */
567   gni_test (gni_invalid_idn_1, 0, "xn---.example");
568   gni_test (gni_invalid_idn_1, NI_IDN, "xn---.example");
569   gni_test (gni_invalid_idn_2, 0, "xn--x.example");
570   gni_test (gni_invalid_idn_2, NI_IDN, "xn--x.example");
571 }
572