// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) // // Copyright (c) 1985-2000 Microsoft Corporation // // This file is part of the Microsoft Research IPv6 Network Protocol Stack. // You should have received a copy of the Microsoft End-User License Agreement // for this software along with this release; see the file "license.txt". // If not, please see http://www.research.microsoft.com/msripv6/license.htm, // or write to Microsoft Research, One Microsoft Way, Redmond, WA 98052-6399. // // Abstract: // // Helper functions for dealing with the IPv6 protocol stack. // Really these should be in a library of some kind. // #include "dpsp.h" HANDLE Handle; // // Initialize this module. // Returns FALSE for failure. // int InitIPv6Library(void) { // // Get a handle to the IPv6 device. // We will use this for ioctl operations. // Handle = CreateFileW(WIN_IPV6_DEVICE_NAME, 0, // access mode FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, // security attributes OPEN_EXISTING, 0, // flags & attributes NULL); // template file return Handle != INVALID_HANDLE_VALUE; } DWORD ForEachInterface(void (*func)(IPV6_INFO_INTERFACE *, void *, void *, void *), void *Context1, void *Context2, void *Context3) { IPV6_QUERY_INTERFACE Query; IPV6_INFO_INTERFACE *IF; u_int InfoSize, BytesReturned; DWORD dwErr = NO_ERROR; InfoSize = sizeof *IF + 2 * MAX_LINK_LAYER_ADDRESS_LENGTH; IF = (IPV6_INFO_INTERFACE *) MemAlloc(InfoSize); if (IF == NULL) { return GetLastError(); } Query.Index = (u_int) -1; for (;;) { if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_INTERFACE, &Query, sizeof Query, IF, InfoSize, &BytesReturned, NULL)) { dwErr = GetLastError(); break; } if (Query.Index != (u_int) -1) { if ((BytesReturned < sizeof *IF) || (IF->Length < sizeof *IF) || (BytesReturned != IF->Length + ((IF->LocalLinkLayerAddress != 0) ? IF->LinkLayerAddressLength : 0) + ((IF->RemoteLinkLayerAddress != 0) ? IF->LinkLayerAddressLength : 0))) { // inconsistent interface info length return ERROR_INVALID_DATA; } (*func)(IF, Context1, Context2, Context3); } else { if (BytesReturned != sizeof IF->Next) { // inconsistent interface info length dwErr = ERROR_INVALID_DATA; break; } } if (IF->Next.Index == (u_int) -1) break; Query = IF->Next; } MemFree(IF); return dwErr; } void ForEachAddress(IPV6_INFO_INTERFACE *IF, void (*func)(IPV6_INFO_INTERFACE *IF, IPV6_INFO_ADDRESS *, void *), void *Context) { IPV6_QUERY_ADDRESS Query; IPV6_INFO_ADDRESS ADE; u_int BytesReturned; DWORD dwErr; Query.IF = IF->This; Query.Address = in6addr_any; for (;;) { if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_ADDRESS, &Query, sizeof Query, &ADE, sizeof ADE, &BytesReturned, NULL)) { // bad address dwErr = GetLastError(); DPF(0, "Query address failed with error = %d\n", dwErr); return; } if (!IN6_ADDR_EQUAL(&Query.Address, &in6addr_any)) { if (BytesReturned != sizeof ADE) { // inconsistent address info length return; } (*func)(IF, &ADE, Context); } else { if (BytesReturned != sizeof ADE.Next) { // inconsistent address info length return; } } if (IN6_ADDR_EQUAL(&ADE.Next.Address, &in6addr_any)) break; Query = ADE.Next; } } UINT JoinEnumGroup(SOCKET sSocket, UINT ifindex) { IPV6_MREQ mreq; mreq.ipv6mr_interface = ifindex; mreq.ipv6mr_multiaddr = in6addr_multicast; return setsockopt(sSocket, IPPROTO_IPV6, IPV6_JOIN_GROUP, (CHAR FAR *)&mreq, sizeof mreq); }