Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

156 lines
4.4 KiB

  1. // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs)
  2. //
  3. // Copyright (c) 1985-2000 Microsoft Corporation
  4. //
  5. // This file is part of the Microsoft Research IPv6 Network Protocol Stack.
  6. // You should have received a copy of the Microsoft End-User License Agreement
  7. // for this software along with this release; see the file "license.txt".
  8. // If not, please see http://www.research.microsoft.com/msripv6/license.htm,
  9. // or write to Microsoft Research, One Microsoft Way, Redmond, WA 98052-6399.
  10. //
  11. // Abstract:
  12. //
  13. // Helper functions for dealing with the IPv6 protocol stack.
  14. // Really these should be in a library of some kind.
  15. //
  16. #include "dpsp.h"
  17. HANDLE Handle;
  18. //
  19. // Initialize this module.
  20. // Returns FALSE for failure.
  21. //
  22. int
  23. InitIPv6Library(void)
  24. {
  25. //
  26. // Get a handle to the IPv6 device.
  27. // We will use this for ioctl operations.
  28. //
  29. Handle = CreateFileW(WIN_IPV6_DEVICE_NAME,
  30. 0, // access mode
  31. FILE_SHARE_READ | FILE_SHARE_WRITE,
  32. NULL, // security attributes
  33. OPEN_EXISTING,
  34. 0, // flags & attributes
  35. NULL); // template file
  36. return Handle != INVALID_HANDLE_VALUE;
  37. }
  38. DWORD
  39. ForEachInterface(void (*func)(IPV6_INFO_INTERFACE *, void *, void *, void *), void *Context1, void *Context2, void *Context3)
  40. {
  41. IPV6_QUERY_INTERFACE Query;
  42. IPV6_INFO_INTERFACE *IF;
  43. u_int InfoSize, BytesReturned;
  44. DWORD dwErr = NO_ERROR;
  45. InfoSize = sizeof *IF + 2 * MAX_LINK_LAYER_ADDRESS_LENGTH;
  46. IF = (IPV6_INFO_INTERFACE *) MemAlloc(InfoSize);
  47. if (IF == NULL) {
  48. return GetLastError();
  49. }
  50. Query.Index = (u_int) -1;
  51. for (;;) {
  52. if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_INTERFACE,
  53. &Query, sizeof Query,
  54. IF, InfoSize, &BytesReturned,
  55. NULL)) {
  56. dwErr = GetLastError();
  57. break;
  58. }
  59. if (Query.Index != (u_int) -1) {
  60. if ((BytesReturned < sizeof *IF) ||
  61. (IF->Length < sizeof *IF) ||
  62. (BytesReturned != IF->Length +
  63. ((IF->LocalLinkLayerAddress != 0) ?
  64. IF->LinkLayerAddressLength : 0) +
  65. ((IF->RemoteLinkLayerAddress != 0) ?
  66. IF->LinkLayerAddressLength : 0))) {
  67. // inconsistent interface info length
  68. return ERROR_INVALID_DATA;
  69. }
  70. (*func)(IF, Context1, Context2, Context3);
  71. }
  72. else {
  73. if (BytesReturned != sizeof IF->Next) {
  74. // inconsistent interface info length
  75. dwErr = ERROR_INVALID_DATA;
  76. break;
  77. }
  78. }
  79. if (IF->Next.Index == (u_int) -1)
  80. break;
  81. Query = IF->Next;
  82. }
  83. MemFree(IF);
  84. return dwErr;
  85. }
  86. void
  87. ForEachAddress(IPV6_INFO_INTERFACE *IF,
  88. void (*func)(IPV6_INFO_INTERFACE *IF, IPV6_INFO_ADDRESS *, void *),
  89. void *Context)
  90. {
  91. IPV6_QUERY_ADDRESS Query;
  92. IPV6_INFO_ADDRESS ADE;
  93. u_int BytesReturned;
  94. DWORD dwErr;
  95. Query.IF = IF->This;
  96. Query.Address = in6addr_any;
  97. for (;;) {
  98. if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_ADDRESS,
  99. &Query, sizeof Query,
  100. &ADE, sizeof ADE, &BytesReturned,
  101. NULL)) {
  102. // bad address
  103. dwErr = GetLastError();
  104. DPF(0, "Query address failed with error = %d\n", dwErr);
  105. return;
  106. }
  107. if (!IN6_ADDR_EQUAL(&Query.Address, &in6addr_any)) {
  108. if (BytesReturned != sizeof ADE) {
  109. // inconsistent address info length
  110. return;
  111. }
  112. (*func)(IF, &ADE, Context);
  113. }
  114. else {
  115. if (BytesReturned != sizeof ADE.Next) {
  116. // inconsistent address info length
  117. return;
  118. }
  119. }
  120. if (IN6_ADDR_EQUAL(&ADE.Next.Address, &in6addr_any))
  121. break;
  122. Query = ADE.Next;
  123. }
  124. }
  125. UINT
  126. JoinEnumGroup(SOCKET sSocket, UINT ifindex)
  127. {
  128. IPV6_MREQ mreq;
  129. mreq.ipv6mr_interface = ifindex;
  130. mreq.ipv6mr_multiaddr = in6addr_multicast;
  131. return setsockopt(sSocket, IPPROTO_IPV6, IPV6_JOIN_GROUP,
  132. (CHAR FAR *)&mreq, sizeof mreq);
  133. }