Leaked source code of windows server 2003
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.
 
 
 
 
 
 

609 lines
12 KiB

/*++
Copyright (c) 2001-2002 Microsoft Corporation
Module Name:
isatap.c
Abstract:
This module contains the ISATAP interface to the IPv6 Helper Service.
Author:
Mohit Talwar (mohitt) Tue May 07 10:16:49 2002
Environment:
User mode only.
--*/
#include "precomp.h"
#pragma hdrstop
#define DEFAULT_ISATAP_STATE ENABLED
#define DEFAULT_ISATAP_ROUTER_NAME L"isatap"
#define DEFAULT_ISATAP_RESOLUTION_STATE ENABLED
#define DEFAULT_ISATAP_RESOLUTION_INTERVAL (24 * HOURS)
#define KEY_ISATAP_STATE L"IsatapState"
#define KEY_ISATAP_ROUTER_NAME L"IsatapRouterName"
#define KEY_ISATAP_RESOLUTION_STATE L"EnableIsatapResolution"
#define KEY_ISATAP_RESOLUTION_INTERVAL L"IsatapResolutionInterval"
STATE IsatapState;
WCHAR IsatapRouterName[NI_MAXHOST];
STATE IsatapResolutionState;
ULONG IsatapResolutionInterval; // in minutes
HANDLE IsatapTimer; // Periodic timer started for the service.
HANDLE IsatapTimerEvent; // Event signalled upon Timer deletion.
HANDLE IsatapTimerEventWait; // Wait registered for TimerEvent.
IN_ADDR IsatapRouter;
IN_ADDR IsatapToken;
BOOL IsatapInitialized = FALSE;
DWORD
GetPreferredSource(
IN IN_ADDR Destination,
OUT PIN_ADDR Source
)
{
SOCKADDR_IN DestinationAddress, SourceAddress;
int BytesReturned;
memset(&DestinationAddress, 0, sizeof(SOCKADDR_IN));
DestinationAddress.sin_family = AF_INET;
DestinationAddress.sin_addr = Destination;
if (WSAIoctl(
g_sIPv4Socket, SIO_ROUTING_INTERFACE_QUERY,
&DestinationAddress, sizeof(SOCKADDR_IN),
&SourceAddress, sizeof(SOCKADDR_IN),
&BytesReturned, NULL, NULL) == SOCKET_ERROR) {
return WSAGetLastError();
}
*Source = SourceAddress.sin_addr;
return NO_ERROR;
}
VOID
IsatapUpdateRouterAddress(
VOID
)
{
DWORD Error = NO_ERROR;
ADDRINFOW Hints;
PADDRINFOW Addresses;
IN_ADDR NewRouter = { INADDR_ANY }, NewToken = { INADDR_ANY };
//
// Set the ISATAP router address if ISATAP resolution is enabled.
//
if (IsatapResolutionState == ENABLED) {
//
// Resolve IsatapRouterName to an IPv4 address.
//
ZeroMemory(&Hints, sizeof(Hints));
Hints.ai_family = PF_INET;
Error = GetAddrInfoW(IsatapRouterName, NULL, &Hints, &Addresses);
if (Error == NO_ERROR) {
NewRouter = ((LPSOCKADDR_IN) Addresses->ai_addr)->sin_addr;
FreeAddrInfoW(Addresses);
//
// Determine the preferred source address.
//
if (GetPreferredSource(NewRouter, &NewToken) != NO_ERROR) {
//
// What use is the IsatapRouter that cannot be reached?
//
NewRouter.s_addr = INADDR_ANY;
}
} else {
Trace2(ERR, _T("GetAddrInfoW(%s): %x"), IsatapRouterName, Error);
}
}
//
// Update the stack with the new addresses.
//
IsatapRouter = NewRouter;
IsatapToken = NewToken;
UpdateRouterLinkAddress(V4_COMPAT_IFINDEX, IsatapToken, IsatapRouter);
}
VOID
IsatapConfigureAddress(
IN BOOL Delete,
IN IN_ADDR Ipv4
)
/*++
Routine Description:
Creates an ISATAP link-scoped address from an IPv4 address.
--*/
{
SOCKADDR_IN6 IsatapAddress;
memset(&IsatapAddress, 0, sizeof(SOCKADDR_IN6));
IsatapAddress.sin6_family = AF_INET6;
IsatapAddress.sin6_addr.s6_addr[0] = 0xfe;
IsatapAddress.sin6_addr.s6_addr[1] = 0x80;
IsatapAddress.sin6_addr.s6_addr[10] = 0x5e;
IsatapAddress.sin6_addr.s6_addr[11] = 0xfe;
memcpy(&IsatapAddress.sin6_addr.s6_addr[12], &Ipv4, sizeof(IN_ADDR));
(VOID) ConfigureAddressUpdate(
V4_COMPAT_IFINDEX,
&IsatapAddress,
Delete ? 0 : INFINITE_LIFETIME,
ADE_UNICAST, PREFIX_CONF_WELLKNOWN, IID_CONF_LL_ADDRESS);
}
VOID
IsatapConfigureAddressList(
IN BOOL Delete
)
{
int i;
//
// Configure the lifetime of link-local ISATAP addresses.
// This will cause them to be either added or deleted.
//
for (i = 0; i < g_pIpv4AddressList->iAddressCount; i++) {
IsatapConfigureAddress(
Delete,
((PSOCKADDR_IN)
g_pIpv4AddressList->Address[i].lpSockaddr)->sin_addr);
}
}
__inline
VOID
IsatapRestartTimer(
VOID
)
{
ULONG ResolveInterval = (IsatapResolutionState == ENABLED)
? IsatapResolutionInterval * MINUTES * 1000 // minutes to milliseconds
: INFINITE_INTERVAL;
(VOID) ChangeTimerQueueTimer(NULL, IsatapTimer, 0, ResolveInterval);
}
__inline
VOID
IsatapStart(
VOID
)
{
ASSERT(IsatapState != ENABLED);
IsatapState = ENABLED;
IsatapConfigureAddressList(FALSE);
IsatapRestartTimer();
}
__inline
VOID
IsatapStop(
VOID
)
{
ASSERT(IsatapState == ENABLED);
IsatapState = DISABLED;
IsatapConfigureAddressList(TRUE);
IsatapRestartTimer();
}
__inline
VOID
IsatapRefresh(
VOID
)
{
ASSERT(IsatapState == ENABLED);
IsatapRestartTimer();
}
VOID
CALLBACK
IsatapTimerCallback(
IN PVOID Parameter,
IN BOOLEAN TimerOrWaitFired
)
/*++
Routine Description:
Callback routine for IsatapTimer expiration.
The timer is always active.
Arguments:
Parameter, TimerOrWaitFired - Ignored.
Return Value:
None.
--*/
{
ENTER_API();
TraceEnter("IsatapTimerCallback");
IsatapUpdateRouterAddress();
TraceLeave("IsatapTimerCallback");
LEAVE_API();
}
VOID
CALLBACK
IsatapTimerCleanup(
IN PVOID Parameter,
IN BOOLEAN TimerOrWaitFired
)
/*++
Routine Description:
Callback routine for IsatapTimer deletion.
Deletion is performed asynchronously since we acquire a lock in
the callback function that we hold when deleting the timer.
Arguments:
Parameter, TimerOrWaitFired - Ignored.
Return Value:
None.
--*/
{
UnregisterWait(IsatapTimerEventWait);
IsatapTimerEventWait = NULL;
CloseHandle(IsatapTimerEvent);
IsatapTimerEvent = NULL;
IsatapState = IsatapResolutionState = DISABLED;
IsatapUpdateRouterAddress();
DecEventCount("IsatapCleanupTimer");
}
DWORD
IsatapInitializeTimer(
VOID
)
/*++
Routine Description:
Initializes the timer.
Arguments:
None.
Return Value:
NO_ERROR or failure code.
--*/
{
DWORD Error;
ULONG ResolveInterval;
IsatapTimerEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (IsatapTimerEvent == NULL) {
Error = GetLastError();
return Error;
}
if (!RegisterWaitForSingleObject(
&(IsatapTimerEventWait),
IsatapTimerEvent,
IsatapTimerCleanup,
NULL,
INFINITE,
0)) {
Error = GetLastError();
CloseHandle(IsatapTimerEvent);
return Error;
}
ResolveInterval = (IsatapResolutionState == ENABLED)
? (IsatapResolutionInterval * MINUTES * 1000)
: INFINITE_INTERVAL;
if (!CreateTimerQueueTimer(
&(IsatapTimer),
NULL,
IsatapTimerCallback,
NULL,
0,
ResolveInterval,
0)) {
Error = GetLastError();
UnregisterWait(IsatapTimerEventWait);
CloseHandle(IsatapTimerEvent);
return Error;
}
IncEventCount("IsatapInitializeTimer");
return NO_ERROR;
}
VOID
IsatapUninitializeTimer(
VOID
)
/*++
Routine Description:
Uninitializes the timer. Typically invoked upon service stop.
Arguments:
None.
Return Value:
None.
--*/
{
DeleteTimerQueueTimer(NULL, IsatapTimer, IsatapTimerEvent);
IsatapTimer = NULL;
}
DWORD
IsatapInitialize(
VOID
)
/*++
Routine Description:
Initializes ISATAP and attempts to start it.
Arguments:
None.
Return Value:
NO_ERROR or failure code.
--*/
{
DWORD Error;
IsatapState = DEFAULT_ISATAP_STATE;
wcscpy(IsatapRouterName, DEFAULT_ISATAP_ROUTER_NAME);
IsatapResolutionState = DEFAULT_ISATAP_RESOLUTION_STATE;
IsatapResolutionInterval = DEFAULT_ISATAP_RESOLUTION_INTERVAL;
IsatapRouter.s_addr = INADDR_ANY;
IsatapToken.s_addr = INADDR_ANY;
IsatapUpdateRouterAddress();
Error = IsatapInitializeTimer();
if (Error != NO_ERROR) {
return Error;
}
IsatapInitialized = TRUE;
return NO_ERROR;
}
VOID
IsatapUninitialize(
VOID
)
/*++
Routine Description:
Uninitializes ISATAP.
Arguments:
None.
Return Value:
None.
--*/
{
if (!IsatapInitialized) {
return;
}
IsatapUninitializeTimer();
IsatapInitialized = FALSE;
}
VOID
IsatapAddressChangeNotification(
IN BOOL Delete,
IN IN_ADDR Address
)
/*++
Routine Description:
Process an address deletion or addition request.
Arguments:
Delete - Supplies a boolean. TRUE if the address was deleted, FALSE o/w.
Address - Supplies the IPv4 address that was deleted or added.
Return Value:
None.
Caller LOCK: API.
--*/
{
IsatapConfigureAddress(Delete, Address);
if (IsatapResolutionState == ENABLED) {
//
// Preferred source address deleted -or- Any address added.
//
if (Delete
? (IsatapToken.s_addr == Address.s_addr)
: (IsatapToken.s_addr == INADDR_ANY)) {
Sleep(1000); // Wait a second to ensure DNS is alerted.
IsatapUpdateRouterAddress();
}
}
}
VOID
IsatapRouteChangeNotification(
VOID
)
/*++
Routine Description:
Process a route change notification.
Arguments:
None.
Return Value:
None.
Caller LOCK: API.
--*/
{
if (IsatapResolutionState == ENABLED) {
IsatapRefresh();
}
}
VOID
IsatapConfigurationChangeNotification(
VOID
)
/*++
Routine Description:
Process an configuration change request.
Arguments:
None.
Return Value:
None.
Caller LOCK: API.
--*/
{
HKEY Key = INVALID_HANDLE_VALUE;
STATE State;
(VOID) RegOpenKeyExW(
HKEY_LOCAL_MACHINE, KEY_GLOBAL, 0, KEY_QUERY_VALUE, &Key);
//
// Continue despite errors, reverting to default values.
//
State = GetInteger(
Key,
KEY_ISATAP_STATE,
DEFAULT_ISATAP_STATE);
IsatapResolutionState = GetInteger(
Key,
KEY_ISATAP_RESOLUTION_STATE,
DEFAULT_ISATAP_RESOLUTION_STATE);
IsatapResolutionInterval= GetInteger(
Key,
KEY_ISATAP_RESOLUTION_INTERVAL,
DEFAULT_ISATAP_RESOLUTION_INTERVAL);
GetString(
Key,
KEY_ISATAP_ROUTER_NAME,
IsatapRouterName,
NI_MAXHOST,
DEFAULT_ISATAP_ROUTER_NAME);
if (Key != INVALID_HANDLE_VALUE) {
RegCloseKey(Key);
}
if (State == DISABLED) {
IsatapResolutionState = DISABLED;
}
//
// Start / Reconfigure / Stop.
//
if (State == ENABLED) {
if (IsatapState == ENABLED) {
IsatapRefresh();
} else {
IsatapStart();
}
} else {
if (IsatapState == ENABLED) {
IsatapStop();
}
}
}