tst-inet6_scopeid_pton.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /* Tests for __inet6_scopeid_pton and IPv6 scopes in getaddrinfo.
  2. Copyright (C) 2016-2026 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. #include <arpa/inet.h>
  16. #include <inttypes.h>
  17. #include <net-internal.h>
  18. #include <net/if.h>
  19. #include <netdb.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <support/check.h>
  24. #include <support/support.h>
  25. #include <support/test-driver.h>
  26. /* An interface which is known to the system. */
  27. static const char *interface_name;
  28. static uint32_t interface_index;
  29. /* Initiale the variables above. */
  30. static void
  31. setup_interface (void)
  32. {
  33. struct if_nameindex *list = if_nameindex ();
  34. if (list != NULL && list[0].if_index != 0 && list[0].if_name[0] != '\0')
  35. {
  36. interface_name = list[0].if_name;
  37. interface_index = list[0].if_index;
  38. }
  39. }
  40. /* Convert ADDRESS to struct in6_addr. */
  41. static struct in6_addr
  42. from_string (const char *address)
  43. {
  44. struct in6_addr addr;
  45. if (inet_pton (AF_INET6, address, &addr) != 1)
  46. FAIL_EXIT1 ("inet_pton (\"%s\")", address);
  47. return addr;
  48. }
  49. /* Invoke getaddrinfo to parse ADDRESS%SCOPE. Return true if
  50. getaddrinfo was successful. */
  51. static bool
  52. call_gai (int family, const char *address, const char *scope,
  53. struct sockaddr_in6 *result)
  54. {
  55. struct addrinfo hints =
  56. {
  57. .ai_family = family,
  58. .ai_flags = AI_NUMERICHOST,
  59. .ai_socktype = SOCK_DGRAM,
  60. .ai_protocol = IPPROTO_UDP,
  61. };
  62. char *fulladdr = xasprintf ("%s%%%s", address, scope);
  63. struct addrinfo *ai = NULL;
  64. int ret = getaddrinfo (fulladdr, NULL, &hints, &ai);
  65. if (ret == EAI_ADDRFAMILY || ret == EAI_NONAME)
  66. {
  67. if (test_verbose > 0)
  68. printf ("info: getaddrinfo (\"%s\"): %s (%d)\n",
  69. fulladdr, gai_strerror (ret), ret);
  70. free (fulladdr);
  71. return false;
  72. }
  73. if (ret != 0)
  74. FAIL_EXIT1 ("getaddrinfo (\"%s\"): %s (%d)\n",
  75. fulladdr, gai_strerror (ret), ret);
  76. TEST_VERIFY_EXIT (ai != NULL);
  77. TEST_VERIFY_EXIT (ai->ai_addrlen == sizeof (*result));
  78. TEST_VERIFY (ai->ai_family == AF_INET6);
  79. TEST_VERIFY (ai->ai_next == NULL);
  80. memcpy (result, ai->ai_addr, sizeof (*result));
  81. free (fulladdr);
  82. freeaddrinfo (ai);
  83. return true;
  84. }
  85. /* Verify that a successful call to getaddrinfo returned the expected
  86. scope data. */
  87. static void
  88. check_ai (const char *what, const char *addr_string, const char *scope_string,
  89. const struct sockaddr_in6 *sa,
  90. const struct in6_addr *addr, uint32_t scope)
  91. {
  92. if (memcmp (addr, &sa->sin6_addr, sizeof (*addr)) != 0)
  93. {
  94. support_record_failure ();
  95. printf ("error: getaddrinfo %s address mismatch for %s%%%s\n",
  96. what, addr_string, scope_string);
  97. }
  98. if (sa->sin6_scope_id != scope)
  99. {
  100. support_record_failure ();
  101. printf ("error: getaddrinfo %s scope mismatch for %s%%%s\n"
  102. " expected: %" PRIu32 "\n"
  103. " actual: %" PRIu32 "\n",
  104. what, addr_string, scope_string, scope, sa->sin6_scope_id);
  105. }
  106. }
  107. /* Check a single address were we expected a failure. */
  108. static void
  109. expect_failure (const char *address, const char *scope)
  110. {
  111. if (test_verbose > 0)
  112. printf ("info: expecting failure for %s%%%s\n", address, scope);
  113. struct in6_addr addr = from_string (address);
  114. uint32_t result = 1234;
  115. if (__inet6_scopeid_pton (&addr, scope, &result) == 0)
  116. {
  117. support_record_failure ();
  118. printf ("error: unexpected success for %s%%%s\n",
  119. address, scope);
  120. }
  121. if (result != 1234)
  122. {
  123. support_record_failure ();
  124. printf ("error: unexpected result update for %s%%%s\n",
  125. address, scope);
  126. }
  127. struct sockaddr_in6 sa;
  128. if (call_gai (AF_UNSPEC, address, scope, &sa))
  129. {
  130. support_record_failure ();
  131. printf ("error: unexpected getaddrinfo success for %s%%%s (AF_UNSPEC)\n",
  132. address, scope);
  133. }
  134. if (call_gai (AF_INET6, address, scope, &sa))
  135. {
  136. support_record_failure ();
  137. printf ("error: unexpected getaddrinfo success for %s%%%s (AF_INET6)\n",
  138. address, scope);
  139. }
  140. }
  141. /* Check a single address were we expected a success. */
  142. static void
  143. expect_success (const char *address, const char *scope, uint32_t expected)
  144. {
  145. if (test_verbose > 0)
  146. printf ("info: expecting success for %s%%%s\n", address, scope);
  147. struct in6_addr addr = from_string (address);
  148. uint32_t actual = expected + 1;
  149. if (__inet6_scopeid_pton (&addr, scope, &actual) != 0)
  150. {
  151. support_record_failure ();
  152. printf ("error: unexpected failure for %s%%%s\n",
  153. address, scope);
  154. }
  155. if (actual != expected)
  156. {
  157. support_record_failure ();
  158. printf ("error: unexpected result for for %s%%%s\n",
  159. address, scope);
  160. printf (" expected: %" PRIu32 "\n", expected);
  161. printf (" actual: %" PRIu32 "\n", actual);
  162. }
  163. struct sockaddr_in6 sa;
  164. memset (&sa, 0xc0, sizeof (sa));
  165. if (call_gai (AF_UNSPEC, address, scope, &sa))
  166. check_ai ("AF_UNSPEC", address, scope, &sa, &addr, expected);
  167. else
  168. {
  169. support_record_failure ();
  170. printf ("error: unexpected getaddrinfo failure for %s%%%s (AF_UNSPEC)\n",
  171. address, scope);
  172. }
  173. memset (&sa, 0xc0, sizeof (sa));
  174. if (call_gai (AF_INET6, address, scope, &sa))
  175. check_ai ("AF_INET6", address, scope, &sa, &addr, expected);
  176. else
  177. {
  178. support_record_failure ();
  179. printf ("error: unexpected getaddrinfo failure for %s%%%s (AF_INET6)\n",
  180. address, scope);
  181. }
  182. }
  183. static int
  184. do_test (void)
  185. {
  186. setup_interface ();
  187. static const char *test_addresses[]
  188. = { "::", "::1", "2001:db8::1", NULL };
  189. for (int i = 0; test_addresses[i] != NULL; ++i)
  190. {
  191. expect_success (test_addresses[i], "0", 0);
  192. expect_success (test_addresses[i], "5555", 5555);
  193. expect_failure (test_addresses[i], "");
  194. expect_failure (test_addresses[i], "-1");
  195. expect_failure (test_addresses[i], "-99");
  196. expect_failure (test_addresses[i], "037777777777");
  197. expect_failure (test_addresses[i], "0x");
  198. expect_failure (test_addresses[i], "0x1");
  199. }
  200. if (interface_name != NULL)
  201. {
  202. expect_success ("fe80::1", interface_name, interface_index);
  203. expect_success ("ff02::1", interface_name, interface_index);
  204. expect_success ("ff01::1", interface_name, interface_index);
  205. expect_failure ("::", interface_name);
  206. expect_failure ("::1", interface_name);
  207. expect_failure ("2001:db8::1", interface_name);
  208. }
  209. return 0;
  210. }
  211. #include <support/test-driver.c>