test-ip6-addr.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
  2. *
  3. * Permission is hereby granted, free of charge, to any person obtaining a copy
  4. * of this software and associated documentation files (the "Software"), to
  5. * deal in the Software without restriction, including without limitation the
  6. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  7. * sell copies of the Software, and to permit persons to whom the Software is
  8. * furnished to do so, subject to the following conditions:
  9. *
  10. * The above copyright notice and this permission notice shall be included in
  11. * all copies or substantial portions of the Software.
  12. *
  13. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  18. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  19. * IN THE SOFTWARE.
  20. */
  21. #include "uv.h"
  22. #include "task.h"
  23. #include <stdio.h>
  24. #include <string.h>
  25. #ifdef __linux__
  26. # include <sys/socket.h>
  27. # include <net/if.h>
  28. #endif
  29. TEST_IMPL(ip6_addr_link_local) {
  30. #if defined(__CYGWIN__) || defined(__MSYS__)
  31. /* FIXME: Does Cygwin support this? */
  32. RETURN_SKIP("FIXME: This test needs more investigation on Cygwin");
  33. #endif
  34. char string_address[INET6_ADDRSTRLEN];
  35. uv_interface_address_t* addresses;
  36. uv_interface_address_t* address;
  37. struct sockaddr_in6 addr;
  38. unsigned int iface_index;
  39. const char* device_name;
  40. /* 40 bytes address, 16 bytes device name, plus reserve. */
  41. char scoped_addr[128];
  42. size_t scoped_addr_len;
  43. char interface_id[UV_IF_NAMESIZE];
  44. size_t interface_id_len;
  45. int count;
  46. int ix;
  47. int r;
  48. ASSERT(0 == uv_interface_addresses(&addresses, &count));
  49. for (ix = 0; ix < count; ix++) {
  50. address = addresses + ix;
  51. if (address->address.address6.sin6_family != AF_INET6)
  52. continue;
  53. ASSERT(0 == uv_inet_ntop(AF_INET6,
  54. &address->address.address6.sin6_addr,
  55. string_address,
  56. sizeof(string_address)));
  57. /* Skip addresses that are not link-local. */
  58. if (strncmp(string_address, "fe80::", 6) != 0)
  59. continue;
  60. iface_index = address->address.address6.sin6_scope_id;
  61. device_name = address->name;
  62. scoped_addr_len = sizeof(scoped_addr);
  63. ASSERT(0 == uv_if_indextoname(iface_index, scoped_addr, &scoped_addr_len));
  64. #ifndef _WIN32
  65. /* This assert fails on Windows, as Windows semantics are different. */
  66. ASSERT(0 == strcmp(device_name, scoped_addr));
  67. #endif
  68. interface_id_len = sizeof(interface_id);
  69. r = uv_if_indextoiid(iface_index, interface_id, &interface_id_len);
  70. ASSERT(0 == r);
  71. #ifdef _WIN32
  72. /* On Windows, the interface identifier is the numeric string of the index. */
  73. ASSERT(strtoul(interface_id, NULL, 10) == iface_index);
  74. #else
  75. /* On Unix/Linux, the interface identifier is the interface device name. */
  76. ASSERT(0 == strcmp(device_name, interface_id));
  77. #endif
  78. snprintf(scoped_addr,
  79. sizeof(scoped_addr),
  80. "%s%%%s",
  81. string_address,
  82. interface_id);
  83. fprintf(stderr, "Testing link-local address %s "
  84. "(iface_index: 0x%02x, device_name: %s)\n",
  85. scoped_addr,
  86. iface_index,
  87. device_name);
  88. fflush(stderr);
  89. ASSERT(0 == uv_ip6_addr(scoped_addr, TEST_PORT, &addr));
  90. fprintf(stderr, "Got scope_id 0x%02x\n", addr.sin6_scope_id);
  91. fflush(stderr);
  92. ASSERT(iface_index == addr.sin6_scope_id);
  93. }
  94. uv_free_interface_addresses(addresses, count);
  95. scoped_addr_len = sizeof(scoped_addr);
  96. ASSERT(0 != uv_if_indextoname((unsigned int)-1, scoped_addr, &scoped_addr_len));
  97. MAKE_VALGRIND_HAPPY();
  98. return 0;
  99. }
  100. #define GOOD_ADDR_LIST(X) \
  101. X("::") \
  102. X("::1") \
  103. X("fe80::1") \
  104. X("fe80::") \
  105. X("fe80::2acf:daff:fedd:342a") \
  106. X("fe80:0:0:0:2acf:daff:fedd:342a") \
  107. X("fe80:0:0:0:2acf:daff:1.2.3.4") \
  108. X("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") \
  109. #define BAD_ADDR_LIST(X) \
  110. X(":::1") \
  111. X("abcde::1") \
  112. X("fe80:0:0:0:2acf:daff:fedd:342a:5678") \
  113. X("fe80:0:0:0:2acf:daff:abcd:1.2.3.4") \
  114. X("fe80:0:0:2acf:daff:1.2.3.4.5") \
  115. X("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255.255") \
  116. #define TEST_GOOD(ADDR) \
  117. ASSERT(0 == uv_inet_pton(AF_INET6, ADDR, &addr)); \
  118. ASSERT(0 == uv_inet_pton(AF_INET6, ADDR "%en1", &addr)); \
  119. ASSERT(0 == uv_inet_pton(AF_INET6, ADDR "%%%%", &addr)); \
  120. ASSERT(0 == uv_inet_pton(AF_INET6, ADDR "%en1:1.2.3.4", &addr)); \
  121. #define TEST_BAD(ADDR) \
  122. ASSERT(0 != uv_inet_pton(AF_INET6, ADDR, &addr)); \
  123. ASSERT(0 != uv_inet_pton(AF_INET6, ADDR "%en1", &addr)); \
  124. ASSERT(0 != uv_inet_pton(AF_INET6, ADDR "%%%%", &addr)); \
  125. ASSERT(0 != uv_inet_pton(AF_INET6, ADDR "%en1:1.2.3.4", &addr)); \
  126. TEST_IMPL(ip6_pton) {
  127. struct in6_addr addr;
  128. GOOD_ADDR_LIST(TEST_GOOD)
  129. BAD_ADDR_LIST(TEST_BAD)
  130. MAKE_VALGRIND_HAPPY();
  131. return 0;
  132. }
  133. #undef GOOD_ADDR_LIST
  134. #undef BAD_ADDR_LIST
  135. #ifdef SIN6_LEN
  136. TEST_IMPL(ip6_sin6_len) {
  137. struct sockaddr_in6 s;
  138. ASSERT(uv_ip6_addr("::", 0, &s) < 0);
  139. ASSERT(s.sin6_len == sizeof(s));
  140. return 0;
  141. }
  142. #endif