|
|
//=============================================================================
// Copyright (c) 2001 Microsoft Corporation
// Abstract:
// This module implements IPv6 configuration commands.
//
// This code is based off ipv6.c from Rich Draves
//=============================================================================
#include "precomp.h"
#pragma hdrstop
HANDLE Handle = INVALID_HANDLE_VALUE; BOOL AdminAccess = TRUE;
#define IPv6_MINIMUM_MTU 1280
DWORD SetString( IN HKEY hKey, IN LPCTSTR lpName, IN PWCHAR pwcValue );
PWCHAR FormatTime( IN DWORD dwLife, OUT PWCHAR pwszLife ) { DWORD dwDays, dwHours, dwMinutes; PWCHAR pwszNext = pwszLife; if (dwLife == INFINITE_LIFETIME) { swprintf(pwszNext, L"%s", TOKEN_VALUE_INFINITE); return pwszLife; }
if (dwLife < MINUTES) goto FormatSeconds;
if (dwLife < HOURS) goto FormatMinutes;
if (dwLife < DAYS) goto FormatHours;
dwDays = dwLife / DAYS; pwszNext += swprintf(pwszNext, L"%ud", dwDays); dwLife -= dwDays * DAYS;
FormatHours: dwHours = dwLife / HOURS; if (dwHours != 0) pwszNext += swprintf(pwszNext, L"%uh", dwHours); dwLife -= dwHours * HOURS;
FormatMinutes: dwMinutes = dwLife / MINUTES; if (dwMinutes != 0) pwszNext += swprintf(pwszNext, L"%um", dwMinutes); dwLife -= dwMinutes * MINUTES;
if (dwLife == 0) { return pwszLife; } FormatSeconds: swprintf(pwszNext, L"%us", dwLife); return pwszLife; }
DWORD OpenIPv6( VOID ) { WSADATA wsaData; BOOL bInstalled; DWORD dwErr = NO_ERROR;
if (Handle != INVALID_HANDLE_VALUE) { return NO_ERROR; }
dwErr = IsIpv6Installed(&bInstalled); if (dwErr != NO_ERROR) { return dwErr; } if (!bInstalled) { DisplayMessage(g_hModule, EMSG_PROTO_NOT_INSTALLED); return ERROR_SUPPRESS_OUTPUT; }
//
// We initialize Winsock just so we can have access
// to WSAStringToAddress and WSAAddressToString.
//
if (WSAStartup(MAKEWORD(2, 0), &wsaData)) { return WSAGetLastError(); }
//
// First request write access.
// This will fail if the process does not have local Administrator privs.
//
Handle = CreateFileW(WIN_IPV6_DEVICE_NAME, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, // security attributes
OPEN_EXISTING, 0, // flags & attributes
NULL); // template file
if (Handle == INVALID_HANDLE_VALUE) { //
// We will not have Administrator access to the stack.
//
AdminAccess = FALSE;
Handle = CreateFileW(WIN_IPV6_DEVICE_NAME, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, // security attributes
OPEN_EXISTING, 0, // flags & attributes
NULL); // template file
if (Handle == INVALID_HANDLE_VALUE) { return GetLastError(); } }
return NO_ERROR; }
//////////////////////////////////////////////////////////////////////////////
// Generic interface-related functions
//////////////////////////////////////////////////////////////////////////////
IPV6_INFO_INTERFACE * GetInterfaceByIpv6IfIndex( IN DWORD dwIfIndex ) { IPV6_QUERY_INTERFACE Query; IPV6_INFO_INTERFACE *IF; DWORD dwInfoSize, dwBytesReturned;
Query.Index = dwIfIndex;
dwInfoSize = sizeof *IF + 2 * MAX_LINK_LAYER_ADDRESS_LENGTH; IF = (IPV6_INFO_INTERFACE *) MALLOC(dwInfoSize); if (IF == NULL) { return NULL; }
if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_INTERFACE, &Query, sizeof Query, IF, dwInfoSize, &dwBytesReturned, NULL)) { FREE(IF); return NULL; }
if ((dwBytesReturned < sizeof *IF) || (IF->Length < sizeof *IF) || (dwBytesReturned != IF->Length + ((IF->LocalLinkLayerAddress != 0) ? IF->LinkLayerAddressLength : 0) + ((IF->RemoteLinkLayerAddress != 0) ? IF->LinkLayerAddressLength : 0))) {
FREE(IF); return NULL; }
return IF; }
DWORD GetInterfaceByFriendlyName( IN PWCHAR pwszFriendlyName, IN IP_ADAPTER_ADDRESSES *pAdapterInfo, IN BOOL bPersistent, OUT IPV6_INFO_INTERFACE **pIF ) { DWORD dwIfIndex; DWORD dwErr;
//
// TODO: we cannot yet query an interface by GUID, so we can't
// yet work for a persistent interface which is not currently present.
//
dwErr = MapFriendlyNameToIpv6IfIndex(pwszFriendlyName, pAdapterInfo, &dwIfIndex); if (dwErr != NO_ERROR) { return dwErr; }
*pIF = GetInterfaceByIpv6IfIndex(dwIfIndex); return (*pIF)? NO_ERROR : ERROR_NOT_FOUND; }
DWORD MyGetAdaptersInfo( OUT PIP_ADAPTER_ADDRESSES *ppAdapterInfo ) { IP_ADAPTER_ADDRESSES *pAdapterInfo; DWORD dwErr, BufLen = 0; DWORD Flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST;
dwErr = GetAdaptersAddresses(AF_INET6, Flags, NULL, NULL, &BufLen); if (dwErr != ERROR_BUFFER_OVERFLOW) { return dwErr; } pAdapterInfo = (IP_ADAPTER_ADDRESSES *) MALLOC(BufLen); if (pAdapterInfo == NULL) { return GetLastError(); } dwErr = GetAdaptersAddresses(AF_INET6, Flags, NULL, pAdapterInfo, &BufLen); if (dwErr != NO_ERROR) { FREE(pAdapterInfo); return dwErr; }
*ppAdapterInfo = pAdapterInfo; return NO_ERROR; }
DWORD ForEachPersistentInterface( IN DWORD (*pfnFunc)(IPV6_INFO_INTERFACE *,PIP_ADAPTER_ADDRESSES,DWORD,FORMAT), IN PIP_ADAPTER_ADDRESSES pAdapterInfo, IN FORMAT Format ) { IPV6_PERSISTENT_QUERY_INTERFACE Query; IPV6_INFO_INTERFACE *IF; DWORD dwInfoSize, dwBytesReturned; DWORD dwCount = 0;
dwInfoSize = sizeof *IF + 2 * MAX_LINK_LAYER_ADDRESS_LENGTH; IF = (IPV6_INFO_INTERFACE *) MALLOC(dwInfoSize); if (IF == NULL) { return 0; }
for (Query.RegistryIndex = 0; ; Query.RegistryIndex++) { if (!DeviceIoControl(Handle, IOCTL_IPV6_PERSISTENT_QUERY_INTERFACE, &Query, sizeof Query, IF, dwInfoSize, &dwBytesReturned, NULL)) { break; }
if ((dwBytesReturned < sizeof *IF) || (IF->Length < sizeof *IF) || (dwBytesReturned != IF->Length + ((IF->LocalLinkLayerAddress != 0) ? IF->LinkLayerAddressLength : 0) + ((IF->RemoteLinkLayerAddress != 0) ? IF->LinkLayerAddressLength : 0))) {
break; }
if ((*pfnFunc)(IF, pAdapterInfo, dwCount, Format) == NO_ERROR) { dwCount++; } }
FREE(IF);
return dwCount; }
DWORD ForEachInterface( IN DWORD (*pfnFunc)(IPV6_INFO_INTERFACE *,PIP_ADAPTER_ADDRESSES,DWORD,FORMAT), IN PIP_ADAPTER_ADDRESSES pAdapterInfo, IN FORMAT Format, IN BOOL bPersistent ) { IPV6_QUERY_INTERFACE Query; IPV6_INFO_INTERFACE *IF; DWORD dwInfoSize, dwBytesReturned; DWORD dwCount = 0;
if (bPersistent) { return ForEachPersistentInterface(pfnFunc, pAdapterInfo, Format); }
dwInfoSize = sizeof *IF + 2 * MAX_LINK_LAYER_ADDRESS_LENGTH; IF = (IPV6_INFO_INTERFACE *) MALLOC(dwInfoSize); if (IF == NULL) { return 0; }
Query.Index = (u_int) -1;
for (;;) { if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_INTERFACE, &Query, sizeof Query, IF, dwInfoSize, &dwBytesReturned, NULL)) { break; }
if (Query.Index != (u_int) -1) {
if ((dwBytesReturned < sizeof *IF) || (IF->Length < sizeof *IF) || (dwBytesReturned != IF->Length + ((IF->LocalLinkLayerAddress != 0) ? IF->LinkLayerAddressLength : 0) + ((IF->RemoteLinkLayerAddress != 0) ? IF->LinkLayerAddressLength : 0))) {
break; }
if ((*pfnFunc)(IF, pAdapterInfo, dwCount, Format) == NO_ERROR) { dwCount++; } } else { if (dwBytesReturned != sizeof IF->Next) { break; } }
if (IF->Next.Index == (u_int) -1) break; Query = IF->Next; }
FREE(IF);
return dwCount; }
//////////////////////////////////////////////////////////////////////////////
// Site prefix table functions
//////////////////////////////////////////////////////////////////////////////
DWORD ForEachSitePrefix( IN DWORD (*pfnFunc)(IPV6_INFO_SITE_PREFIX *,FORMAT,DWORD,IP_ADAPTER_ADDRESSES *), IN FORMAT Format, IN IP_ADAPTER_ADDRESSES *pAdapterInfo ) { IPV6_QUERY_SITE_PREFIX Query, NextQuery; IPV6_INFO_SITE_PREFIX SPE; DWORD dwBytesReturned; DWORD dwCount = 0;
NextQuery.IF.Index = 0;
for (;;) { Query = NextQuery;
if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_SITE_PREFIX, &Query, sizeof Query, &SPE, sizeof SPE, &dwBytesReturned, NULL)) { break; }
NextQuery = SPE.Query;
if (Query.IF.Index != 0) {
SPE.Query = Query; if ((*pfnFunc)(&SPE, Format, dwCount, pAdapterInfo) == NO_ERROR) { dwCount++; } }
if (NextQuery.IF.Index == 0) { break; } }
return dwCount; }
DWORD PrintSitePrefix( IN IPV6_INFO_SITE_PREFIX *SPE, IN FORMAT Format, IN DWORD dwCount, IN IP_ADAPTER_ADDRESSES *pAdapterInfo ) { DWORD dwErr; WCHAR *FriendlyName; WCHAR wszValid[64]; dwErr = MapIpv6IfIndexToFriendlyName(SPE->Query.IF.Index, pAdapterInfo, &FriendlyName); if (dwErr != NO_ERROR) { return dwErr; }
FormatTime(SPE->ValidLifetime, wszValid); if (Format == FORMAT_DUMP) { DisplayMessageT(DMP_IPV6_ADD_SITEPREFIX); DisplayMessageT(DMP_STRING_ARG, TOKEN_PREFIX, FormatIPv6Prefix(&SPE->Query.Prefix, SPE->Query.PrefixLength)); DisplayMessageT(DMP_QUOTED_STRING_ARG, TOKEN_INTERFACE, FriendlyName); DisplayMessageT(DMP_STRING_ARG, TOKEN_LIFETIME, wszValid); DisplayMessage(g_hModule, MSG_NEWLINE); } else { if (!dwCount) { DisplayMessage(g_hModule, MSG_IPV6_SITE_PREFIX_HDR); }
DisplayMessage(g_hModule, MSG_IPV6_SITE_PREFIX, FormatIPv6Prefix(&SPE->Query.Prefix, SPE->Query.PrefixLength), SPE->ValidLifetime, FriendlyName); // wszValid, FriendlyName);
}
return NO_ERROR; }
DWORD QuerySitePrefixTable( IN FORMAT Format ) { DWORD dwErr, dwCount = 0; IP_ADAPTER_ADDRESSES *pAdapterInfo;
dwErr = OpenIPv6(); if (dwErr != NO_ERROR) { return dwErr; }
dwErr = MyGetAdaptersInfo(&pAdapterInfo); if (dwErr != ERROR_NO_DATA) { if (dwErr == NO_ERROR) { dwCount = ForEachSitePrefix(PrintSitePrefix, Format, pAdapterInfo); FREE(pAdapterInfo); } else if (dwErr == ERROR_NO_DATA) { dwErr = NO_ERROR; } } if (!dwCount && (Format != FORMAT_DUMP)) { DisplayMessage(g_hModule, MSG_IP_NO_ENTRIES); }
return dwErr; }
//////////////////////////////////////////////////////////////////////////////
// General global parameters functions
//////////////////////////////////////////////////////////////////////////////
DWORD QueryGlobalParameters( IN FORMAT Format, IN BOOL bPersistent ) { IPV6_GLOBAL_PARAMETERS Params; DWORD dwBytesReturned, dwErr;
dwErr = OpenIPv6(); if (dwErr != NO_ERROR) { return dwErr; }
if (Format != FORMAT_DUMP) { // DisplayMessage(g_hModule, (bPersistent)? MSG_PERSISTENT : MSG_ACTIVE);
}
if (!DeviceIoControl(Handle, (bPersistent)? IOCTL_IPV6_PERSISTENT_QUERY_GLOBAL_PARAMETERS : IOCTL_IPV6_QUERY_GLOBAL_PARAMETERS, NULL, 0, &Params, sizeof Params, &dwBytesReturned, NULL) || (dwBytesReturned != sizeof Params)) { return GetLastError(); }
if (Format == FORMAT_DUMP) { DisplayMessageT(DMP_IPV6_SET_GLOBAL); DisplayMessageT(DMP_INTEGER_ARG, TOKEN_DEFAULTCURHOPLIMIT, Params.DefaultCurHopLimit); DisplayMessageT(DMP_INTEGER_ARG, TOKEN_NEIGHBORCACHELIMIT, Params.NeighborCacheLimit); DisplayMessageT(DMP_INTEGER_ARG, TOKEN_DESTINATIONCACHELIMIT, Params.RouteCacheLimit); DisplayMessageT(DMP_INTEGER_ARG, TOKEN_REASSEMBLYLIMIT, Params.ReassemblyLimit); DisplayMessage(g_hModule, MSG_NEWLINE); } else { DisplayMessage(g_hModule, MSG_IPV6_GLOBAL_PARAMETERS, Params.DefaultCurHopLimit, Params.NeighborCacheLimit, Params.RouteCacheLimit); // Params.RouteCacheLimit, Params.ReassemblyLimit);
}
return NO_ERROR; }
DWORD QueryPrivacyParameters( IN FORMAT Format, IN BOOL bPersistent ) { IPV6_GLOBAL_PARAMETERS Params; DWORD dwBytesReturned, dwErr; WCHAR wszValid[64], wszPreferred[64], wszRegenerate[64]; WCHAR wszMaxRandom[64], wszRandom[64];
dwErr = OpenIPv6(); if (dwErr != NO_ERROR) { return dwErr; }
if (Format != FORMAT_DUMP) { // DisplayMessage(g_hModule, (bPersistent)? MSG_PERSISTENT : MSG_ACTIVE);
}
if (!DeviceIoControl(Handle, (bPersistent)? IOCTL_IPV6_PERSISTENT_QUERY_GLOBAL_PARAMETERS : IOCTL_IPV6_QUERY_GLOBAL_PARAMETERS, NULL, 0, &Params, sizeof Params, &dwBytesReturned, NULL) || (dwBytesReturned != sizeof Params)) { return GetLastError(); }
FormatTime(Params.MaxAnonValidLifetime, wszValid); FormatTime(Params.MaxAnonPreferredLifetime, wszPreferred); FormatTime(Params.AnonRegenerateTime, wszRegenerate); FormatTime(Params.MaxAnonRandomTime, wszMaxRandom); FormatTime(Params.AnonRandomTime, wszRandom); if (Format == FORMAT_DUMP) { DisplayMessageT(DMP_IPV6_SET_PRIVACY); DisplayMessageT(DMP_STRING_ARG, TOKEN_STATE, ((Params.UseAnonymousAddresses == USE_ANON_NO)? TOKEN_VALUE_DISABLED : TOKEN_VALUE_ENABLED)); DisplayMessageT(DMP_INTEGER_ARG, TOKEN_MAXDADATTEMPTS, Params.MaxAnonDADAttempts); DisplayMessageT(DMP_STRING_ARG, TOKEN_MAXVALIDLIFETIME, wszValid); DisplayMessageT(DMP_STRING_ARG, TOKEN_MAXPREFERREDLIFETIME, wszPreferred); DisplayMessageT(DMP_STRING_ARG, TOKEN_REGENERATETIME, wszRegenerate); DisplayMessageT(DMP_STRING_ARG, TOKEN_MAXRANDOMTIME, wszMaxRandom); DisplayMessageT(DMP_STRING_ARG, TOKEN_RANDOMTIME, wszRandom); DisplayMessage(g_hModule, MSG_NEWLINE); } else { DisplayMessage( g_hModule, MSG_IPV6_PRIVACY_PARAMETERS, ((Params.UseAnonymousAddresses == USE_ANON_NO) ? TOKEN_VALUE_DISABLED : TOKEN_VALUE_ENABLED), Params.MaxAnonDADAttempts,
Params.MaxAnonValidLifetime, Params.MaxAnonPreferredLifetime, Params.AnonRegenerateTime, Params.MaxAnonRandomTime, Params.AnonRandomTime); }
return NO_ERROR; }
DWORD UpdateGlobalParameters( IN DWORD dwDefaultCurHopLimit, IN DWORD dwNeighborCacheLimit, IN DWORD dwRouteCacheLimit, IN DWORD dwReassemblyLimit, IN BOOL bPersistent ) { IPV6_GLOBAL_PARAMETERS Params; DWORD dwBytesReturned; DWORD dwErr;
dwErr = OpenIPv6(); if (dwErr != NO_ERROR) { return dwErr; }
Params.DefaultCurHopLimit = dwDefaultCurHopLimit; Params.UseAnonymousAddresses = (u_int) -1; Params.MaxAnonDADAttempts = (u_int) -1; Params.MaxAnonValidLifetime = (u_int) -1; Params.MaxAnonPreferredLifetime = (u_int) -1; Params.AnonRegenerateTime = (u_int) -1; Params.MaxAnonRandomTime = (u_int) -1; Params.AnonRandomTime = (u_int) -1; Params.NeighborCacheLimit = dwNeighborCacheLimit; Params.RouteCacheLimit = dwRouteCacheLimit; Params.ReassemblyLimit = dwReassemblyLimit;
dwErr = ERROR_OKAY;
if (bPersistent) { if (!DeviceIoControl(Handle, IOCTL_IPV6_PERSISTENT_UPDATE_GLOBAL_PARAMETERS, &Params, sizeof Params, NULL, 0, &dwBytesReturned, NULL)) { dwErr = GetLastError(); } }
if (!DeviceIoControl(Handle, IOCTL_IPV6_UPDATE_GLOBAL_PARAMETERS, &Params, sizeof Params, NULL, 0, &dwBytesReturned, NULL)) { if (dwErr == ERROR_OKAY) { dwErr = GetLastError(); } }
return dwErr; }
DWORD UpdatePrivacyParameters( IN DWORD dwUseAnonymousAddresses, IN DWORD dwMaxDadAttempts, IN DWORD dwMaxValidLifetime, IN DWORD dwMaxPrefLifetime, IN DWORD dwRegenerateTime, IN DWORD dwMaxRandomTime, IN DWORD dwRandomTime, IN BOOL bPersistent ) { IPV6_GLOBAL_PARAMETERS Params; DWORD dwBytesReturned; DWORD dwErr;
dwErr = OpenIPv6(); if (dwErr != NO_ERROR) { return dwErr; }
Params.DefaultCurHopLimit = -1; Params.UseAnonymousAddresses = dwUseAnonymousAddresses; Params.MaxAnonDADAttempts = dwMaxDadAttempts; Params.MaxAnonValidLifetime = dwMaxValidLifetime; Params.MaxAnonPreferredLifetime = dwMaxPrefLifetime; Params.AnonRegenerateTime = dwRegenerateTime; Params.MaxAnonRandomTime = dwMaxRandomTime; Params.AnonRandomTime = dwRandomTime; Params.NeighborCacheLimit = -1; Params.RouteCacheLimit = -1; Params.ReassemblyLimit = (u_int) -1;
dwErr = ERROR_OKAY;
if (bPersistent) { if (!DeviceIoControl(Handle, IOCTL_IPV6_PERSISTENT_UPDATE_GLOBAL_PARAMETERS, &Params, sizeof Params, NULL, 0, &dwBytesReturned, NULL)) { dwErr = GetLastError(); } }
if (!DeviceIoControl(Handle, IOCTL_IPV6_UPDATE_GLOBAL_PARAMETERS, &Params, sizeof Params, NULL, 0, &dwBytesReturned, NULL)) { if (dwErr == ERROR_OKAY) { dwErr = GetLastError(); } }
return dwErr; }
//////////////////////////////////////////////////////////////////////////////
// Mobility-related functions
//////////////////////////////////////////////////////////////////////////////
DWORD ForEachBinding( IN DWORD (*pfnFunc)(IPV6_INFO_BINDING_CACHE *) ) { IPV6_QUERY_BINDING_CACHE Query, NextQuery; IPV6_INFO_BINDING_CACHE BCE; DWORD dwBytesReturned; DWORD dwCount = 0;
NextQuery.HomeAddress = in6addr_any;
for (;;) { Query = NextQuery;
if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_BINDING_CACHE, &Query, sizeof Query, &BCE, sizeof BCE, &dwBytesReturned, NULL)) { DisplayMessage(g_hModule, IPV6_MESSAGE_126, FormatIPv6Address(&Query.HomeAddress, 0)); break; }
NextQuery = BCE.Query;
if (!IN6_ADDR_EQUAL(&Query.HomeAddress, &in6addr_any)) { BCE.Query = Query; if ((*pfnFunc)(&BCE) == NO_ERROR) { dwCount++; } }
if (IN6_ADDR_EQUAL(&NextQuery.HomeAddress, &in6addr_any)) { break; } }
return dwCount; }
DWORD PrintBindingCacheEntry( IN IPV6_INFO_BINDING_CACHE *BCE ) { WCHAR wszTime[64]; DisplayMessage(g_hModule, IPV6_MESSAGE_127, FormatIPv6Address(&BCE->HomeAddress, 0));
DisplayMessage(g_hModule, IPV6_MESSAGE_128, FormatIPv6Address(&BCE->CareOfAddress, 0));
DisplayMessage(g_hModule, IPV6_MESSAGE_129, BCE->BindingSeqNumber, BCE->BindingLifetime); // FormatTime(BCE->BindingLifetime, wszTime));
return NO_ERROR; }
DWORD QueryBindingCache( VOID ) { DWORD dwCount, dwErr;
dwErr = OpenIPv6(); if (dwErr != NO_ERROR) { return dwErr; }
dwCount = ForEachBinding(PrintBindingCacheEntry);
if (dwCount == 0) { DisplayMessage(g_hModule, MSG_IP_NO_ENTRIES); }
return NO_ERROR; }
DWORD QueryMobilityParameters( IN FORMAT Format, IN BOOL bPersistent ) { IPV6_GLOBAL_PARAMETERS Params; DWORD dwBytesReturned, dwErr; PWCHAR pwszTempString;
dwErr = OpenIPv6(); if (dwErr != NO_ERROR) { return dwErr; }
if (Format != FORMAT_DUMP) { // DisplayMessage(g_hModule, (bPersistent)? MSG_PERSISTENT : MSG_ACTIVE);
}
if (!DeviceIoControl(Handle, (bPersistent)? IOCTL_IPV6_PERSISTENT_QUERY_GLOBAL_PARAMETERS : IOCTL_IPV6_QUERY_GLOBAL_PARAMETERS, NULL, 0, &Params, sizeof Params, &dwBytesReturned, NULL) || (dwBytesReturned != sizeof Params)) { return GetLastError(); }
pwszTempString = Params.MobilitySecurity ? TOKEN_VALUE_ENABLED : TOKEN_VALUE_DISABLED;
if (Format == FORMAT_DUMP) { DisplayMessageT(DMP_IPV6_SET_MOBILITY); DisplayMessageT(DMP_STRING_ARG, TOKEN_SECURITY, pwszTempString); DisplayMessageT(DMP_INTEGER_ARG, TOKEN_BINDINGCACHELIMIT, Params.BindingCacheLimit); DisplayMessage(g_hModule, MSG_NEWLINE); } else { DisplayMessage(g_hModule, MSG_IPV6_MOBILITY_PARAMETERS, pwszTempString, Params.BindingCacheLimit); }
return NO_ERROR; }
DWORD UpdateMobilityParameters( IN DWORD dwSecurity, IN DWORD dwBindingCacheLimit, IN BOOL bPersistent ) { DWORD dwBytesReturned; DWORD dwErr;
dwErr = OpenIPv6(); if (dwErr != NO_ERROR) { return dwErr; }
dwErr = ERROR_OKAY;
if ((dwBindingCacheLimit != -1) || (dwSecurity != -1)) { IPV6_GLOBAL_PARAMETERS Params;
Params.DefaultCurHopLimit = (u_int) -1; Params.UseAnonymousAddresses = (u_int) -1; Params.MaxAnonDADAttempts = (u_int) -1; Params.MaxAnonValidLifetime = (u_int) -1; Params.MaxAnonPreferredLifetime = (u_int) -1; Params.AnonRegenerateTime = (u_int) -1; Params.MaxAnonRandomTime = (u_int) -1; Params.AnonRandomTime = (u_int) -1; Params.NeighborCacheLimit = (u_int) -1; Params.RouteCacheLimit = (u_int) -1; Params.ReassemblyLimit = (u_int) -1; Params.BindingCacheLimit = dwBindingCacheLimit; Params.MobilitySecurity = dwSecurity;
if (bPersistent) { if (!DeviceIoControl(Handle, IOCTL_IPV6_PERSISTENT_UPDATE_GLOBAL_PARAMETERS, &Params, sizeof Params, NULL, 0, &dwBytesReturned, NULL)) { dwErr = GetLastError(); } }
if (!DeviceIoControl(Handle, IOCTL_IPV6_UPDATE_GLOBAL_PARAMETERS, &Params, sizeof Params, NULL, 0, &dwBytesReturned, NULL)) { if (dwErr == ERROR_OKAY) { dwErr = GetLastError(); } } }
return dwErr; }
//////////////////////////////////////////////////////////////////////////////
// Prefix policy table functions
//////////////////////////////////////////////////////////////////////////////
DWORD ForEachPrefixPolicy( IN DWORD (*pfnFunc)(IPV6_INFO_PREFIX_POLICY *,FORMAT,DWORD), IN FORMAT Format, IN BOOL bPersistent ) { IPV6_QUERY_PREFIX_POLICY Query; IPV6_INFO_PREFIX_POLICY PPE; DWORD dwBytesReturned, dwCount = 0;
Query.PrefixLength = (u_int) -1;
for (;;) { if (!DeviceIoControl(Handle, (bPersistent)? IOCTL_IPV6_PERSISTENT_QUERY_PREFIX_POLICY : IOCTL_IPV6_QUERY_PREFIX_POLICY, &Query, sizeof Query, &PPE, sizeof PPE, &dwBytesReturned, NULL)) { break; }
if (Query.PrefixLength != (u_int) -1) {
if (dwBytesReturned != sizeof PPE) break;
if ((*pfnFunc)(&PPE, Format, dwCount) == NO_ERROR) { dwCount++; } } else { if (dwBytesReturned != sizeof PPE.Next) break; }
if (PPE.Next.PrefixLength == (u_int) -1) break; Query = PPE.Next; }
return dwCount; }
DWORD PrintPrefixPolicyEntry( IN IPV6_INFO_PREFIX_POLICY *PPE, IN FORMAT Format, IN DWORD dwCount ) { if (Format == FORMAT_DUMP) { DisplayMessageT(DMP_IPV6_ADD_PREFIXPOLICY); DisplayMessageT(DMP_STRING_ARG, TOKEN_PREFIX, FormatIPv6Prefix(&PPE->This.Prefix, PPE->This.PrefixLength)); DisplayMessageT(DMP_INTEGER_ARG, TOKEN_PRECEDENCE, PPE->Precedence); DisplayMessageT(DMP_INTEGER_ARG, TOKEN_LABEL, PPE->SrcLabel); DisplayMessage(g_hModule, MSG_NEWLINE); } else { if (!dwCount) { DisplayMessage(g_hModule, MSG_IPV6_PREFIX_POLICY_HDR); }
DisplayMessage(g_hModule, MSG_IPV6_PREFIX_POLICY, FormatIPv6Prefix(&PPE->This.Prefix, PPE->This.PrefixLength), PPE->Precedence, PPE->SrcLabel, PPE->DstLabel); }
return NO_ERROR; }
DWORD QueryPrefixPolicy( IN FORMAT Format, IN BOOL bPersistent ) { DWORD dwCount, dwErr;
dwErr = OpenIPv6(); if (dwErr != NO_ERROR) { return dwErr; }
if (Format != FORMAT_DUMP) { // DisplayMessage(g_hModule, (bPersistent)? MSG_PERSISTENT : MSG_ACTIVE);
}
dwCount = ForEachPrefixPolicy(PrintPrefixPolicyEntry, Format, bPersistent);
if (!dwCount && (Format != FORMAT_DUMP)) { DisplayMessage(g_hModule, MSG_IP_NO_ENTRIES); }
return NO_ERROR; }
DWORD UpdatePrefixPolicy( IN IN6_ADDR *IpAddress, IN DWORD dwPrefixLength, IN DWORD dwPrecedence, IN DWORD dwLabel, IN BOOL bPersistent ) { IPV6_INFO_PREFIX_POLICY Info; DWORD dwBytesReturned, dwErr;
dwErr = OpenIPv6(); if (dwErr != NO_ERROR) { return dwErr; }
Info.This.Prefix = *IpAddress; Info.This.PrefixLength = dwPrefixLength; Info.Precedence = dwPrecedence; Info.SrcLabel = Info.DstLabel = dwLabel;
dwErr = ERROR_OKAY;
if (bPersistent) { if (!DeviceIoControl(Handle, IOCTL_IPV6_PERSISTENT_UPDATE_PREFIX_POLICY, &Info, sizeof Info, NULL, 0, &dwBytesReturned, NULL)) { dwErr = GetLastError(); } }
if (!DeviceIoControl(Handle, IOCTL_IPV6_UPDATE_PREFIX_POLICY, &Info, sizeof Info, NULL, 0, &dwBytesReturned, NULL)) { if (dwErr == ERROR_OKAY) { dwErr = GetLastError(); } }
return dwErr; }
DWORD DeletePrefixPolicy( IN IN6_ADDR *IpAddress, IN DWORD dwPrefixLength, IN BOOL bPersistent ) { IPV6_QUERY_PREFIX_POLICY Query; DWORD dwBytesReturned, dwErr;
dwErr = OpenIPv6(); if (dwErr != NO_ERROR) { return dwErr; }
Query.Prefix = *IpAddress; Query.PrefixLength = dwPrefixLength;
dwErr = ERROR_OKAY;
if (bPersistent) { if (!DeviceIoControl(Handle, IOCTL_IPV6_PERSISTENT_DELETE_PREFIX_POLICY, &Query, sizeof Query, NULL, 0, &dwBytesReturned, NULL)) { dwErr = GetLastError(); } }
if (!DeviceIoControl(Handle, IOCTL_IPV6_DELETE_PREFIX_POLICY, &Query, sizeof Query, NULL, 0, &dwBytesReturned, NULL)) { if (dwErr == ERROR_OKAY) { dwErr = GetLastError(); } }
return dwErr; }
//////////////////////////////////////////////////////////////////////////////
// Address table functions
//////////////////////////////////////////////////////////////////////////////
DWORD ForEachAddress( IN IPV6_INFO_INTERFACE *IF, IN PIP_ADAPTER_ADDRESSES pAdapterInfo, IN FORMAT Format, IN DWORD (*pfnFunc)(IPV6_INFO_INTERFACE *IF, PIP_ADAPTER_ADDRESSES, FORMAT, DWORD, IPV6_INFO_ADDRESS *)) { IPV6_QUERY_ADDRESS Query; IPV6_INFO_ADDRESS ADE; DWORD BytesReturned, dwCount = 0;
Query.IF = IF->This; Query.Address = in6addr_any;
for (;;) { if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_ADDRESS, &Query, sizeof Query, &ADE, sizeof ADE, &BytesReturned, NULL)) { break; }
if (!IN6_ADDR_EQUAL(&Query.Address, &in6addr_any)) {
if (BytesReturned != sizeof ADE) break;
if ((*pfnFunc)(IF, pAdapterInfo, Format, dwCount, &ADE) == NO_ERROR) { dwCount++; } } else { if (BytesReturned != sizeof ADE.Next) break; }
if (IN6_ADDR_EQUAL(&ADE.Next.Address, &in6addr_any)) break; Query = ADE.Next; }
return dwCount; }
PWCHAR GetDadState( IN DWORD dwDadState, OUT BOOL *bDynamic ) { PWCHAR pwszTemp; DWORD dwMsg = 0; static WCHAR wszDadState[128];
switch (dwDadState) { case DAD_STATE_INVALID: dwMsg = STRING_INVALID; break; case DAD_STATE_DUPLICATE: dwMsg = STRING_DUPLICATE; break; case DAD_STATE_TENTATIVE: dwMsg = STRING_TENTATIVE; break; case DAD_STATE_DEPRECATED: dwMsg = STRING_DEPRECATED; break; case DAD_STATE_PREFERRED: dwMsg = STRING_PREFERRED; break; default: swprintf(wszDadState, L"%u", dwDadState); *bDynamic = FALSE; return wszDadState; }
*bDynamic = TRUE; pwszTemp = MakeString(g_hModule, dwMsg); return pwszTemp; }
PWCHAR GetAddressType( IN DWORD dwScope, IN DWORD dwPrefixConf, IN DWORD dwIidConf ) { DWORD dwMsg = 0;
if ((dwScope == ADE_LINK_LOCAL) && (dwPrefixConf == PREFIX_CONF_WELLKNOWN) && (dwIidConf == IID_CONF_WELLKNOWN)) {
dwMsg = STRING_LOOPBACK;
} else if ((dwScope == ADE_LINK_LOCAL) && (dwPrefixConf == PREFIX_CONF_WELLKNOWN) && (dwIidConf == IID_CONF_LL_ADDRESS)) { dwMsg = STRING_LINK;
} else if ((dwPrefixConf == PREFIX_CONF_MANUAL) && (dwIidConf == IID_CONF_MANUAL)) {
dwMsg = STRING_MANUAL;
} else if ((dwPrefixConf == PREFIX_CONF_RA) && (dwIidConf == IID_CONF_LL_ADDRESS)) {
dwMsg = STRING_PUBLIC;
} else if ((dwPrefixConf == PREFIX_CONF_RA) && (dwIidConf == IID_CONF_RANDOM)) {
dwMsg = STRING_ANONYMOUS;
} else if ((dwPrefixConf == PREFIX_CONF_DHCP) && (dwIidConf == IID_CONF_DHCP)) {
dwMsg = STRING_DHCP; } else { dwMsg = STRING_OTHER; }
return MakeString(g_hModule, dwMsg); }
PWCHAR GetScopeNoun( IN DWORD dwScope, OUT BOOL *bDynamic ) { PWCHAR pwszTemp; DWORD dwMsg = 0; static WCHAR wszScopeLevel[128];
switch (dwScope) { case ADE_INTERFACE_LOCAL: dwMsg = STRING_INTERFACE; break; case ADE_LINK_LOCAL: dwMsg = STRING_LINK; break; case ADE_SUBNET_LOCAL: dwMsg = STRING_SUBNET; break; case ADE_ADMIN_LOCAL: dwMsg = STRING_ADMIN; break; case ADE_SITE_LOCAL: dwMsg = STRING_SITE; break; case ADE_ORG_LOCAL: dwMsg = STRING_ORG; break; case ADE_GLOBAL: dwMsg = STRING_GLOBAL; break; default: swprintf(wszScopeLevel, L"%u", dwScope); *bDynamic = FALSE; return wszScopeLevel; }
*bDynamic = TRUE; pwszTemp = MakeString(g_hModule, dwMsg); return pwszTemp; }
DWORD rgdwPrefixConfMsg[] = { 0, STRING_MANUAL, STRING_WELLKNOWN, STRING_DHCP, STRING_RA }; #define PREFIX_CONF_MSG_COUNT (sizeof(rgdwPrefixConfMsg)/sizeof(DWORD))
DWORD rgdwIidConfMsg[] = { 0, STRING_MANUAL, STRING_WELLKNOWN, STRING_DHCP, STRING_LL_ADDRESS, STRING_RANDOM }; #define IID_CONF_MSG_COUNT (sizeof(rgdwIidConfMsg)/sizeof(DWORD))
DWORD PrintMulticastAddress( IN IPV6_INFO_INTERFACE *IF, IN PIP_ADAPTER_ADDRESSES pAdapterInfo, IN FORMAT Format, IN DWORD dwCount, IN IPV6_INFO_ADDRESS *ADE ) { BOOL bDynamicDadState, bDynamicScope; PWCHAR pwszDadState, pwszScope, pwszFriendlyName; DWORD dwErr = NO_ERROR; PWCHAR pwszLastReporter, pwszNever; WCHAR wszTime[64];
if (ADE->Type != ADE_MULTICAST) { return ERROR_NO_DATA; }
if (dwCount == 0) { dwErr = MapIpv6IfIndexToFriendlyName(IF->This.Index, pAdapterInfo, &pwszFriendlyName); if (dwErr != NO_ERROR) { return dwErr; }
DisplayMessage(g_hModule, (Format == FORMAT_VERBOSE)? MSG_IPV6_ADDRESS_HDR_VERBOSE : MSG_IPV6_MULTICAST_ADDRESS_HDR, IF->This.Index, pwszFriendlyName); }
pwszScope = GetScopeNoun(ADE->Scope, &bDynamicScope);
pwszNever = MakeString(g_hModule, STRING_NEVER); pwszLastReporter = MakeString(g_hModule, (ADE->MCastFlags & 0x02)? STRING_YES : STRING_NO);
if (Format == FORMAT_VERBOSE) { DisplayMessage(g_hModule, MSG_IPV6_MULTICAST_ADDRESS_VERBOSE, pwszScope, FormatIPv6Address(&ADE->This.Address, 0), ADE->MCastRefCount, (ADE->MCastFlags & 0x01) ? ADE->MCastTimer : 0, pwszLastReporter); } else { DisplayMessage(g_hModule, MSG_IPV6_MULTICAST_ADDRESS, pwszScope, FormatIPv6Address(&ADE->This.Address, 0), ADE->MCastRefCount, (ADE->MCastFlags & 0x01) ? FormatTime(ADE->MCastTimer, wszTime) : pwszNever, pwszLastReporter); }
FreeString(pwszLastReporter); FreeString(pwszNever);
if (bDynamicScope) { FreeString(pwszScope); }
return dwErr; }
DWORD PrintAddress( IN IPV6_INFO_INTERFACE *IF, IN PIP_ADAPTER_ADDRESSES pAdapterInfo, IN FORMAT Format, IN DWORD dwCount, IN IPV6_INFO_ADDRESS *ADE ) { DWORD dwPrefixConf, dwInterfaceIdConf; BOOL bDynamicDadState, bDynamicScope, bDynamicType; PWCHAR pwszDadState, pwszScope, pwszFriendlyName, pwszType; WCHAR wszValid[64], wszPreferred[64]; DWORD dwErr = NO_ERROR;
if (Format != FORMAT_VERBOSE) { //
// Suppress invalid addresses.
//
if ((ADE->Type == ADE_UNICAST) && (ADE->DADState == DAD_STATE_INVALID)) { return ERROR_NO_DATA; }
//
// Multicast addresses are handled by PrintMulticastAddress()
// instead.
//
if (ADE->Type == ADE_MULTICAST) { return ERROR_NO_DATA; } }
if (dwCount == 0) { dwErr = MapIpv6IfIndexToFriendlyName(IF->This.Index, pAdapterInfo, &pwszFriendlyName); if (dwErr != NO_ERROR) { return dwErr; }
DisplayMessage(g_hModule, ((Format == FORMAT_VERBOSE)? MSG_IPV6_ADDRESS_HDR_VERBOSE : MSG_IPV6_ADDRESS_HDR), IF->This.Index, pwszFriendlyName); }
pwszScope = GetScopeNoun(ADE->Scope, &bDynamicScope);
switch (ADE->Type) { case ADE_UNICAST:
pwszDadState = GetDadState(ADE->DADState, &bDynamicDadState);
pwszType = GetAddressType(ADE->Scope, ADE->PrefixConf, ADE->InterfaceIdConf);
DisplayMessage(g_hModule, ((Format == FORMAT_VERBOSE)? MSG_IPV6_UNICAST_ADDRESS_VERBOSE : MSG_IPV6_UNICAST_ADDRESS), pwszType, pwszDadState, FormatIPv6Address(&ADE->This.Address, 0), ADE->ValidLifetime, // FormatTime(ADE->ValidLifetime, wszValid),
ADE->PreferredLifetime, // FormatTime(ADE->PreferredLifetime, wszPreferred),
pwszScope);
if (bDynamicDadState) { FreeString(pwszDadState); } FreeString(pwszType);
if (Format == FORMAT_VERBOSE) { //
// Show prefix origin / interface id origin
//
DisplayMessage(g_hModule, MSG_IPV6_PREFIX_ORIGIN);
dwPrefixConf = ADE->PrefixConf; if ((dwPrefixConf == PREFIX_CONF_OTHER) || (dwPrefixConf >= PREFIX_CONF_MSG_COUNT)) {
DisplayMessage(g_hModule, MSG_IPV6_INTEGER, dwPrefixConf); } else { DisplayMessage(g_hModule, rgdwPrefixConfMsg[dwPrefixConf]); } DisplayMessage(g_hModule, MSG_NEWLINE);
DisplayMessage(g_hModule, MSG_IPV6_IID_ORIGIN); dwInterfaceIdConf = ADE->InterfaceIdConf; if ((dwInterfaceIdConf == IID_CONF_OTHER) || (dwInterfaceIdConf >= IID_CONF_MSG_COUNT)) {
DisplayMessage(g_hModule, MSG_IPV6_INTEGER, dwInterfaceIdConf); } else { DisplayMessage(g_hModule, rgdwIidConfMsg[dwInterfaceIdConf]); } DisplayMessage(g_hModule, MSG_NEWLINE); }
break;
case ADE_ANYCAST: DisplayMessage(g_hModule, ((Format == FORMAT_VERBOSE)? MSG_IPV6_ANYCAST_ADDRESS_VERBOSE : MSG_IPV6_ANYCAST_ADDRESS), FormatIPv6Address(&ADE->This.Address, 0), pwszScope);
break;
case ADE_MULTICAST: default: dwErr = ERROR_NO_DATA; break; }
if (bDynamicScope) { FreeString(pwszScope); }
return dwErr; }
DWORD PrintAddressTable( IN IPV6_INFO_INTERFACE *IF, IN PIP_ADAPTER_ADDRESSES pAdapterInfo, IN DWORD dwIfCount, IN FORMAT Format ) { DWORD dwCount = ForEachAddress(IF, pAdapterInfo, Format, PrintAddress); return (dwCount > 0)? NO_ERROR : ERROR_NO_DATA; }
DWORD PrintMulticastAddressTable( IN IPV6_INFO_INTERFACE *IF, IN PIP_ADAPTER_ADDRESSES pAdapterInfo, IN DWORD dwIfCount, IN FORMAT Format ) { DWORD dwCount = ForEachAddress(IF, pAdapterInfo, Format, PrintMulticastAddress); return (dwCount > 0)? NO_ERROR : ERROR_NO_DATA; }
DWORD QueryAddressTable( IN PWCHAR pwszIfFriendlyName, IN FORMAT Format, IN BOOL bPersistent ) { DWORD dwErr, dwCount = 0; IP_ADAPTER_ADDRESSES *pAdapterInfo; IPV6_INFO_INTERFACE *IF;
dwErr = OpenIPv6(); if (dwErr != NO_ERROR) { return dwErr; }
if (Format != FORMAT_DUMP) { // DisplayMessage(g_hModule, (bPersistent)? MSG_PERSISTENT : MSG_ACTIVE);
}
dwErr = MyGetAdaptersInfo(&pAdapterInfo); if (dwErr != ERROR_NO_DATA) { if (dwErr == NO_ERROR) { if (pwszIfFriendlyName == NULL) { dwCount = ForEachInterface(PrintAddressTable, pAdapterInfo, Format, bPersistent); } else { dwErr = GetInterfaceByFriendlyName(pwszIfFriendlyName, pAdapterInfo, bPersistent, &IF); if (dwErr == NO_ERROR) { PrintAddressTable(IF, pAdapterInfo, 0, Format); FREE(IF); } }
FREE(pAdapterInfo); } else if (dwErr == ERROR_NO_DATA) { dwErr = NO_ERROR; } } if (!dwCount && (Format != FORMAT_DUMP)) { DisplayMessage(g_hModule, MSG_IP_NO_ENTRIES); }
return dwErr; }
DWORD QueryMulticastAddressTable( IN PWCHAR pwszIfFriendlyName, IN FORMAT Format ) { DWORD dwErr, dwCount = 0; IP_ADAPTER_ADDRESSES *pAdapterInfo; IPV6_INFO_INTERFACE *IF;
dwErr = OpenIPv6(); if (dwErr != NO_ERROR) { return dwErr; }
dwErr = MyGetAdaptersInfo(&pAdapterInfo); if (dwErr != ERROR_NO_DATA) { if (dwErr == NO_ERROR) { if (pwszIfFriendlyName == NULL) { ForEachInterface(PrintMulticastAddressTable, pAdapterInfo, Format, FALSE); } else { dwErr = GetInterfaceByFriendlyName(pwszIfFriendlyName, pAdapterInfo, FALSE, &IF); if (dwErr == NO_ERROR) { dwErr = PrintMulticastAddressTable(IF, pAdapterInfo, 0, Format); FREE(IF); } }
FREE(pAdapterInfo); } else if (dwErr == ERROR_NO_DATA) { dwErr = NO_ERROR; } }
return dwErr; }
DWORD UpdateAddress( IN PWCHAR pwszIfFriendlyName, IN IN6_ADDR *pipAddress, IN DWORD dwType, IN DWORD dwValidLifetime, IN DWORD dwPreferredLifetime, IN BOOL bPersistent ) { IPV6_UPDATE_ADDRESS Update; DWORD dwBytesReturned, dwErr; PIP_ADAPTER_ADDRESSES pAdapterInfo;
dwErr = OpenIPv6(); if (dwErr != NO_ERROR) { return dwErr; }
dwErr = MyGetAdaptersInfo(&pAdapterInfo); if (dwErr != NO_ERROR) { return dwErr; }
dwErr = MapFriendlyNameToIpv6IfIndex(pwszIfFriendlyName, pAdapterInfo, &Update.This.IF.Index); FREE(pAdapterInfo); if (dwErr != NO_ERROR) { return dwErr; }
Update.This.Address = *pipAddress; Update.Type = dwType; Update.PrefixConf = PREFIX_CONF_MANUAL; Update.InterfaceIdConf = IID_CONF_MANUAL; Update.ValidLifetime = dwValidLifetime; Update.PreferredLifetime = dwPreferredLifetime;
dwErr = ERROR_OKAY;
if (bPersistent) { if (!DeviceIoControl(Handle, IOCTL_IPV6_PERSISTENT_UPDATE_ADDRESS, &Update, sizeof Update, NULL, 0, &dwBytesReturned, NULL)) { dwErr = GetLastError(); } }
if (!DeviceIoControl(Handle, IOCTL_IPV6_UPDATE_ADDRESS, &Update, sizeof Update, NULL, 0, &dwBytesReturned, NULL)) { if (dwErr == ERROR_OKAY) { dwErr = GetLastError(); } }
return dwErr; }
//////////////////////////////////////////////////////////////////////////////
// Interface table functions
//////////////////////////////////////////////////////////////////////////////
DWORD RenewViaReconnect( IN IPV6_INFO_INTERFACE *IF, IN PIP_ADAPTER_ADDRESSES pAdapterInfo, IN DWORD dwCount, IN FORMAT Format ) { DWORD dwBytesReturned;
if (!DeviceIoControl(Handle, IOCTL_IPV6_RENEW_INTERFACE, &IF->This, sizeof IF->This, NULL, 0, &dwBytesReturned, NULL)) { return GetLastError(); }
return NO_ERROR; }
DWORD RenewInterface( IN PWCHAR wszIfFriendlyName ) { DWORD dwErr; BOOL PokeService = FALSE; dwErr = OpenIPv6(); if (dwErr != NO_ERROR) { return dwErr; }
if (wszIfFriendlyName == NULL) { ForEachInterface(RenewViaReconnect, NULL, FALSE, FALSE); PokeService = TRUE; } else { IP_ADAPTER_ADDRESSES *pAdapterInfo;
dwErr = MyGetAdaptersInfo(&pAdapterInfo); if (dwErr == NO_ERROR) { IPV6_INFO_INTERFACE *IF;
dwErr = GetInterfaceByFriendlyName(wszIfFriendlyName, pAdapterInfo, FALSE, &IF); FREE(pAdapterInfo); if (dwErr != NO_ERROR) { return dwErr; } dwErr = RenewViaReconnect(IF, NULL, 0, FALSE); //
// Poke the 6to4 service if it manages the interface being renewed.
//
PokeService = (IF->Type == IPV6_IF_TYPE_TUNNEL_6TO4) || (IF->Type == IPV6_IF_TYPE_TUNNEL_TEREDO) || (IF->Type == IPV6_IF_TYPE_TUNNEL_AUTO); FREE(IF); } else if (dwErr == ERROR_NO_DATA) { dwErr = NO_ERROR; } }
if (PokeService) { Ip6to4PokeService(); } return dwErr; }
DWORD dwMediaSenseMsg[] = { STRING_DISCONNECTED, STRING_RECONNECTED, STRING_CONNECTED, }; #define MEDIA_SENSE_MSG_COUNT (sizeof(dwMediaSenseMsg)/sizeof(DWORD))
DWORD PrintInterface( IN IPV6_INFO_INTERFACE *IF, IN PIP_ADAPTER_ADDRESSES pAdapterInfo, IN DWORD dwCount, IN FORMAT Format ) { PWCHAR pwszFriendlyName, pwszTemp; DWORD dwErr, dwMsg, dwScope; WCHAR wszReachable[64], wszBaseReachable[64], wszRetransTimer[64]; PIP_ADAPTER_ADDRESSES pIf; CHAR szGuid[41]; dwErr = MapGuidToFriendlyName(NULL, &IF->This.Guid, pAdapterInfo, &pwszFriendlyName); if (dwErr != NO_ERROR) { return dwErr; }
if (IF->MediaStatus < MEDIA_SENSE_MSG_COUNT) { dwMsg = dwMediaSenseMsg[IF->MediaStatus]; } else { dwMsg = STRING_UNKNOWN; }
switch (Format) { case FORMAT_DUMP: switch (IF->Type) { case IPV6_IF_TYPE_TUNNEL_6OVER4: DisplayMessageT(DMP_IPV6_ADD_6OVER4TUNNEL); DisplayMessageT(DMP_QUOTED_STRING_ARG, TOKEN_INTERFACE, pwszFriendlyName); if (IF->LocalLinkLayerAddress != 0) { DisplayMessageT(DMP_STRING_ARG, TOKEN_LOCALADDRESS, FormatLinkLayerAddress(IF->LinkLayerAddressLength, (char *)IF + IF->LocalLinkLayerAddress)); } DisplayMessage(g_hModule, MSG_NEWLINE); break; case IPV6_IF_TYPE_TUNNEL_V6V4: DisplayMessageT(DMP_IPV6_ADD_V6V4TUNNEL); DisplayMessageT(DMP_QUOTED_STRING_ARG, TOKEN_INTERFACE, pwszFriendlyName); if (IF->LocalLinkLayerAddress != 0) { DisplayMessageT(DMP_STRING_ARG, TOKEN_LOCALADDRESS, FormatLinkLayerAddress(IF->LinkLayerAddressLength, (char *)IF + IF->LocalLinkLayerAddress)); } if (IF->RemoteLinkLayerAddress != 0) { DisplayMessageT(DMP_STRING_ARG, TOKEN_REMOTEADDRESS, FormatLinkLayerAddress(IF->LinkLayerAddressLength, (char *)IF + IF->RemoteLinkLayerAddress)); } if (IF->NeighborDiscovers) { DisplayMessageT(DMP_STRING_ARG, TOKEN_NEIGHBORDISCOVERY, TOKEN_VALUE_ENABLED); } DisplayMessage(g_hModule, MSG_NEWLINE); break; }
DisplayMessageT(DMP_IPV6_SET_INTERFACE); DisplayMessageT(DMP_QUOTED_STRING_ARG, TOKEN_INTERFACE, pwszFriendlyName); DisplayMessageT(DMP_INTEGER_ARG, TOKEN_METRIC, IF->Preference); DisplayMessageT(DMP_INTEGER_ARG, TOKEN_MTU, IF->LinkMTU); DisplayMessage(g_hModule, MSG_NEWLINE);
break;
case FORMAT_NORMAL: if (dwCount == 0) { DisplayMessage(g_hModule, MSG_IPV6_INTERFACE_HDR); }
pwszTemp = MakeString(g_hModule, dwMsg);
DisplayMessage(g_hModule, MSG_IPV6_INTERFACE, IF->This.Index, IF->Preference, IF->LinkMTU, pwszTemp, pwszFriendlyName);
FreeString(pwszTemp);
break;
case FORMAT_VERBOSE:
DisplayMessage(g_hModule, MSG_SEPARATOR);
ForEachAddress(IF, pAdapterInfo, FORMAT_NORMAL, PrintAddress);
//
// Get extra interface information.
//
pIf = MapIfIndexToAdapter(AF_INET6, IF->This.Index, pAdapterInfo);
pwszTemp = MakeString(g_hModule, dwMsg);
ConvertGuidToStringA(&IF->This.Guid, szGuid);
DisplayMessage(g_hModule, MSG_IPV6_INTERFACE_VERBOSE, szGuid, pwszTemp, IF->Preference, IF->LinkMTU, IF->TrueLinkMTU, IF->CurHopLimit, IF->ReachableTime, // FormatTime(IF->ReachableTime, wszReachable),
IF->BaseReachableTime, // FormatTime(IF->BaseReachableTime, wszBaseReachable),
IF->RetransTimer, // FormatTime(IF->RetransTimer, wszRetransTimer),
IF->DupAddrDetectTransmits, (pIf)? pIf->DnsSuffix : L"" // , pwszFriendlyName
);
FreeString(pwszTemp);
for (dwScope = ADE_LINK_LOCAL; dwScope < ADE_GLOBAL; dwScope++) { DWORD Expected = 0;
//
// Always print link & site.
//
if ((dwScope != ADE_LINK_LOCAL) && (dwScope != ADE_SITE_LOCAL)) { Expected = IF->ZoneIndices[dwScope + 1]; }
if (IF->ZoneIndices[dwScope] != Expected) { BOOL bDynamic;
pwszTemp = GetScopeNoun(dwScope, &bDynamic);
DisplayMessage(g_hModule, MSG_IPV6_INTERFACE_SCOPE, pwszTemp, IF->ZoneIndices[dwScope]);
if (bDynamic) { FreeString(pwszTemp); } } }
DisplayMessage(g_hModule, MSG_IPV6_ND_ENABLED); DisplayMessage(g_hModule, (IF->NeighborDiscovers ? STRING_YES : STRING_NO)); DisplayMessage(g_hModule, MSG_NEWLINE); DisplayMessage(g_hModule, MSG_IPV6_SENDS_RAS); DisplayMessage(g_hModule, (IF->Advertises ? STRING_YES : STRING_NO)); DisplayMessage(g_hModule, MSG_NEWLINE); DisplayMessage(g_hModule, MSG_IPV6_FORWARDS); DisplayMessage(g_hModule, (IF->Forwards ? STRING_YES : STRING_NO)); DisplayMessage(g_hModule, MSG_NEWLINE);
if (IF->LocalLinkLayerAddress != 0) { DisplayMessage(g_hModule, MSG_IPV6_LL_ADDRESS, FormatLinkLayerAddress(IF->LinkLayerAddressLength, (char *)IF + IF->LocalLinkLayerAddress)); } if (IF->RemoteLinkLayerAddress != 0) { DisplayMessage(g_hModule, MSG_IPV6_REMOTE_LL_ADDRESS, FormatLinkLayerAddress(IF->LinkLayerAddressLength, (char *)IF + IF->RemoteLinkLayerAddress)); }
break; }
return NO_ERROR; }
DWORD QueryInterface( IN PWCHAR pwszIfFriendlyName, IN FORMAT Format, IN BOOL bPersistent ) { IPV6_INFO_INTERFACE *IF; PIP_ADAPTER_ADDRESSES pAdapterInfo; DWORD dwErr;
dwErr = OpenIPv6(); if (dwErr != NO_ERROR) { return dwErr; }
if (Format != FORMAT_DUMP) { // DisplayMessage(g_hModule, (bPersistent)? MSG_PERSISTENT : MSG_ACTIVE);
}
dwErr = MyGetAdaptersInfo(&pAdapterInfo); if (dwErr == ERROR_NO_DATA) { if (Format != FORMAT_DUMP) { DisplayMessage(g_hModule, MSG_IP_NO_ENTRIES); } return NO_ERROR; } if (dwErr != NO_ERROR) { return dwErr; }
if (pwszIfFriendlyName == NULL) { ForEachInterface(PrintInterface, pAdapterInfo, Format, bPersistent); } else { dwErr = GetInterfaceByFriendlyName(pwszIfFriendlyName, pAdapterInfo, bPersistent, &IF); if (dwErr == NO_ERROR) { dwErr = PrintInterface(IF, pAdapterInfo, 0, Format); FREE(IF); } }
FREE(pAdapterInfo); return dwErr; }
DWORD DeleteInterface( IN PWCHAR pwszIfFriendlyName, IN BOOL bPersistent ) { IPV6_QUERY_INTERFACE Query; IPV6_INFO_INTERFACE *IF; IP_ADAPTER_ADDRESSES *pAdapterInfo; DWORD dwBytesReturned, dwErr;
dwErr = OpenIPv6(); if (dwErr != NO_ERROR) { return dwErr; }
dwErr = MyGetAdaptersInfo(&pAdapterInfo); if (dwErr != NO_ERROR) { return dwErr; }
dwErr = MapFriendlyNameToIpv6IfIndex(pwszIfFriendlyName, pAdapterInfo, &Query.Index); FREE(pAdapterInfo); if (dwErr != NO_ERROR) { return dwErr; }
dwErr = ERROR_OKAY;
if (!DeviceIoControl(Handle, (bPersistent) ? IOCTL_IPV6_PERSISTENT_DELETE_INTERFACE : IOCTL_IPV6_DELETE_INTERFACE, &Query, sizeof Query, NULL, 0, &dwBytesReturned, NULL)) { if (dwErr == ERROR_OKAY) { dwErr = GetLastError(); } }
return dwErr; }
#define KEY_TCPIP6_IF L"System\\CurrentControlSet\\Services\\Tcpip6\\Parameters\\Interfaces"
DWORD SetFriendlyName( IN GUID *pGuid, IN PWCHAR pwszFriendlyName ) { DWORD dwErr; HKEY hInterfaces = NULL, hIf = NULL; UNICODE_STRING usGuid;
dwErr = RtlStringFromGUID(pGuid, &usGuid); if (!NT_SUCCESS(dwErr)) { return dwErr; }
dwErr = RegOpenKeyExW(HKEY_LOCAL_MACHINE, KEY_TCPIP6_IF, 0, GENERIC_READ, &hInterfaces); if (dwErr != NO_ERROR) { goto Cleanup; }
dwErr = RegOpenKeyExW(hInterfaces, usGuid.Buffer, 0, GENERIC_WRITE, &hIf); if (dwErr != NO_ERROR) { goto Cleanup; }
dwErr = SetString(hIf, L"FriendlyName", pwszFriendlyName);
Cleanup: if (hInterfaces) { RegCloseKey(hInterfaces); } if (hIf) { RegCloseKey(hIf); } RtlFreeUnicodeString(&usGuid);
return dwErr; }
DWORD AddTunnelInterface( IN PWCHAR pwszFriendlyName, IN IN_ADDR *pipLocalAddr, IN IN_ADDR *pipRemoteAddr, IN DWORD dwType, IN DWORD dwDiscovery, IN BOOL bPersistent ) { struct { IPV6_INFO_INTERFACE Info; IN_ADDR SrcAddr; IN_ADDR DstAddr; } Create; IPV6_QUERY_INTERFACE Result; DWORD dwBytesReturned, dwErr;
dwErr = OpenIPv6(); if (dwErr != NO_ERROR) { return dwErr; }
//
// TODO: use pwszFriendlyName when persistent config is ready
//
IPV6_INIT_INFO_INTERFACE(&Create.Info); Create.Info.Type = dwType; Create.Info.NeighborDiscovers = dwDiscovery; Create.Info.RouterDiscovers = dwDiscovery; Create.Info.LinkLayerAddressLength = sizeof(IN_ADDR); if (pipLocalAddr != NULL) { Create.SrcAddr = *pipLocalAddr; Create.Info.LocalLinkLayerAddress = (u_int) ((char *)&Create.SrcAddr - (char *)&Create.Info); } if (pipRemoteAddr != NULL) { Create.DstAddr = *pipRemoteAddr; Create.Info.RemoteLinkLayerAddress = (u_int) ((char *)&Create.DstAddr - (char *)&Create.Info); }
dwErr = ERROR_OKAY;
if (!DeviceIoControl(Handle, (bPersistent) ? IOCTL_IPV6_PERSISTENT_CREATE_INTERFACE : IOCTL_IPV6_CREATE_INTERFACE, &Create, sizeof Create, &Result, sizeof Result, &dwBytesReturned, NULL) || (dwBytesReturned != sizeof Result)) { dwErr = GetLastError(); } else if (bPersistent) { SetFriendlyName(&Result.Guid, pwszFriendlyName); }
return dwErr; }
DWORD UpdateInterface( IN PWCHAR pwszIfFriendlyName, IN DWORD dwForwarding, IN DWORD dwAdvertises, IN DWORD dwMtu, IN DWORD dwSiteId, IN DWORD dwMetric, IN BOOL bPersistent ) { IPV6_INFO_INTERFACE Update; DWORD dwBytesReturned, dwErr; PIP_ADAPTER_ADDRESSES pAdapterInfo;
dwErr = OpenIPv6(); if (dwErr != NO_ERROR) { return dwErr; }
dwErr = MyGetAdaptersInfo(&pAdapterInfo); if (dwErr != NO_ERROR) { return dwErr; }
IPV6_INIT_INFO_INTERFACE(&Update);
dwErr = MapFriendlyNameToIpv6IfIndex(pwszIfFriendlyName, pAdapterInfo, &Update.This.Index); FREE(pAdapterInfo); if (dwErr != NO_ERROR) { return dwErr; }
Update.Advertises = dwAdvertises; Update.Forwards = dwForwarding; Update.LinkMTU = dwMtu; Update.Preference = dwMetric; Update.ZoneIndices[ADE_SITE_LOCAL] = dwSiteId;
dwErr = ERROR_OKAY;
if (bPersistent) { if (!DeviceIoControl(Handle, IOCTL_IPV6_PERSISTENT_UPDATE_INTERFACE, &Update, sizeof Update, NULL, 0, &dwBytesReturned, NULL)) { dwErr = GetLastError(); } }
if (!DeviceIoControl(Handle, IOCTL_IPV6_UPDATE_INTERFACE, &Update, sizeof Update, NULL, 0, &dwBytesReturned, NULL)) { if (dwErr == ERROR_OKAY) { dwErr = GetLastError(); } }
return dwErr; }
//////////////////////////////////////////////////////////////////////////////
// Neighbor cache functions
//////////////////////////////////////////////////////////////////////////////
DWORD PrintNeighborCacheEntry( IN IPV6_INFO_NEIGHBOR_CACHE *NCE, IN PIP_ADAPTER_ADDRESSES pAdapterInfo, IN DWORD dwCount ) { DWORD dwErr; PWCHAR pwszLinkLayerAddress = L""; PWCHAR pwszUnreachable;
if (NCE->NDState != ND_STATE_INCOMPLETE) { pwszLinkLayerAddress = FormatLinkLayerAddress( NCE->LinkLayerAddressLength, (u_char *)(NCE + 1)); }
if (!dwCount) { PWCHAR pwszFriendlyName;
dwErr = MapIpv6IfIndexToFriendlyName(NCE->Query.IF.Index, pAdapterInfo, &pwszFriendlyName); if (dwErr != NO_ERROR) { return dwErr; }
DisplayMessage(g_hModule, MSG_IPV6_NEIGHBOR_CACHE_HDR, NCE->Query.IF.Index, pwszFriendlyName); }
pwszUnreachable = MakeString(g_hModule, MSG_IPV6_NEIGHBOR_UNREACHABLE);
DisplayMessage(g_hModule, MSG_IPV6_NEIGHBOR_CACHE_ENTRY, FormatIPv6Address(&NCE->Query.Address, 0), ((NCE->IsUnreachable)? pwszUnreachable : pwszLinkLayerAddress)); FreeString(pwszUnreachable);
switch (NCE->NDState) { case ND_STATE_INCOMPLETE: DisplayMessage(g_hModule, MSG_IPV6_NEIGHBOR_INCOMPLETE); break;
case ND_STATE_PROBE: DisplayMessage(g_hModule, MSG_IPV6_NEIGHBOR_PROBE); break;
case ND_STATE_DELAY: DisplayMessage(g_hModule, MSG_IPV6_NEIGHBOR_DELAY); break;
case ND_STATE_STALE: DisplayMessage(g_hModule, MSG_IPV6_NEIGHBOR_STALE); break;
case ND_STATE_REACHABLE: DisplayMessage(g_hModule, MSG_IPV6_NEIGHBOR_REACHABLE, NCE->ReachableTimer / 1000); break;
case ND_STATE_PERMANENT: DisplayMessage(g_hModule, MSG_IPV6_NEIGHBOR_PERMANENT); break;
default: DisplayMessage(g_hModule, MSG_IPV6_NEIGHBOR_UNKNOWN, NCE->NDState); break; }
if (NCE->IsRouter) { DisplayMessage(g_hModule, MSG_IPV6_NEIGHBOR_ISROUTER); }
DisplayMessage(g_hModule, MSG_NEWLINE);
return NO_ERROR; }
DWORD ForEachNeighborCacheEntry( IN IPV6_INFO_INTERFACE *IF, IN PIP_ADAPTER_ADDRESSES pAdapterInfo, IN DWORD (*pfnFunc)(IPV6_INFO_NEIGHBOR_CACHE *,PIP_ADAPTER_ADDRESSES,DWORD) ) { IPV6_QUERY_NEIGHBOR_CACHE Query, NextQuery; IPV6_INFO_NEIGHBOR_CACHE *NCE; DWORD dwInfoSize, dwBytesReturned; DWORD dwCount = 0;
dwInfoSize = sizeof *NCE + MAX_LINK_LAYER_ADDRESS_LENGTH; NCE = (IPV6_INFO_NEIGHBOR_CACHE *) MALLOC(dwInfoSize); if (NCE == NULL) { return 0; }
NextQuery.IF = IF->This; NextQuery.Address = in6addr_any;
for (;;) { Query = NextQuery;
if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_NEIGHBOR_CACHE, &Query, sizeof Query, NCE, dwInfoSize, &dwBytesReturned, NULL)) { return dwCount; }
NextQuery = NCE->Query;
if (!IN6_ADDR_EQUAL(&Query.Address, &in6addr_any)) {
if ((dwBytesReturned < sizeof *NCE) || (dwBytesReturned != sizeof *NCE + NCE->LinkLayerAddressLength)) { return dwCount; }
NCE->Query = Query; if ((*pfnFunc)(NCE,pAdapterInfo,dwCount) == NO_ERROR) { dwCount++; } }
if (IN6_ADDR_EQUAL(&NextQuery.Address, &in6addr_any)) break; }
FREE(NCE);
return dwCount; }
DWORD PrintNeighborCache( IN IPV6_INFO_INTERFACE *IF, IN PIP_ADAPTER_ADDRESSES pAdapterInfo, IN DWORD dwIfCount, IN FORMAT Format ) { DWORD dwCount = ForEachNeighborCacheEntry(IF, pAdapterInfo, PrintNeighborCacheEntry); return (dwCount > 0)? NO_ERROR : ERROR_NO_DATA; }
IPV6_INFO_NEIGHBOR_CACHE * GetNeighborCacheEntry( IN IPV6_INFO_INTERFACE *IF, IN IN6_ADDR *Address ) { IPV6_QUERY_NEIGHBOR_CACHE Query; IPV6_INFO_NEIGHBOR_CACHE *NCE; DWORD dwInfoSize, dwBytesReturned;
dwInfoSize = sizeof *NCE + MAX_LINK_LAYER_ADDRESS_LENGTH; NCE = (IPV6_INFO_NEIGHBOR_CACHE *) malloc(dwInfoSize); if (NCE == NULL) { return NULL; }
Query.IF = IF->This; Query.Address = *Address;
if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_NEIGHBOR_CACHE, &Query, sizeof Query, NCE, dwInfoSize, &dwBytesReturned, NULL)) { return NULL; }
if ((dwBytesReturned < sizeof *NCE) || (dwBytesReturned != sizeof *NCE + NCE->LinkLayerAddressLength)) { return NULL; }
NCE->Query = Query; return NCE; }
DWORD QueryNeighborCache( IN PWCHAR pwszInterface, IN IN6_ADDR *pipAddress ) { IPV6_INFO_INTERFACE *IF; IPV6_INFO_NEIGHBOR_CACHE *NCE; PIP_ADAPTER_ADDRESSES pAdapterInfo; DWORD dwErr;
dwErr = OpenIPv6(); if (dwErr != NO_ERROR) { return dwErr; }
dwErr = MyGetAdaptersInfo(&pAdapterInfo); if (dwErr != NO_ERROR) { return dwErr; }
if (!pwszInterface) { ForEachInterface(PrintNeighborCache, pAdapterInfo, FORMAT_NORMAL, FALSE); FREE(pAdapterInfo); return NO_ERROR; }
dwErr = GetInterfaceByFriendlyName(pwszInterface, pAdapterInfo, FALSE, &IF); if (dwErr != NO_ERROR) { return dwErr; }
if (!pipAddress) { PrintNeighborCache(IF, pAdapterInfo, 0, FALSE); } else { NCE = GetNeighborCacheEntry(IF, pipAddress); PrintNeighborCacheEntry(NCE, pAdapterInfo, 0); FREE(NCE); }
FREE(IF); FREE(pAdapterInfo); return dwErr; }
DWORD FlushNeighborCacheForInterface( IN IPV6_INFO_INTERFACE *IF, IN PIP_ADAPTER_ADDRESSES pAdapterInfo, IN DWORD dwCount, IN FORMAT Format ) { IPV6_QUERY_NEIGHBOR_CACHE Query; DWORD dwBytesReturned;
Query.IF = IF->This; Query.Address = in6addr_any;
if (!DeviceIoControl(Handle, IOCTL_IPV6_FLUSH_NEIGHBOR_CACHE, &Query, sizeof Query, NULL, 0, &dwBytesReturned, NULL)) { return GetLastError(); }
return NO_ERROR; }
DWORD FlushNeighborCache( IN PWCHAR pwszInterface, IN IN6_ADDR *pipAddress ) { IPV6_QUERY_NEIGHBOR_CACHE Query; DWORD dwBytesReturned, dwErr; PIP_ADAPTER_ADDRESSES pAdapterInfo;
dwErr = OpenIPv6(); if (dwErr != NO_ERROR) { return dwErr; }
if (!pwszInterface) { ForEachInterface(FlushNeighborCacheForInterface, NULL, FORMAT_NORMAL, FALSE); return NO_ERROR; }
dwErr = MyGetAdaptersInfo(&pAdapterInfo); if (dwErr != NO_ERROR) { return dwErr; }
dwErr = MapFriendlyNameToIpv6IfIndex(pwszInterface, pAdapterInfo, &Query.IF.Index); if (dwErr != NO_ERROR) { return dwErr; }
if (pipAddress) { Query.Address = *pipAddress; } else { Query.Address = in6addr_any; }
if (!DeviceIoControl(Handle, IOCTL_IPV6_FLUSH_NEIGHBOR_CACHE, &Query, sizeof Query, NULL, 0, &dwBytesReturned, NULL)) { return GetLastError(); }
return ERROR_OKAY; }
//////////////////////////////////////////////////////////////////////////////
// Destination cache functions
//////////////////////////////////////////////////////////////////////////////
DWORD PrintDestination( IN IPV6_INFO_ROUTE_CACHE *RCE, IN PIP_ADAPTER_ADDRESSES pAdapterInfo, IN DWORD dwCount, IN FORMAT Format ) { DWORD dwErr; PWCHAR pwszTemp; WCHAR wszTime[64]; if (!dwCount) { PWCHAR pwszFriendlyName;
dwErr = MapIpv6IfIndexToFriendlyName(RCE->Query.IF.Index, pAdapterInfo, &pwszFriendlyName); if (dwErr != NO_ERROR) { return dwErr; }
DisplayMessage(g_hModule, ((Format == FORMAT_VERBOSE)? MSG_IPV6_DESTINATION_HDR_VERBOSE : MSG_IPV6_DESTINATION_HDR), RCE->Query.IF.Index, pwszFriendlyName); }
DisplayMessage(g_hModule, ((Format == FORMAT_VERBOSE)? MSG_IPV6_DESTINATION_ENTRY_VERBOSE : MSG_IPV6_DESTINATION_ENTRY), ((RCE->PathMTU == 0)? IPv6_MINIMUM_MTU : RCE->PathMTU), FormatIPv6Address(&RCE->Query.Address, 0)); DisplayMessage(g_hModule, ((Format == FORMAT_VERBOSE)? MSG_IPV6_DESTINATION_NEXTHOP_VERBOSE : MSG_IPV6_DESTINATION_NEXTHOP), FormatIPv6Address(&RCE->NextHopAddress, 0));
if (Format == FORMAT_VERBOSE) {
DisplayMessage(g_hModule, MSG_IPV6_DESTINATION_SOURCE_ADDR, FormatIPv6Address(&RCE->SourceAddress, 0));
pwszTemp = MakeString(g_hModule, ((RCE->Valid)? STRING_NO : STRING_YES)); DisplayMessage(g_hModule, MSG_IPV6_STALE, pwszTemp);
FreeString(pwszTemp); switch (RCE->Flags) { case RCE_FLAG_CONSTRAINED: DisplayMessage(g_hModule, MSG_IPV6_IF_SPECIFIC); break; case RCE_FLAG_CONSTRAINED_SCOPEID: DisplayMessage(g_hModule, MSG_IPV6_ZONE_SPECIFIC); break; }
if (RCE->PMTUProbeTimer != INFINITE_LIFETIME) { DisplayMessage(g_hModule, MSG_IPV6_PMTU_PROBE_TIME, RCE->PMTUProbeTimer/1000); // FormatTime(RCE->PMTUProbeTimer/1000, wszTime));
} if ((RCE->ICMPLastError != 0) && (RCE->ICMPLastError < 10*60*1000)) { DisplayMessage(g_hModule, MSG_IPV6_ICMP_ERROR_TIME, RCE->ICMPLastError/1000); // FormatTime(RCE->ICMPLastError/1000, wszTime));
} if ((RCE->BindingSeqNumber != 0) || (RCE->BindingLifetime != 0) || ! IN6_ADDR_EQUAL(&RCE->CareOfAddress, &in6addr_any)) {
DisplayMessage(g_hModule, MSG_IPV6_CAREOF, FormatIPv6Address(&RCE->CareOfAddress, 0), RCE->BindingSeqNumber, RCE->BindingLifetime); // FormatTime(RCE->BindingLifetime, wszTime));
} }
return NO_ERROR; }
DWORD ForEachDestination( IN IPV6_INFO_INTERFACE *IF, IN PIP_ADAPTER_ADDRESSES pAdapterInfo, IN FORMAT Format, IN DWORD (*pfnFunc)(IPV6_INFO_ROUTE_CACHE *,PIP_ADAPTER_ADDRESSES,DWORD,FORMAT) ) { IPV6_QUERY_ROUTE_CACHE Query, NextQuery; IPV6_INFO_ROUTE_CACHE RCE; DWORD dwInfoSize, dwBytesReturned, dwCount = 0;
NextQuery.IF.Index = 0; NextQuery.Address = in6addr_any;
for (;;) { Query = NextQuery;
if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_ROUTE_CACHE, &Query, sizeof Query, &RCE, sizeof(RCE), &dwBytesReturned, NULL)) { return dwCount; }
NextQuery = RCE.Query;
if (Query.IF.Index == IF->This.Index) { RCE.Query = Query; if ((*pfnFunc)(&RCE,pAdapterInfo,dwCount,Format) == NO_ERROR) { dwCount++; } } else if (dwCount > 0) { //
// Stop if we're done with the desired interface.
//
break; }
if (NextQuery.IF.Index == 0) { break; } }
return dwCount; }
IPV6_INFO_ROUTE_CACHE * GetDestination( IN IPV6_QUERY_INTERFACE *IF, IN IN6_ADDR *Address ) { IPV6_QUERY_ROUTE_CACHE Query; IPV6_INFO_ROUTE_CACHE *RCE; DWORD dwBytesReturned;
Query.IF = *IF; Query.Address = *Address;
RCE = (IPV6_INFO_ROUTE_CACHE *) malloc(sizeof *RCE); if (RCE == NULL) { return NULL; }
if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_ROUTE_CACHE, &Query, sizeof Query, RCE, sizeof *RCE, &dwBytesReturned, NULL)) { return NULL; }
RCE->Query = Query; return RCE; }
DWORD PrintRouteCache( IN IPV6_INFO_INTERFACE *IF, IN PIP_ADAPTER_ADDRESSES pAdapterInfo, IN DWORD dwIfCount, IN FORMAT Format ) { DWORD dwCount = ForEachDestination(IF, pAdapterInfo, Format, PrintDestination); return (dwCount > 0)? NO_ERROR : ERROR_NO_DATA; }
DWORD QueryRouteCache( IN PWCHAR pwszInterface, IN IN6_ADDR *pipAddress, IN FORMAT Format ) { IPV6_INFO_INTERFACE *IF; IPV6_INFO_ROUTE_CACHE *RCE; PIP_ADAPTER_ADDRESSES pAdapterInfo; DWORD dwCount, dwErr;
dwErr = OpenIPv6(); if (dwErr != NO_ERROR) { return dwErr; }
dwErr = MyGetAdaptersInfo(&pAdapterInfo); if (dwErr != NO_ERROR) { return dwErr; }
if (!pwszInterface) { dwCount = ForEachInterface(PrintRouteCache, pAdapterInfo, Format, FALSE); FREE(pAdapterInfo); if (dwCount == 0) { DisplayMessage(g_hModule, MSG_IP_NO_ENTRIES); } return NO_ERROR; }
dwErr = GetInterfaceByFriendlyName(pwszInterface, pAdapterInfo, FALSE, &IF); if (dwErr != NO_ERROR) { return dwErr; }
if (!pipAddress) { if (PrintRouteCache(IF, pAdapterInfo, 0, Format) == ERROR_NO_DATA) { DisplayMessage(g_hModule, MSG_IP_NO_ENTRIES); } } else { RCE = GetDestination(&IF->This, pipAddress); PrintDestination(RCE, pAdapterInfo, 0, Format); FREE(RCE); }
FREE(IF); FREE(pAdapterInfo); return dwErr; }
DWORD FlushRouteCacheForInterface( IN IPV6_INFO_INTERFACE *IF, IN PIP_ADAPTER_ADDRESSES pAdapterInfo, IN DWORD dwCount, IN FORMAT Format ) { IPV6_QUERY_ROUTE_CACHE Query; DWORD dwBytesReturned;
Query.IF = IF->This; Query.Address = in6addr_any;
if (!DeviceIoControl(Handle, IOCTL_IPV6_FLUSH_ROUTE_CACHE, &Query, sizeof Query, NULL, 0, &dwBytesReturned, NULL)) { return GetLastError(); }
return NO_ERROR; }
DWORD FlushRouteCache( IN PWCHAR pwszInterface, IN IN6_ADDR *pipAddress ) { IPV6_QUERY_ROUTE_CACHE Query; DWORD dwBytesReturned, dwErr; PIP_ADAPTER_ADDRESSES pAdapterInfo;
dwErr = OpenIPv6(); if (dwErr != NO_ERROR) { return dwErr; }
if (!pwszInterface) { ForEachInterface(FlushRouteCacheForInterface, NULL, FORMAT_NORMAL, FALSE); return NO_ERROR; }
dwErr = MyGetAdaptersInfo(&pAdapterInfo); if (dwErr != NO_ERROR) { return dwErr; }
dwErr = MapFriendlyNameToIpv6IfIndex(pwszInterface, pAdapterInfo, &Query.IF.Index); if (dwErr != NO_ERROR) { return dwErr; }
if (pipAddress) { Query.Address = *pipAddress; } else { Query.Address = in6addr_any; }
if (!DeviceIoControl(Handle, IOCTL_IPV6_FLUSH_ROUTE_CACHE, &Query, sizeof Query, NULL, 0, &dwBytesReturned, NULL)) { return GetLastError(); }
return ERROR_OKAY; }
//////////////////////////////////////////////////////////////////////////////
// Route table functions
//////////////////////////////////////////////////////////////////////////////
DWORD ForEachRoute( IN DWORD (*pfnFunc)(IPV6_INFO_ROUTE_TABLE *, DWORD, DWORD, PIP_ADAPTER_ADDRESSES, FORMAT), IN DWORD dwArg, IN PIP_ADAPTER_ADDRESSES pAdapterInfo, IN FORMAT Format, IN BOOL bPersistent ) { IPV6_QUERY_ROUTE_TABLE Query, NextQuery; IPV6_INFO_ROUTE_TABLE RTE; DWORD dwBytesReturned, dwCount = 0;
ZeroMemory(&NextQuery, sizeof(NextQuery));
for (;;) { Query = NextQuery;
if (!DeviceIoControl(Handle, (bPersistent)? IOCTL_IPV6_PERSISTENT_QUERY_ROUTE_TABLE : IOCTL_IPV6_QUERY_ROUTE_TABLE, &Query, sizeof Query, &RTE, sizeof RTE, &dwBytesReturned, NULL)) { return dwCount; }
NextQuery = RTE.Next;
if (Query.Neighbor.IF.Index != 0) {
RTE.This = Query; if ((*pfnFunc)(&RTE, dwArg, dwCount, pAdapterInfo, Format) == NO_ERROR) { dwCount++; } }
if (NextQuery.Neighbor.IF.Index == 0) break; }
return dwCount; }
//
// These are RFC 2465 ipv6RouteProtocol values, and must match
// RTE_TYPE_... in ntddip6.h.
//
DWORD RteTypeMsg[] = { 0,0, STRING_SYSTEM, STRING_MANUAL, STRING_AUTOCONF, STRING_RIP, STRING_OSPF, STRING_BGP, STRING_IDRP, STRING_IGRP }; #define RTE_TYPE_MSG_COUNT (sizeof(RteTypeMsg)/sizeof(DWORD))
DWORD PrintRouteTableEntry( IN IPV6_INFO_ROUTE_TABLE *RTE, IN DWORD dwArg, IN DWORD dwCount, IN PIP_ADAPTER_ADDRESSES pAdapterInfo, IN FORMAT Format ) { DWORD dwTypeMsg, dwErr; PWCHAR pwszPublishMsg, pwszFriendlyName;
if (Format != FORMAT_VERBOSE) { //
// Suppress system routes (used for loopback).
//
if (RTE->Type == RTE_TYPE_SYSTEM) { return ERROR_NO_DATA; } }
dwErr = MapIpv6IfIndexToFriendlyName(RTE->This.Neighbor.IF.Index, pAdapterInfo, &pwszFriendlyName); if (dwErr != NO_ERROR) { return dwErr; }
pwszPublishMsg = TOKEN_VALUE_NO; if (RTE->Publish) { pwszPublishMsg = (RTE->Immortal)? TOKEN_VALUE_YES : TOKEN_VALUE_AGE; }
if (Format == FORMAT_DUMP) { DisplayMessageT(DMP_IPV6_ADD_ROUTE); DisplayMessageT(DMP_STRING_ARG, TOKEN_PREFIX, FormatIPv6Prefix(&RTE->This.Prefix, RTE->This.PrefixLength)); DisplayMessageT(DMP_QUOTED_STRING_ARG, TOKEN_INTERFACE, pwszFriendlyName); DisplayMessageT(DMP_INTEGER_ARG, TOKEN_METRIC, RTE->Preference);
if (!IN6_ADDR_EQUAL(&RTE->This.Neighbor.Address, &in6addr_any)) { DisplayMessageT(DMP_STRING_ARG, TOKEN_NEXTHOP, FormatIPv6Address(&RTE->This.Neighbor.Address, 0)); }
if (RTE->Publish) { DisplayMessageT(DMP_STRING_ARG, TOKEN_PUBLISH, pwszPublishMsg);
if ((RTE->SitePrefixLength != 0) && IN6_ADDR_EQUAL(&RTE->This.Neighbor.Address, &in6addr_any)) {
DisplayMessageT(DMP_STRING_ARG, TOKEN_SITEPREFIXLENGTH, RTE->SitePrefixLength); } } DisplayMessage(g_hModule, MSG_NEWLINE); } else { WCHAR wszValid[64], wszPreferred[64]; PWCHAR pwszTemp, pwszPrefix, pwszGateway; IPV6_INFO_INTERFACE *IF;
if ((Format == FORMAT_NORMAL) && (dwCount == 0)) { DisplayMessage(g_hModule, MSG_IPV6_ROUTE_TABLE_HDR); }
dwTypeMsg = (RTE->Type < RTE_TYPE_MSG_COUNT)? RteTypeMsg[RTE->Type] : STRING_UNKNOWN; pwszTemp = MakeString(g_hModule, dwTypeMsg);
pwszPrefix = FormatIPv6Prefix(&RTE->This.Prefix, RTE->This.PrefixLength);
if (IN6_ADDR_EQUAL(&RTE->This.Neighbor.Address, &in6addr_any)) { pwszGateway = pwszFriendlyName; } else { pwszGateway = FormatIPv6Address(&RTE->This.Neighbor.Address, 0); }
IF = GetInterfaceByIpv6IfIndex(RTE->This.Neighbor.IF.Index); if (!IF) { FreeString(pwszTemp); return ERROR_NO_DATA; }
DisplayMessage(g_hModule, ((Format == FORMAT_VERBOSE)? MSG_IPV6_ROUTE_TABLE_ENTRY_VERBOSE : MSG_IPV6_ROUTE_TABLE_ENTRY), pwszPrefix, RTE->This.Neighbor.IF.Index, pwszGateway, IF->Preference + RTE->Preference, pwszPublishMsg, pwszTemp, pwszFriendlyName, RTE->ValidLifetime, // FormatTime(RTE->ValidLifetime, wszValid),
RTE->PreferredLifetime, // FormatTime(RTE->PreferredLifetime, wszPreferred),
RTE->SitePrefixLength);
FREE(IF);
FreeString(pwszTemp); }
return NO_ERROR; }
DWORD QueryRouteTable( IN FORMAT Format, IN BOOL bPersistent ) { DWORD dwErr, dwCount = 0; PIP_ADAPTER_ADDRESSES pAdapterInfo;
dwErr = OpenIPv6(); if (dwErr != NO_ERROR) { return dwErr; }
if (Format != FORMAT_DUMP) { // DisplayMessage(g_hModule, (bPersistent)? MSG_PERSISTENT : MSG_ACTIVE);
}
dwErr = MyGetAdaptersInfo(&pAdapterInfo); if (dwErr != ERROR_NO_DATA) { if (dwErr != NO_ERROR) { return dwErr; }
dwCount = ForEachRoute(PrintRouteTableEntry, 0, pAdapterInfo, Format, bPersistent); FREE(pAdapterInfo); }
if ((Format != FORMAT_DUMP) && !dwCount) { DisplayMessage(g_hModule, MSG_IP_NO_ENTRIES); }
return NO_ERROR; }
DWORD UpdateRouteTable( IN IN6_ADDR *pipPrefix, IN DWORD dwPrefixLength, IN PWCHAR pwszIfFriendlyName, IN IN6_ADDR *pipNextHop, IN DWORD dwMetric, IN PUBLISH Publish, IN DWORD dwSitePrefixLength, IN DWORD dwValidLifetime, IN DWORD dwPreferredLifetime, IN BOOL bPersistent ) { IPV6_INFO_ROUTE_TABLE Route; DWORD dwBytesReturned; PIP_ADAPTER_ADDRESSES pAdapterInfo; DWORD dwErr;
dwErr = OpenIPv6(); if (dwErr != NO_ERROR) { return dwErr; }
dwErr = MyGetAdaptersInfo(&pAdapterInfo); if (dwErr != NO_ERROR) { return dwErr; }
dwErr = MapFriendlyNameToIpv6IfIndex(pwszIfFriendlyName, pAdapterInfo, &Route.This.Neighbor.IF.Index);
FREE(pAdapterInfo);
if (dwErr != NO_ERROR) { return dwErr; }
Route.This.Prefix = *pipPrefix; Route.This.PrefixLength = dwPrefixLength; Route.This.Neighbor.Address = (pipNextHop)? *pipNextHop : in6addr_any;
Route.SitePrefixLength = dwSitePrefixLength; Route.ValidLifetime = dwValidLifetime; Route.PreferredLifetime = dwPreferredLifetime; Route.Preference = dwMetric; Route.Type = RTE_TYPE_MANUAL; switch (Publish) { case PUBLISH_IMMORTAL: Route.Publish = TRUE; Route.Immortal = TRUE; break; case PUBLISH_AGE: Route.Publish = TRUE; Route.Immortal = FALSE; break; case PUBLISH_NO: Route.Publish = FALSE; Route.Immortal = FALSE; break; default: ASSERT(FALSE); }
dwErr = ERROR_OKAY;
if (bPersistent) { if (!DeviceIoControl(Handle, IOCTL_IPV6_PERSISTENT_UPDATE_ROUTE_TABLE, &Route, sizeof Route, NULL, 0, &dwBytesReturned, NULL)) { dwErr = GetLastError(); } }
if (!DeviceIoControl(Handle, IOCTL_IPV6_UPDATE_ROUTE_TABLE, &Route, sizeof Route, NULL, 0, &dwBytesReturned, NULL)) { if (dwErr == ERROR_OKAY) { dwErr = GetLastError(); } }
return dwErr; }
DWORD ResetIpv6Config( IN BOOL bPersistent ) { DWORD dwBytesReturned, dwErr;
dwErr = OpenIPv6(); if (dwErr != NO_ERROR) { return dwErr; }
dwErr = ERROR_OKAY;
if (bPersistent) { if (!DeviceIoControl(Handle, IOCTL_IPV6_PERSISTENT_RESET, NULL, 0, NULL, 0, &dwBytesReturned, NULL)) { dwErr = GetLastError(); } }
if (!DeviceIoControl(Handle, IOCTL_IPV6_RESET, NULL, 0, NULL, 0, &dwBytesReturned, NULL)) { if (dwErr == ERROR_OKAY) { dwErr = GetLastError(); } }
return dwErr; }
|