PageRenderTime 45ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/resolv/tst-resolv-ai_idn-common.c

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