mirror of https://github.com/tongzx/nt5src
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.
893 lines
19 KiB
893 lines
19 KiB
/*++
|
|
|
|
Copyright (c) 1998 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
net\routing\ip\rtrmgr\ipipcfg.c
|
|
|
|
Abstract:
|
|
|
|
The configuration code for ipinip
|
|
|
|
Revision History:
|
|
|
|
Amritansh Raghav
|
|
|
|
--*/
|
|
|
|
#include "allinc.h"
|
|
|
|
//
|
|
// All the following are protected by the ICB_LIST lock
|
|
//
|
|
|
|
HKEY g_hIpIpIfKey;
|
|
DWORD g_dwNumIpIpInterfaces;
|
|
HANDLE g_hIpInIpDevice;
|
|
|
|
|
|
DWORD
|
|
OpenIpIpKey(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Opens the necessary reg keys for IP in IP
|
|
|
|
Locks
|
|
|
|
None
|
|
|
|
Arguments
|
|
|
|
None
|
|
|
|
Return Value
|
|
|
|
Win32 errors
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD dwResult;
|
|
|
|
g_hIpIpIfKey = NULL;
|
|
|
|
dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
REG_KEY_TCPIP_INTERFACES,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&g_hIpIpIfKey);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
g_hIpIpIfKey = NULL;
|
|
|
|
Trace1(ERR,
|
|
"OpenIpIpKey: Error %d opening interfaces key\n",
|
|
dwResult);
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
VOID
|
|
CloseIpIpKey(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Closes the necessary reg keys for IP in IP
|
|
|
|
Locks
|
|
|
|
None
|
|
|
|
Arguments
|
|
|
|
None
|
|
|
|
Return Value
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
if(g_hIpIpIfKey isnot NULL)
|
|
{
|
|
RegCloseKey(g_hIpIpIfKey);
|
|
|
|
g_hIpIpIfKey = NULL;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
DeleteIpIpKeyAndInfo(
|
|
IN PICB pIcb
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Deletes the key used for the interface
|
|
|
|
Locks
|
|
|
|
ICB_LIST as writer
|
|
|
|
Arguments
|
|
|
|
pIcb ICB of the interface to delete
|
|
|
|
Return Value
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
if(pIcb->pIpIpInfo)
|
|
{
|
|
HeapFree(IPRouterHeap,
|
|
0,
|
|
pIcb->pIpIpInfo);
|
|
|
|
pIcb->pIpIpInfo = NULL;
|
|
}
|
|
|
|
RegDeleteKeyW(g_hIpIpIfKey,
|
|
pIcb->pwszName);
|
|
}
|
|
|
|
DWORD
|
|
CreateIpIpKeyAndInfo(
|
|
IN PICB pIcb
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Creates a key under the tcpip interfaces
|
|
|
|
Locks
|
|
|
|
ICB_LIST lock held as READER (atleast)
|
|
|
|
Arguments
|
|
|
|
ICB for whom to create a key
|
|
|
|
Return Value
|
|
|
|
Win32 errors
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD dwResult, dwDisposition, dwIndex, dwSize;
|
|
HKEY hNewIfKey;
|
|
TCHAR ptszNoAddr[] = "0.0.0.0\0";
|
|
|
|
dwDisposition = 0;
|
|
|
|
dwResult = RegCreateKeyExW(g_hIpIpIfKey,
|
|
pIcb->pwszName,
|
|
0,
|
|
UNICODE_NULL,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
NULL,
|
|
&hNewIfKey,
|
|
&dwDisposition);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace2(ERR,
|
|
"CreateIpIpKey: Error %d creating %S",
|
|
dwResult,
|
|
pIcb->pwszName);
|
|
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
|
|
//
|
|
// Good, key is done, now do the minimum needed by IP
|
|
//
|
|
|
|
do
|
|
{
|
|
//
|
|
// Create a block for the configuration. When the dwLocalAddress is
|
|
// 0, it means that the information hasnt been set
|
|
//
|
|
|
|
pIcb->pIpIpInfo = HeapAlloc(IPRouterHeap,
|
|
HEAP_ZERO_MEMORY,
|
|
sizeof(IPINIP_CONFIG_INFO));
|
|
|
|
if(pIcb->pIpIpInfo is NULL)
|
|
{
|
|
dwResult = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
break;
|
|
}
|
|
|
|
dwResult = RegSetValueEx(hNewIfKey,
|
|
REG_VAL_DEFGATEWAY,
|
|
0,
|
|
REG_MULTI_SZ,
|
|
NULL,
|
|
0);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace2(ERR,
|
|
"CreateIpIpKey: Error %d setting %s",
|
|
dwResult, REG_VAL_DEFGATEWAY);
|
|
|
|
break;
|
|
}
|
|
|
|
dwDisposition = 0;
|
|
|
|
dwResult = RegSetValueEx(hNewIfKey,
|
|
REG_VAL_ENABLEDHCP,
|
|
0,
|
|
REG_DWORD,
|
|
(CONST BYTE *)&dwDisposition,
|
|
sizeof(DWORD));
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace2(ERR,
|
|
"CreateIpIpKey: Error %d setting %s",
|
|
dwResult, REG_VAL_ENABLEDHCP);
|
|
|
|
break;
|
|
}
|
|
|
|
dwResult = RegSetValueEx(hNewIfKey,
|
|
REG_VAL_IPADDRESS,
|
|
0,
|
|
REG_MULTI_SZ,
|
|
(CONST BYTE *)ptszNoAddr,
|
|
sizeof(ptszNoAddr));
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace2(ERR,
|
|
"CreateIpIpKey: Error %d setting %s",
|
|
dwResult, REG_VAL_IPADDRESS);
|
|
|
|
break;
|
|
}
|
|
|
|
dwResult = RegSetValueEx(hNewIfKey,
|
|
REG_VAL_NTECONTEXTLIST,
|
|
0,
|
|
REG_MULTI_SZ,
|
|
NULL,
|
|
0);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace2(ERR,
|
|
"CreateIpIpKey: Error %d setting %s",
|
|
dwResult, REG_VAL_NTECONTEXTLIST);
|
|
|
|
break;
|
|
}
|
|
|
|
dwResult = RegSetValueEx(hNewIfKey,
|
|
REG_VAL_SUBNETMASK,
|
|
0,
|
|
REG_MULTI_SZ,
|
|
(CONST BYTE *)ptszNoAddr,
|
|
sizeof(ptszNoAddr));
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace2(ERR,
|
|
"CreateIpIpKey: Error %d setting %s",
|
|
dwResult, REG_VAL_SUBNETMASK);
|
|
|
|
break;
|
|
}
|
|
|
|
dwDisposition = 0;
|
|
|
|
dwResult = RegSetValueEx(hNewIfKey,
|
|
REG_VAL_ZEROBCAST,
|
|
0,
|
|
REG_DWORD,
|
|
(CONST BYTE *)&dwDisposition,
|
|
sizeof(DWORD));
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace2(ERR,
|
|
"CreateIpIpKey: Error %d setting %s",
|
|
dwResult, REG_VAL_ZEROBCAST);
|
|
|
|
break;
|
|
}
|
|
|
|
}while(FALSE);
|
|
|
|
RegCloseKey(hNewIfKey);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
DeleteIpIpKeyAndInfo(pIcb);
|
|
}
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
DWORD
|
|
AddInterfaceToIpInIp(
|
|
IN GUID *pGuid,
|
|
IN PICB pIcb
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Adds an interface to IP in IP driver
|
|
|
|
Locks
|
|
|
|
ICB_LIST lock held as WRITER
|
|
|
|
|
|
Arguments
|
|
|
|
pIcb ICB of the interface to add
|
|
|
|
Return Value
|
|
|
|
NO_ERROR
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD dwResult;
|
|
NTSTATUS ntStatus;
|
|
PADAPTER_INFO pBindNode;
|
|
ULONG ulSize;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
IPINIP_CREATE_TUNNEL CreateInfo;
|
|
|
|
|
|
IpRtAssert(pIcb->ritType is ROUTER_IF_TYPE_TUNNEL1);
|
|
|
|
//
|
|
// Get a key for this interface
|
|
//
|
|
|
|
dwResult = CreateIpIpKeyAndInfo(pIcb);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace2(ERR,
|
|
"AddInterfaceToIpInIp: Error %d creating key for %S",
|
|
dwResult,
|
|
pIcb->pwszName);
|
|
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
|
|
//
|
|
// See if we need to start IP in IP
|
|
//
|
|
|
|
g_dwNumIpIpInterfaces++;
|
|
|
|
if(g_dwNumIpIpInterfaces is 1)
|
|
{
|
|
dwResult = StartDriverAndOpenHandle(IPINIP_SERVICE_NAME,
|
|
DD_IPINIP_DEVICE_NAME,
|
|
&g_hIpInIpDevice);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace2(ERR,
|
|
"AddInterfaceToIpInIp: Error %d starting ipinip for %S",
|
|
dwResult,
|
|
pIcb->pwszName);
|
|
|
|
g_dwNumIpIpInterfaces--;
|
|
|
|
DeleteIpIpKeyAndInfo(pIcb);
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
//
|
|
// Once you start, post a notification
|
|
//
|
|
|
|
PostIpInIpNotification();
|
|
}
|
|
|
|
//
|
|
// Copy out the name
|
|
//
|
|
|
|
CreateInfo.Guid = *pGuid;
|
|
|
|
ntStatus = NtDeviceIoControlFile(g_hIpInIpDevice,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
IOCTL_IPINIP_CREATE_TUNNEL,
|
|
&CreateInfo,
|
|
sizeof(IPINIP_CREATE_TUNNEL),
|
|
&CreateInfo,
|
|
sizeof(IPINIP_CREATE_TUNNEL));
|
|
|
|
if(!NT_SUCCESS(ntStatus))
|
|
{
|
|
Trace1(ERR,
|
|
"AddInterfaceToIpInIp: NtStatus %x creating tunnel",
|
|
ntStatus);
|
|
|
|
g_dwNumIpIpInterfaces--;
|
|
|
|
if(g_dwNumIpIpInterfaces is 0)
|
|
{
|
|
StopDriverAndCloseHandle(IPINIP_SERVICE_NAME,
|
|
g_hIpInIpDevice);
|
|
}
|
|
|
|
DeleteIpIpKeyAndInfo(pIcb);
|
|
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
|
|
//
|
|
// Set the interface index
|
|
//
|
|
|
|
pIcb->bBound = TRUE;
|
|
pIcb->dwNumAddresses = 0;
|
|
pIcb->dwIfIndex = CreateInfo.dwIfIndex;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
DeleteInterfaceFromIpInIp(
|
|
PICB pIcb
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Removes an interface to IP in IP driver. Also removes binding information
|
|
and frees the ipipcfg
|
|
|
|
Locks
|
|
|
|
ICB_LIST lock held as WRITER
|
|
|
|
|
|
Arguments
|
|
|
|
pIcb ICB of the interface to remove
|
|
|
|
Return Value
|
|
|
|
NO_ERROR
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS ntStatus;
|
|
IPINIP_DELETE_TUNNEL DeleteInfo;
|
|
PADAPTER_INFO pBindNode;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
DWORD dwResult;
|
|
|
|
|
|
IpRtAssert(pIcb->ritType is ROUTER_IF_TYPE_TUNNEL1);
|
|
|
|
//
|
|
// See if the interface was added to ipinip
|
|
//
|
|
|
|
if(pIcb->pIpIpInfo is NULL)
|
|
{
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DeleteInfo.dwIfIndex = pIcb->dwIfIndex;
|
|
|
|
ntStatus = NtDeviceIoControlFile(g_hIpInIpDevice,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
IOCTL_IPINIP_DELETE_TUNNEL,
|
|
(PVOID)&DeleteInfo,
|
|
sizeof(IPINIP_DELETE_TUNNEL),
|
|
NULL,
|
|
0);
|
|
|
|
if(!NT_SUCCESS(ntStatus))
|
|
{
|
|
Trace1(ERR,
|
|
"DeleteInterfaceFromIpInIp: NtStatus %x setting info",
|
|
ntStatus);
|
|
}
|
|
|
|
pIcb->bBound = FALSE;
|
|
pIcb->dwNumAddresses = 0;
|
|
|
|
//
|
|
// These interfaces always have a binding
|
|
// Clear out any info there
|
|
//
|
|
|
|
pIcb->pibBindings[0].dwAddress = 0;
|
|
pIcb->pibBindings[0].dwMask = 0;
|
|
|
|
DeleteIpIpKeyAndInfo(pIcb);
|
|
|
|
g_dwNumIpIpInterfaces--;
|
|
|
|
if(g_dwNumIpIpInterfaces is 0)
|
|
{
|
|
StopDriverAndCloseHandle(IPINIP_SERVICE_NAME,
|
|
g_hIpInIpDevice);
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
SetIpInIpInfo(
|
|
PICB pIcb,
|
|
PRTR_INFO_BLOCK_HEADER pInterfaceInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
The routine sets the IP in IP info to the driver. The interface must
|
|
have already been added to the driver
|
|
|
|
Locks
|
|
|
|
ICB_LIST lock held as WRITER
|
|
|
|
Arguments
|
|
|
|
pIcb ICB of the tunnel interface
|
|
pInterfaceInfo Header to the interface info
|
|
|
|
Return Value
|
|
|
|
NO_ERROR
|
|
|
|
--*/
|
|
|
|
{
|
|
PRTR_TOC_ENTRY pToc;
|
|
PIPINIP_CONFIG_INFO pInfo;
|
|
IPINIP_SET_TUNNEL_INFO SetInfo;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
NTSTATUS ntStatus;
|
|
DWORD dwResult;
|
|
|
|
if(pIcb->ritType isnot ROUTER_IF_TYPE_TUNNEL1)
|
|
{
|
|
return NO_ERROR;
|
|
}
|
|
|
|
pToc = GetPointerToTocEntry(IP_IPINIP_CFG_INFO,
|
|
pInterfaceInfo);
|
|
|
|
if(pToc is NULL)
|
|
{
|
|
//
|
|
// No change
|
|
//
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
IpRtAssert(pToc->InfoSize isnot 0);
|
|
|
|
#if 0
|
|
|
|
if(pToc->InfoSize is 0)
|
|
{
|
|
//
|
|
// Blow the interface away from protocols etc
|
|
//
|
|
|
|
dwResult = LanEtcInterfaceUpToDown(pIcb,
|
|
FALSE);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
Trace2(ERR,
|
|
"SetIpInIpInfo: Error %d bringing %S down\n",
|
|
dwResult,
|
|
pIcb->pwszName);
|
|
}
|
|
|
|
//
|
|
// Tear down the tunnel
|
|
//
|
|
|
|
DeleteInterfaceFromIpInIp(pIcb);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
#endif
|
|
|
|
//
|
|
// Verify the information
|
|
//
|
|
|
|
pInfo = GetInfoFromTocEntry(pInterfaceInfo,
|
|
pToc);
|
|
|
|
if (pInfo is NULL)
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if((pInfo->dwLocalAddress is INVALID_IP_ADDRESS) or
|
|
(pInfo->dwRemoteAddress is INVALID_IP_ADDRESS) or
|
|
((DWORD)(pInfo->dwLocalAddress & 0x000000E0) >= (DWORD)0x000000E0) or
|
|
((DWORD)(pInfo->dwRemoteAddress & 0x000000E0) >= (DWORD)0x000000E0) or
|
|
(pInfo->byTtl is 0))
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// See if the interface has already been added to the driver
|
|
//
|
|
|
|
IpRtAssert(pIcb->pIpIpInfo isnot NULL);
|
|
|
|
SetInfo.dwIfIndex = pIcb->dwIfIndex;
|
|
SetInfo.dwRemoteAddress = pInfo->dwRemoteAddress;
|
|
SetInfo.dwLocalAddress = pInfo->dwLocalAddress;
|
|
SetInfo.byTtl = pInfo->byTtl;
|
|
|
|
|
|
//
|
|
// Set the info to the driver
|
|
//
|
|
|
|
ntStatus = NtDeviceIoControlFile(g_hIpInIpDevice,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
IOCTL_IPINIP_SET_TUNNEL_INFO,
|
|
(PVOID)&SetInfo,
|
|
sizeof(IPINIP_SET_TUNNEL_INFO),
|
|
NULL,
|
|
0);
|
|
|
|
if(!NT_SUCCESS(ntStatus))
|
|
{
|
|
Trace1(ERR,
|
|
"SetIpInIpInfo: NtStatus %x setting info",
|
|
ntStatus);
|
|
|
|
#if 0
|
|
DeleteInterfaceFromIpInIp(pIcb);
|
|
|
|
#endif
|
|
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
|
|
pIcb->dwOperationalState = SetInfo.dwOperationalState;
|
|
pIcb->pIpIpInfo->dwRemoteAddress = SetInfo.dwRemoteAddress;
|
|
pIcb->pIpIpInfo->dwLocalAddress = SetInfo.dwLocalAddress;
|
|
pIcb->pIpIpInfo->byTtl = SetInfo.byTtl;
|
|
|
|
//
|
|
// Also set the operational state to UP
|
|
//
|
|
|
|
pIcb->dwOperationalState = CONNECTED;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
GetInterfaceIpIpInfo(
|
|
IN PICB pIcb,
|
|
IN PRTR_TOC_ENTRY pToc,
|
|
IN PBYTE pbDataPtr,
|
|
IN OUT PRTR_INFO_BLOCK_HEADER pInfoHdr,
|
|
IN OUT PDWORD pdwInfoSize
|
|
)
|
|
{
|
|
PIPINIP_CONFIG_INFO pInfo;
|
|
|
|
TraceEnter("GetInterfaceIpIpInfo");
|
|
|
|
IpRtAssert(pIcb->ritType is ROUTER_IF_TYPE_TUNNEL1);
|
|
|
|
if(*pdwInfoSize < sizeof(IPINIP_CONFIG_INFO))
|
|
{
|
|
*pdwInfoSize = sizeof(IPINIP_CONFIG_INFO);
|
|
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
|
|
*pdwInfoSize = 0;
|
|
|
|
if(pIcb->pIpIpInfo is NULL)
|
|
{
|
|
//
|
|
// Have no info
|
|
//
|
|
|
|
return ERROR_NO_DATA;
|
|
}
|
|
|
|
*pdwInfoSize = sizeof(IPINIP_CONFIG_INFO);
|
|
|
|
//pToc->InfoVersion sizeof(IPINIP_CONFIG_INFO);
|
|
pToc->InfoSize = sizeof(IPINIP_CONFIG_INFO);
|
|
pToc->InfoType = IP_IPINIP_CFG_INFO;
|
|
pToc->Count = 1;
|
|
pToc->Offset = (ULONG)(pbDataPtr - (PBYTE) pInfoHdr);
|
|
|
|
pInfo = (PIPINIP_CONFIG_INFO)pbDataPtr;
|
|
|
|
*pInfo = *(pIcb->pIpIpInfo);
|
|
|
|
TraceLeave("GetInterfaceIpIpInfo");
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
PostIpInIpNotification(
|
|
VOID
|
|
)
|
|
{
|
|
DWORD dwBytesRead;
|
|
DWORD dwErr = NO_ERROR;
|
|
|
|
TraceEnter("PostIpInIpNotification");
|
|
|
|
ZeroMemory(&g_IpInIpOverlapped,
|
|
sizeof(OVERLAPPED));
|
|
|
|
g_IpInIpOverlapped.hEvent = g_hIpInIpEvent ;
|
|
|
|
if (!DeviceIoControl(g_hIpInIpDevice,
|
|
IOCTL_IPINIP_NOTIFICATION,
|
|
&g_inIpInIpMsg,
|
|
sizeof(g_inIpInIpMsg),
|
|
&g_inIpInIpMsg,
|
|
sizeof(g_inIpInIpMsg),
|
|
(PDWORD) &dwBytesRead,
|
|
&g_IpInIpOverlapped))
|
|
{
|
|
dwErr = GetLastError();
|
|
|
|
if(dwErr isnot ERROR_IO_PENDING)
|
|
{
|
|
Trace1(ERR,
|
|
"PostIpInIpNotification: Couldnt post irp with IpInIp: %d",
|
|
dwErr);
|
|
|
|
dwErr = NO_ERROR;
|
|
}
|
|
else
|
|
{
|
|
Trace0(IF,
|
|
"PostIpInIpNotification: Notification pending in IpInIP");
|
|
}
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
VOID
|
|
HandleIpInIpEvent(
|
|
VOID
|
|
)
|
|
{
|
|
PICB pIcb;
|
|
DWORD dwBytes;
|
|
|
|
ENTER_WRITER(ICB_LIST);
|
|
|
|
TraceEnter("HandleIpInIpEvent");
|
|
|
|
do
|
|
{
|
|
if((g_inIpInIpMsg.ieEvent isnot IE_INTERFACE_UP) and
|
|
(g_inIpInIpMsg.ieEvent isnot IE_INTERFACE_DOWN))
|
|
{
|
|
Trace1(IF,
|
|
"HandleIpInIpEvent: Unknown event code %d\n",
|
|
g_inIpInIpMsg.ieEvent);
|
|
|
|
break;
|
|
}
|
|
|
|
if(!GetOverlappedResult(g_hIpInIpDevice,
|
|
&g_IpInIpOverlapped,
|
|
&dwBytes,
|
|
FALSE))
|
|
{
|
|
Trace1(IF,
|
|
"HandleIpInIpEvent: Error %d from GetOverlappedResult",
|
|
GetLastError());
|
|
|
|
break;
|
|
}
|
|
|
|
pIcb = InterfaceLookupByIfIndex(g_inIpInIpMsg.dwIfIndex);
|
|
|
|
if(pIcb is NULL)
|
|
{
|
|
Trace1(IF,
|
|
"HandleIpInIpEvent: Interface %x not found",
|
|
g_inIpInIpMsg.dwIfIndex);
|
|
|
|
break;
|
|
}
|
|
|
|
if(pIcb->ritType isnot ROUTER_IF_TYPE_TUNNEL1)
|
|
{
|
|
Trace1(IF,
|
|
"HandleIpInIpEvent: Interface %x not an IpInIp tunnel",
|
|
g_inIpInIpMsg.dwIfIndex);
|
|
|
|
IpRtAssert(FALSE);
|
|
|
|
break;
|
|
}
|
|
|
|
Trace3(IF,
|
|
"HandleIpInIpEvent: Interface %S is %s due to %d",
|
|
pIcb->pwszName,
|
|
(g_inIpInIpMsg.ieEvent is IE_INTERFACE_UP) ? "operational" : "non-operational",
|
|
g_inIpInIpMsg.iseSubEvent);
|
|
|
|
pIcb->dwOperationalState =
|
|
(g_inIpInIpMsg.ieEvent is IE_INTERFACE_UP) ? OPERATIONAL : NON_OPERATIONAL;
|
|
}while(FALSE);
|
|
|
|
EXIT_LOCK(ICB_LIST);
|
|
|
|
PostIpInIpNotification();
|
|
|
|
return;
|
|
}
|