157 lines
4.4 KiB
C
157 lines
4.4 KiB
C
|
// -*- 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);
|
||
|
}
|