1249 lines
26 KiB
C
1249 lines
26 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1999 Microsoft Corporation
|
||
|
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
interface.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This module contains all of the code to drive
|
||
|
the interface list management of IPSecSPD Service.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
abhisheV 30-September-1999
|
||
|
|
||
|
Environment
|
||
|
|
||
|
User Level: Win32
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
|
||
|
--*/
|
||
|
|
||
|
|
||
|
#include "precomp.h"
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
CreateInterfaceList(
|
||
|
OUT PIPSEC_INTERFACE * ppIfListToCreate
|
||
|
)
|
||
|
{
|
||
|
DWORD dwError = 0;
|
||
|
PIPSEC_INTERFACE pIfList = NULL;
|
||
|
|
||
|
|
||
|
dwError = GetInterfaceListFromStack(
|
||
|
&pIfList
|
||
|
);
|
||
|
|
||
|
ENTER_SPD_SECTION();
|
||
|
|
||
|
*ppIfListToCreate = pIfList;
|
||
|
|
||
|
LEAVE_SPD_SECTION();
|
||
|
|
||
|
return (dwError);
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
DestroyInterfaceList(
|
||
|
IN PIPSEC_INTERFACE pIfListToDelete
|
||
|
)
|
||
|
{
|
||
|
PIPSEC_INTERFACE pIf = NULL;
|
||
|
PIPSEC_INTERFACE pTempIf = NULL;
|
||
|
|
||
|
pIf = pIfListToDelete;
|
||
|
|
||
|
while (pIf) {
|
||
|
pTempIf = pIf;
|
||
|
pIf = pIf->pNext;
|
||
|
FreeIpsecInterface(pTempIf);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
OnInterfaceChangeEvent(
|
||
|
)
|
||
|
{
|
||
|
DWORD dwError = 0;
|
||
|
PIPSEC_INTERFACE pIfList = NULL;
|
||
|
PIPSEC_INTERFACE pObseleteIfList = NULL;
|
||
|
PIPSEC_INTERFACE pNewIfList = NULL;
|
||
|
PIPSEC_INTERFACE pExistingIfList = NULL;
|
||
|
DWORD dwMMError = 0;
|
||
|
DWORD dwTxError = 0;
|
||
|
DWORD dwTnError = 0;
|
||
|
|
||
|
|
||
|
dwError = ResetInterfaceChangeEvent();
|
||
|
|
||
|
(VOID) GetInterfaceListFromStack(
|
||
|
&pIfList
|
||
|
);
|
||
|
|
||
|
ENTER_SPD_SECTION();
|
||
|
|
||
|
pExistingIfList = gpInterfaceList;
|
||
|
|
||
|
// Interface List from Stack can be NULL.
|
||
|
|
||
|
FormObseleteAndNewIfLists(
|
||
|
pIfList,
|
||
|
&pExistingIfList,
|
||
|
&pObseleteIfList,
|
||
|
&pNewIfList
|
||
|
);
|
||
|
|
||
|
if (pNewIfList) {
|
||
|
AddToInterfaceList(
|
||
|
pNewIfList,
|
||
|
&pExistingIfList
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if (pObseleteIfList) {
|
||
|
DestroyInterfaceList(
|
||
|
pObseleteIfList
|
||
|
);
|
||
|
}
|
||
|
|
||
|
gpInterfaceList = pExistingIfList;
|
||
|
|
||
|
(VOID) ApplyIfChangeToIniMMFilters(
|
||
|
&dwMMError,
|
||
|
pExistingIfList
|
||
|
);
|
||
|
|
||
|
(VOID) ApplyIfChangeToIniTxFilters(
|
||
|
&dwTxError,
|
||
|
pExistingIfList
|
||
|
);
|
||
|
|
||
|
(VOID) ApplyIfChangeToIniTnFilters(
|
||
|
&dwTnError,
|
||
|
pExistingIfList
|
||
|
);
|
||
|
|
||
|
LEAVE_SPD_SECTION();
|
||
|
|
||
|
if (dwMMError || dwTxError || dwTnError) {
|
||
|
AuditEvent(
|
||
|
SE_CATEGID_POLICY_CHANGE,
|
||
|
SE_AUDITID_IPSEC_POLICY_CHANGED,
|
||
|
IPSECSVC_FAILED_PNP_FILTER_PROCESSING,
|
||
|
NULL,
|
||
|
FALSE,
|
||
|
TRUE
|
||
|
);
|
||
|
}
|
||
|
|
||
|
return (dwError);
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
FormObseleteAndNewIfLists(
|
||
|
IN PIPSEC_INTERFACE pIfList,
|
||
|
IN OUT PIPSEC_INTERFACE * ppExistingIfList,
|
||
|
OUT PIPSEC_INTERFACE * ppObseleteIfList,
|
||
|
OUT PIPSEC_INTERFACE * ppNewIfList
|
||
|
)
|
||
|
{
|
||
|
PIPSEC_INTERFACE pObseleteIfList = NULL;
|
||
|
PIPSEC_INTERFACE pNewIfList = NULL;
|
||
|
PIPSEC_INTERFACE pIf = NULL;
|
||
|
PIPSEC_INTERFACE pNewIf = NULL;
|
||
|
PIPSEC_INTERFACE pTempIf = NULL;
|
||
|
BOOL bInterfaceExists = FALSE;
|
||
|
PIPSEC_INTERFACE pExistingIf = NULL;
|
||
|
PIPSEC_INTERFACE pExistingIfList = NULL;
|
||
|
|
||
|
pExistingIfList = *ppExistingIfList;
|
||
|
|
||
|
MarkInterfaceListSuspect(
|
||
|
pExistingIfList
|
||
|
);
|
||
|
|
||
|
pIf = pIfList;
|
||
|
|
||
|
while (pIf) {
|
||
|
|
||
|
bInterfaceExists = InterfaceExistsInList(
|
||
|
pIf,
|
||
|
pExistingIfList,
|
||
|
&pExistingIf
|
||
|
);
|
||
|
|
||
|
if (bInterfaceExists) {
|
||
|
|
||
|
// Interface already exists in the list.
|
||
|
// Delete the interface.
|
||
|
|
||
|
pTempIf = pIf;
|
||
|
pIf = pIf->pNext;
|
||
|
FreeIpsecInterface(pTempIf);
|
||
|
|
||
|
// The corresponding entry in the original interface list
|
||
|
// is not a suspect any more.
|
||
|
|
||
|
pExistingIf->bIsASuspect = FALSE;
|
||
|
|
||
|
}
|
||
|
else {
|
||
|
|
||
|
// This is a new interface.
|
||
|
// Add it to the list of new interfaces.
|
||
|
|
||
|
pNewIf = pIf;
|
||
|
pIf = pIf->pNext;
|
||
|
|
||
|
pTempIf = pNewIfList;
|
||
|
pNewIfList = pNewIf;
|
||
|
pNewIfList->pNext = pTempIf;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
DeleteObseleteInterfaces(
|
||
|
&pExistingIfList,
|
||
|
&pObseleteIfList
|
||
|
);
|
||
|
|
||
|
*ppExistingIfList = pExistingIfList;
|
||
|
*ppObseleteIfList = pObseleteIfList;
|
||
|
*ppNewIfList = pNewIfList;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
AddToInterfaceList(
|
||
|
IN PIPSEC_INTERFACE pIfListToAppend,
|
||
|
OUT PIPSEC_INTERFACE * ppOriginalIfList
|
||
|
)
|
||
|
{
|
||
|
PIPSEC_INTERFACE pIf = NULL;
|
||
|
PIPSEC_INTERFACE pIfToAppend = NULL;
|
||
|
PIPSEC_INTERFACE pTempIf = NULL;
|
||
|
|
||
|
pIf = pIfListToAppend;
|
||
|
|
||
|
while (pIf) {
|
||
|
|
||
|
pIfToAppend = pIf;
|
||
|
pIf = pIf->pNext;
|
||
|
|
||
|
pTempIf = *ppOriginalIfList;
|
||
|
*ppOriginalIfList = pIfToAppend;
|
||
|
(*ppOriginalIfList)->pNext = pTempIf;
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
MarkInterfaceListSuspect(
|
||
|
IN PIPSEC_INTERFACE pExistingIfList
|
||
|
)
|
||
|
{
|
||
|
PIPSEC_INTERFACE pIf = NULL;
|
||
|
|
||
|
pIf = pExistingIfList;
|
||
|
|
||
|
while (pIf) {
|
||
|
pIf->bIsASuspect = TRUE;
|
||
|
pIf = pIf->pNext;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
DeleteObseleteInterfaces(
|
||
|
IN OUT PIPSEC_INTERFACE * ppExistingIfList,
|
||
|
OUT PIPSEC_INTERFACE * ppObseleteIfList
|
||
|
)
|
||
|
{
|
||
|
PIPSEC_INTERFACE pCurIf = NULL;
|
||
|
PIPSEC_INTERFACE pPreIf = NULL;
|
||
|
PIPSEC_INTERFACE pStartIf = NULL;
|
||
|
PIPSEC_INTERFACE pObseleteIfList = NULL;
|
||
|
PIPSEC_INTERFACE pObseleteIf = NULL;
|
||
|
PIPSEC_INTERFACE pTempIf = NULL;
|
||
|
|
||
|
pCurIf = *ppExistingIfList;
|
||
|
pStartIf = pCurIf;
|
||
|
|
||
|
while (pCurIf) {
|
||
|
|
||
|
if (pCurIf->bIsASuspect) {
|
||
|
|
||
|
pObseleteIf = pCurIf;
|
||
|
pCurIf = pCurIf->pNext;
|
||
|
|
||
|
if (pPreIf) {
|
||
|
pPreIf->pNext = pCurIf;
|
||
|
}
|
||
|
else {
|
||
|
pStartIf = pCurIf;
|
||
|
}
|
||
|
|
||
|
pTempIf = pObseleteIfList;
|
||
|
pObseleteIfList = pObseleteIf;
|
||
|
pObseleteIfList->pNext = pTempIf;
|
||
|
|
||
|
}
|
||
|
else {
|
||
|
|
||
|
pPreIf = pCurIf;
|
||
|
pCurIf = pCurIf->pNext;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
*ppObseleteIfList = pObseleteIfList;
|
||
|
*ppExistingIfList = pStartIf;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
InterfaceExistsInList(
|
||
|
IN PIPSEC_INTERFACE pTestIf,
|
||
|
IN PIPSEC_INTERFACE pExistingIfList,
|
||
|
OUT PIPSEC_INTERFACE * ppExistingIf
|
||
|
)
|
||
|
{
|
||
|
PIPSEC_INTERFACE pIf = NULL;
|
||
|
PIPSEC_INTERFACE pExistingIf = NULL;
|
||
|
BOOL bIfExists = FALSE;
|
||
|
|
||
|
pIf = pExistingIfList;
|
||
|
|
||
|
while (pIf) {
|
||
|
|
||
|
if ((pIf->dwIndex == pTestIf->dwIndex) &&
|
||
|
(pIf->IpAddress == pTestIf->IpAddress)) {
|
||
|
|
||
|
bIfExists = TRUE;
|
||
|
pExistingIf = pIf;
|
||
|
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
|
||
|
pIf = pIf->pNext;
|
||
|
|
||
|
}
|
||
|
|
||
|
*ppExistingIf = pExistingIf;
|
||
|
return (bIfExists);
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
GetInterfaceListFromStack(
|
||
|
OUT PIPSEC_INTERFACE *ppIfList
|
||
|
)
|
||
|
{
|
||
|
DWORD dwError = 0;
|
||
|
PMIB_IPADDRTABLE pMibIpAddrTable = NULL;
|
||
|
PMIB_IFTABLE pMibIfTable = NULL;
|
||
|
PIPSEC_INTERFACE pIfList = NULL;
|
||
|
|
||
|
dwError = PaPNPGetIpAddrTable(
|
||
|
&pMibIpAddrTable
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
dwError = PaPNPGetIfTable(
|
||
|
&pMibIfTable
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
dwError = GenerateInterfaces(
|
||
|
pMibIpAddrTable,
|
||
|
pMibIfTable,
|
||
|
&pIfList
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
*ppIfList = pIfList;
|
||
|
|
||
|
cleanup:
|
||
|
|
||
|
if (pMibIfTable) {
|
||
|
LocalFree(pMibIfTable);
|
||
|
}
|
||
|
|
||
|
if (pMibIpAddrTable) {
|
||
|
LocalFree(pMibIpAddrTable);
|
||
|
}
|
||
|
|
||
|
return (dwError);
|
||
|
|
||
|
error:
|
||
|
|
||
|
AuditEvent(
|
||
|
SE_CATEGID_POLICY_CHANGE,
|
||
|
SE_AUDITID_IPSEC_POLICY_CHANGED,
|
||
|
IPSECSVC_INTERFACE_LIST_INCOMPLETE,
|
||
|
NULL,
|
||
|
FALSE,
|
||
|
TRUE
|
||
|
);
|
||
|
*ppIfList = NULL;
|
||
|
goto cleanup;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
GenerateInterfaces(
|
||
|
IN PMIB_IPADDRTABLE pMibIpAddrTable,
|
||
|
IN PMIB_IFTABLE pMibIfTable,
|
||
|
OUT PIPSEC_INTERFACE * ppIfList
|
||
|
)
|
||
|
{
|
||
|
DWORD dwError = 0;
|
||
|
DWORD dwInterfaceType = 0;
|
||
|
ULONG IpAddress = 0;
|
||
|
DWORD dwIndex = 0;
|
||
|
DWORD dwNumEntries = 0;
|
||
|
DWORD dwCnt = 0;
|
||
|
PMIB_IFROW pMibIfRow = NULL;
|
||
|
PIPSEC_INTERFACE pNewIf = NULL;
|
||
|
PIPSEC_INTERFACE pTempIf = NULL;
|
||
|
PIPSEC_INTERFACE pIfList = NULL;
|
||
|
DWORD dwNewIfsCnt = 0;
|
||
|
|
||
|
dwNumEntries = pMibIpAddrTable->dwNumEntries;
|
||
|
|
||
|
for (dwCnt = 0; dwCnt < dwNumEntries; dwCnt++) {
|
||
|
|
||
|
dwIndex = pMibIpAddrTable->table[dwCnt].dwIndex;
|
||
|
|
||
|
pMibIfRow = GetMibIfRow(
|
||
|
pMibIfTable,
|
||
|
dwIndex
|
||
|
);
|
||
|
if (!pMibIfRow) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
IpAddress = pMibIpAddrTable->table[dwCnt].dwAddr;
|
||
|
dwInterfaceType = pMibIfRow->dwType;
|
||
|
|
||
|
dwError = CreateNewInterface(
|
||
|
dwInterfaceType,
|
||
|
IpAddress,
|
||
|
dwIndex,
|
||
|
pMibIfRow,
|
||
|
&pNewIf
|
||
|
);
|
||
|
if (dwError) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
pTempIf = pIfList;
|
||
|
pIfList = pNewIf;
|
||
|
pIfList->pNext = pTempIf;
|
||
|
dwNewIfsCnt++;
|
||
|
|
||
|
}
|
||
|
|
||
|
if (dwNewIfsCnt) {
|
||
|
*ppIfList = pIfList;
|
||
|
dwError = ERROR_SUCCESS;
|
||
|
}
|
||
|
else {
|
||
|
*ppIfList = NULL;
|
||
|
dwError = ERROR_INVALID_DATA;
|
||
|
}
|
||
|
|
||
|
return (dwError);
|
||
|
}
|
||
|
|
||
|
|
||
|
PMIB_IFROW
|
||
|
GetMibIfRow(
|
||
|
IN PMIB_IFTABLE pMibIfTable,
|
||
|
IN DWORD dwIndex
|
||
|
)
|
||
|
{
|
||
|
DWORD i = 0;
|
||
|
PMIB_IFROW pMibIfRow = NULL;
|
||
|
|
||
|
for (i = 0; i < pMibIfTable->dwNumEntries; i++) {
|
||
|
|
||
|
if (pMibIfTable->table[i].dwIndex == dwIndex) {
|
||
|
pMibIfRow = &(pMibIfTable->table[i]);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
return (pMibIfRow);
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
CreateNewInterface(
|
||
|
IN DWORD dwInterfaceType,
|
||
|
IN ULONG IpAddress,
|
||
|
IN DWORD dwIndex,
|
||
|
IN PMIB_IFROW pMibIfRow,
|
||
|
OUT PIPSEC_INTERFACE * ppNewInterface
|
||
|
)
|
||
|
{
|
||
|
DWORD dwError = 0;
|
||
|
PIPSEC_INTERFACE pNewInterface = NULL;
|
||
|
LPWSTR pszString = NULL;
|
||
|
LPWSTR pszTemp = NULL;
|
||
|
WCHAR szDeviceName[MAXLEN_IFDESCR*sizeof(WCHAR)];
|
||
|
GUID gInterfaceID;
|
||
|
|
||
|
|
||
|
szDeviceName[0] = L'\0';
|
||
|
|
||
|
if (IpAddress == INADDR_ANY) {
|
||
|
dwError = ERROR_INVALID_DATA;
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
else {
|
||
|
if (dwInterfaceType == MIB_IF_TYPE_LOOPBACK) {
|
||
|
dwError = ERROR_INVALID_DATA;
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pszString = AllocSPDStr(pMibIfRow->wszName);
|
||
|
if (!pszString) {
|
||
|
dwError = ERROR_OUTOFMEMORY;
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
|
||
|
if (wcslen(pszString) <= wcslen(L"\\DEVICE\\TCPIP_")) {
|
||
|
dwError = ERROR_INVALID_DATA;
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
|
||
|
pszTemp = pszString + wcslen(L"\\DEVICE\\TCPIP_");
|
||
|
|
||
|
wGUIDFromString(pszTemp, &gInterfaceID);
|
||
|
|
||
|
pNewInterface = (PIPSEC_INTERFACE) AllocSPDMem(
|
||
|
sizeof(IPSEC_INTERFACE)
|
||
|
);
|
||
|
if (!pNewInterface) {
|
||
|
dwError = ERROR_OUTOFMEMORY;
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
|
||
|
pNewInterface->dwInterfaceType = dwInterfaceType;
|
||
|
pNewInterface->IpAddress = IpAddress;
|
||
|
pNewInterface->dwIndex = dwIndex;
|
||
|
pNewInterface->bIsASuspect = FALSE;
|
||
|
|
||
|
memcpy(
|
||
|
&pNewInterface->gInterfaceID,
|
||
|
&gInterfaceID,
|
||
|
sizeof(GUID)
|
||
|
);
|
||
|
|
||
|
pNewInterface->pszInterfaceName = NULL;
|
||
|
|
||
|
mbstowcs(
|
||
|
szDeviceName,
|
||
|
pMibIfRow->bDescr,
|
||
|
MAXLEN_IFDESCR
|
||
|
);
|
||
|
|
||
|
pNewInterface->pszDeviceName = AllocSPDStr(
|
||
|
szDeviceName
|
||
|
);
|
||
|
if (!pNewInterface->pszDeviceName) {
|
||
|
dwError = ERROR_OUTOFMEMORY;
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
|
||
|
pNewInterface->pNext = NULL;
|
||
|
|
||
|
*ppNewInterface = pNewInterface;
|
||
|
|
||
|
cleanup:
|
||
|
|
||
|
if (pszString) {
|
||
|
FreeSPDStr(pszString);
|
||
|
}
|
||
|
|
||
|
return(dwError);
|
||
|
|
||
|
error:
|
||
|
|
||
|
*ppNewInterface = NULL;
|
||
|
|
||
|
if (pNewInterface) {
|
||
|
FreeIpsecInterface(pNewInterface);
|
||
|
}
|
||
|
|
||
|
goto cleanup;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
MatchInterfaceType(
|
||
|
IN DWORD dwIfListEntryIfType,
|
||
|
IN IF_TYPE FilterIfType
|
||
|
)
|
||
|
{
|
||
|
BOOL bMatchesType = FALSE;
|
||
|
|
||
|
if (FilterIfType == INTERFACE_TYPE_ALL) {
|
||
|
bMatchesType = TRUE;
|
||
|
}
|
||
|
else if (FilterIfType == INTERFACE_TYPE_LAN) {
|
||
|
bMatchesType = IsLAN(dwIfListEntryIfType);
|
||
|
}
|
||
|
else if (FilterIfType == INTERFACE_TYPE_DIALUP) {
|
||
|
bMatchesType = IsDialUp(dwIfListEntryIfType);
|
||
|
}
|
||
|
|
||
|
return (bMatchesType);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
IsLAN(
|
||
|
IN DWORD dwInterfaceType
|
||
|
)
|
||
|
{
|
||
|
BOOL bIsLAN = FALSE;
|
||
|
|
||
|
if ((dwInterfaceType == MIB_IF_TYPE_ETHERNET) ||
|
||
|
(dwInterfaceType == MIB_IF_TYPE_FDDI) ||
|
||
|
(dwInterfaceType == MIB_IF_TYPE_TOKENRING)) {
|
||
|
bIsLAN = TRUE;
|
||
|
}
|
||
|
|
||
|
return (bIsLAN);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
IsDialUp(
|
||
|
IN DWORD dwInterfaceType
|
||
|
)
|
||
|
{
|
||
|
BOOL bIsDialUp = FALSE;
|
||
|
|
||
|
if ((dwInterfaceType == MIB_IF_TYPE_PPP) ||
|
||
|
(dwInterfaceType == MIB_IF_TYPE_SLIP)) {
|
||
|
bIsDialUp = TRUE;
|
||
|
}
|
||
|
|
||
|
return (bIsDialUp);
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
InitializeInterfaceChangeEvent(
|
||
|
)
|
||
|
{
|
||
|
DWORD dwError = 0;
|
||
|
WORD wsaVersion = MAKEWORD(2,0);
|
||
|
|
||
|
memset(&gwsaOverlapped, 0, sizeof(WSAOVERLAPPED));
|
||
|
|
||
|
// Start up WinSock.
|
||
|
|
||
|
dwError = WSAStartup(
|
||
|
wsaVersion,
|
||
|
&gwsaData
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
gbwsaStarted = TRUE;
|
||
|
|
||
|
if ((LOBYTE(gwsaData.wVersion) != LOBYTE(wsaVersion)) ||
|
||
|
(HIBYTE(gwsaData.wVersion) != HIBYTE(wsaVersion))) {
|
||
|
dwError = WSAVERNOTSUPPORTED;
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
|
||
|
// Set up the Socket.
|
||
|
|
||
|
gIfChangeEventSocket = WSASocket(
|
||
|
AF_INET,
|
||
|
SOCK_DGRAM,
|
||
|
0,
|
||
|
NULL,
|
||
|
0,
|
||
|
WSA_FLAG_OVERLAPPED
|
||
|
);
|
||
|
if (gIfChangeEventSocket == INVALID_SOCKET) {
|
||
|
dwError = WSAGetLastError();
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
|
||
|
ghIfChangeEvent = WSACreateEvent();
|
||
|
if (ghIfChangeEvent == WSA_INVALID_EVENT) {
|
||
|
dwError = WSAGetLastError();
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
|
||
|
ghOverlapEvent = WSACreateEvent();
|
||
|
if (ghOverlapEvent == WSA_INVALID_EVENT) {
|
||
|
dwError = WSAGetLastError();
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
gwsaOverlapped.hEvent = ghOverlapEvent;
|
||
|
|
||
|
error:
|
||
|
|
||
|
return (dwError);
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
ResetInterfaceChangeEvent(
|
||
|
)
|
||
|
{
|
||
|
DWORD dwError = 0;
|
||
|
LONG lNetworkEvents = FD_ADDRESS_LIST_CHANGE;
|
||
|
DWORD dwOutSize = 0;
|
||
|
|
||
|
ResetEvent(ghIfChangeEvent);
|
||
|
gbIsIoctlPended = FALSE;
|
||
|
|
||
|
dwError = WSAIoctl(
|
||
|
gIfChangeEventSocket,
|
||
|
SIO_ADDRESS_LIST_CHANGE,
|
||
|
NULL,
|
||
|
0,
|
||
|
NULL,
|
||
|
0,
|
||
|
&dwOutSize,
|
||
|
&gwsaOverlapped,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
if (dwError == SOCKET_ERROR) {
|
||
|
dwError = WSAGetLastError();
|
||
|
if (dwError != ERROR_IO_PENDING) {
|
||
|
return (dwError);
|
||
|
}
|
||
|
else {
|
||
|
gbIsIoctlPended = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
dwError = WSAEventSelect(
|
||
|
gIfChangeEventSocket,
|
||
|
ghIfChangeEvent,
|
||
|
lNetworkEvents
|
||
|
);
|
||
|
|
||
|
return (dwError);
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
DestroyInterfaceChangeEvent(
|
||
|
)
|
||
|
{
|
||
|
DWORD dwStatus = 0;
|
||
|
BOOL bDoneWaiting = FALSE;
|
||
|
|
||
|
|
||
|
if (gIfChangeEventSocket) {
|
||
|
if (gbIsIoctlPended) {
|
||
|
CancelIo((HANDLE) gIfChangeEventSocket);
|
||
|
while (!bDoneWaiting) {
|
||
|
dwStatus = WaitForSingleObject(
|
||
|
ghOverlapEvent,
|
||
|
1000
|
||
|
);
|
||
|
switch (dwStatus) {
|
||
|
case WAIT_OBJECT_0:
|
||
|
bDoneWaiting = TRUE;
|
||
|
break;
|
||
|
case WAIT_TIMEOUT:
|
||
|
ASSERT(FALSE);
|
||
|
break;
|
||
|
default:
|
||
|
bDoneWaiting = TRUE;
|
||
|
ASSERT(FALSE);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
closesocket(gIfChangeEventSocket);
|
||
|
}
|
||
|
|
||
|
if (ghIfChangeEvent) {
|
||
|
CloseHandle(ghIfChangeEvent);
|
||
|
}
|
||
|
|
||
|
if (ghOverlapEvent) {
|
||
|
CloseHandle(ghOverlapEvent);
|
||
|
}
|
||
|
|
||
|
if (gbwsaStarted) {
|
||
|
WSACleanup();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
HANDLE
|
||
|
GetInterfaceChangeEvent(
|
||
|
)
|
||
|
{
|
||
|
return ghOverlapEvent;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
IsMyAddress(
|
||
|
IN ULONG IpAddrToCheck,
|
||
|
IN ULONG IpAddrMask,
|
||
|
IN PIPSEC_INTERFACE pExistingIfList
|
||
|
)
|
||
|
{
|
||
|
BOOL bIsMyAddress = FALSE;
|
||
|
PIPSEC_INTERFACE pIf = NULL;
|
||
|
|
||
|
pIf = pExistingIfList;
|
||
|
|
||
|
while (pIf) {
|
||
|
|
||
|
if ((pIf->IpAddress & IpAddrMask) ==
|
||
|
(IpAddrToCheck & IpAddrMask)) {
|
||
|
|
||
|
bIsMyAddress = TRUE;
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
|
||
|
pIf = pIf->pNext;
|
||
|
|
||
|
}
|
||
|
|
||
|
return (bIsMyAddress);
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
PrintInterfaceList(
|
||
|
IN PIPSEC_INTERFACE pInterfaceList
|
||
|
)
|
||
|
{
|
||
|
WCHAR PrintData[256];
|
||
|
PIPSEC_INTERFACE pInterface = NULL;
|
||
|
DWORD i = 0;
|
||
|
|
||
|
pInterface = pInterfaceList;
|
||
|
|
||
|
while (pInterface) {
|
||
|
|
||
|
wsprintf(PrintData, L"Interface Entry no. %d\n", i+1);
|
||
|
OutputDebugString((LPCTSTR) PrintData);
|
||
|
|
||
|
wsprintf(PrintData, L"\tInterface Type: %d\n", pInterface->dwInterfaceType);
|
||
|
OutputDebugString((LPCTSTR) PrintData);
|
||
|
|
||
|
wsprintf(PrintData, L"\tIP Address: %s\n", pInterface->IpAddress);
|
||
|
OutputDebugString((LPCTSTR) PrintData);
|
||
|
|
||
|
wsprintf(PrintData, L"\tIndex: %d\n", pInterface->dwIndex);
|
||
|
OutputDebugString((LPCTSTR) PrintData);
|
||
|
|
||
|
wsprintf(PrintData, L"\tIs a suspect: %d\n", pInterface->bIsASuspect);
|
||
|
OutputDebugString((LPCTSTR) PrintData);
|
||
|
|
||
|
i++;
|
||
|
pInterface = pInterface->pNext;
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
GetMatchingInterfaces(
|
||
|
IF_TYPE FilterInterfaceType,
|
||
|
PIPSEC_INTERFACE pExistingIfList,
|
||
|
MATCHING_ADDR ** ppMatchingAddresses,
|
||
|
DWORD * pdwAddrCnt
|
||
|
)
|
||
|
{
|
||
|
DWORD dwError = 0;
|
||
|
MATCHING_ADDR * pMatchingAddresses = NULL;
|
||
|
PIPSEC_INTERFACE pTempIf = NULL;
|
||
|
BOOL bMatches = FALSE;
|
||
|
DWORD dwCnt = 0;
|
||
|
DWORD i = 0;
|
||
|
|
||
|
pTempIf = pExistingIfList;
|
||
|
while (pTempIf) {
|
||
|
|
||
|
bMatches = MatchInterfaceType(
|
||
|
pTempIf->dwInterfaceType,
|
||
|
FilterInterfaceType
|
||
|
);
|
||
|
if (bMatches) {
|
||
|
dwCnt++;
|
||
|
}
|
||
|
pTempIf = pTempIf->pNext;
|
||
|
|
||
|
}
|
||
|
|
||
|
if (!dwCnt) {
|
||
|
dwError = ERROR_SUCCESS;
|
||
|
BAIL_ON_WIN32_SUCCESS(dwError);
|
||
|
}
|
||
|
|
||
|
dwError = AllocateSPDMemory(
|
||
|
sizeof(MATCHING_ADDR) * dwCnt,
|
||
|
(LPVOID *) &pMatchingAddresses
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
pTempIf = pExistingIfList;
|
||
|
while (pTempIf) {
|
||
|
|
||
|
bMatches = MatchInterfaceType(
|
||
|
pTempIf->dwInterfaceType,
|
||
|
FilterInterfaceType
|
||
|
);
|
||
|
if (bMatches) {
|
||
|
pMatchingAddresses[i].uIpAddr = pTempIf->IpAddress;
|
||
|
memcpy(
|
||
|
&pMatchingAddresses[i].gInterfaceID,
|
||
|
&pTempIf->gInterfaceID,
|
||
|
sizeof(GUID)
|
||
|
);
|
||
|
i++;
|
||
|
}
|
||
|
pTempIf = pTempIf->pNext;
|
||
|
|
||
|
}
|
||
|
|
||
|
*ppMatchingAddresses = pMatchingAddresses;
|
||
|
*pdwAddrCnt = i;
|
||
|
return (dwError);
|
||
|
|
||
|
success:
|
||
|
error:
|
||
|
|
||
|
*ppMatchingAddresses = NULL;
|
||
|
*pdwAddrCnt = 0;
|
||
|
return (dwError);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
InterfaceAddrIsLocal(
|
||
|
ULONG uIpAddr,
|
||
|
ULONG uIpAddrMask,
|
||
|
MATCHING_ADDR * pLocalAddresses,
|
||
|
DWORD dwAddrCnt
|
||
|
)
|
||
|
{
|
||
|
BOOL bIsLocal = FALSE;
|
||
|
DWORD i = 0;
|
||
|
|
||
|
|
||
|
for (i = 0; i < dwAddrCnt; i++) {
|
||
|
|
||
|
if ((pLocalAddresses[i].uIpAddr & uIpAddrMask) ==
|
||
|
(uIpAddr & uIpAddrMask)) {
|
||
|
|
||
|
bIsLocal = TRUE;
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
return (bIsLocal);
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
FreeIpsecInterface(
|
||
|
PIPSEC_INTERFACE pIpsecInterface
|
||
|
)
|
||
|
{
|
||
|
if (pIpsecInterface) {
|
||
|
|
||
|
if (pIpsecInterface->pszInterfaceName) {
|
||
|
FreeSPDStr(pIpsecInterface->pszInterfaceName);
|
||
|
}
|
||
|
|
||
|
if (pIpsecInterface->pszDeviceName) {
|
||
|
FreeSPDStr(pIpsecInterface->pszDeviceName);
|
||
|
}
|
||
|
|
||
|
FreeSPDMem(pIpsecInterface);
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
EnumIPSecInterfaces(
|
||
|
LPWSTR pServerName,
|
||
|
PIPSEC_INTERFACE_INFO pIpsecIfTemplate,
|
||
|
PIPSEC_INTERFACE_INFO * ppIpsecInterfaces,
|
||
|
DWORD dwPreferredNumEntries,
|
||
|
LPDWORD pdwNumInterfaces,
|
||
|
LPDWORD pdwNumTotalInterfaces,
|
||
|
LPDWORD pdwResumeHandle,
|
||
|
DWORD dwFlags
|
||
|
)
|
||
|
{
|
||
|
DWORD dwError = 0;
|
||
|
DWORD dwResumeHandle = 0;
|
||
|
DWORD dwNumToEnum = 0;
|
||
|
PIPSEC_INTERFACE pIpsecIf = NULL;
|
||
|
DWORD dwNumTotalInterfaces = 0;
|
||
|
DWORD i = 0;
|
||
|
PIPSEC_INTERFACE pTempIf = NULL;
|
||
|
DWORD dwNumInterfaces = 0;
|
||
|
PIPSEC_INTERFACE_INFO pIpsecInterfaces = NULL;
|
||
|
PIPSEC_INTERFACE_INFO pTempInterface = NULL;
|
||
|
|
||
|
|
||
|
dwResumeHandle = *pdwResumeHandle;
|
||
|
|
||
|
if (!dwPreferredNumEntries || (dwPreferredNumEntries > MAX_INTERFACE_ENUM_COUNT)) {
|
||
|
dwNumToEnum = MAX_INTERFACE_ENUM_COUNT;
|
||
|
}
|
||
|
else {
|
||
|
dwNumToEnum = dwPreferredNumEntries;
|
||
|
}
|
||
|
|
||
|
ENTER_SPD_SECTION();
|
||
|
|
||
|
dwError = ValidateSecurity(
|
||
|
SPD_OBJECT_SERVER,
|
||
|
SERVER_ACCESS_ADMINISTER,
|
||
|
NULL,
|
||
|
NULL
|
||
|
);
|
||
|
BAIL_ON_LOCK_ERROR(dwError);
|
||
|
|
||
|
pIpsecIf = gpInterfaceList;
|
||
|
|
||
|
for (i = 0; (i < dwResumeHandle) && (pIpsecIf != NULL); i++) {
|
||
|
dwNumTotalInterfaces++;
|
||
|
pIpsecIf = pIpsecIf->pNext;
|
||
|
}
|
||
|
|
||
|
if (!pIpsecIf) {
|
||
|
dwError = ERROR_NO_DATA;
|
||
|
BAIL_ON_LOCK_ERROR(dwError);
|
||
|
}
|
||
|
|
||
|
pTempIf = pIpsecIf;
|
||
|
|
||
|
while (pTempIf && (dwNumInterfaces < dwNumToEnum)) {
|
||
|
dwNumTotalInterfaces++;
|
||
|
dwNumInterfaces++;
|
||
|
pTempIf = pTempIf->pNext;
|
||
|
}
|
||
|
|
||
|
while (pTempIf) {
|
||
|
dwNumTotalInterfaces++;
|
||
|
pTempIf = pTempIf->pNext;
|
||
|
}
|
||
|
|
||
|
dwError = SPDApiBufferAllocate(
|
||
|
sizeof(IPSEC_INTERFACE_INFO)*dwNumInterfaces,
|
||
|
&pIpsecInterfaces
|
||
|
);
|
||
|
BAIL_ON_LOCK_ERROR(dwError);
|
||
|
|
||
|
pTempIf = pIpsecIf;
|
||
|
pTempInterface = pIpsecInterfaces;
|
||
|
|
||
|
for (i = 0; i < dwNumInterfaces; i++) {
|
||
|
|
||
|
dwError = CopyIpsecInterface(
|
||
|
pTempIf,
|
||
|
pTempInterface
|
||
|
);
|
||
|
BAIL_ON_LOCK_ERROR(dwError);
|
||
|
|
||
|
pTempIf = pTempIf->pNext;
|
||
|
pTempInterface++;
|
||
|
|
||
|
}
|
||
|
|
||
|
*ppIpsecInterfaces = pIpsecInterfaces;
|
||
|
*pdwNumInterfaces = dwNumInterfaces;
|
||
|
*pdwNumTotalInterfaces = dwNumTotalInterfaces;
|
||
|
*pdwResumeHandle = dwResumeHandle + dwNumInterfaces;
|
||
|
|
||
|
LEAVE_SPD_SECTION();
|
||
|
|
||
|
return (dwError);
|
||
|
|
||
|
lock:
|
||
|
|
||
|
LEAVE_SPD_SECTION();
|
||
|
|
||
|
if (pIpsecInterfaces) {
|
||
|
FreeIpsecInterfaceInfos(
|
||
|
i,
|
||
|
pIpsecInterfaces
|
||
|
);
|
||
|
}
|
||
|
|
||
|
*ppIpsecInterfaces = NULL;
|
||
|
*pdwNumInterfaces = 0;
|
||
|
*pdwNumTotalInterfaces = 0;
|
||
|
*pdwResumeHandle = dwResumeHandle;
|
||
|
|
||
|
return (dwError);
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
CopyIpsecInterface(
|
||
|
PIPSEC_INTERFACE pIpsecIf,
|
||
|
PIPSEC_INTERFACE_INFO pIpsecInterface
|
||
|
)
|
||
|
{
|
||
|
DWORD dwError = 0;
|
||
|
|
||
|
|
||
|
memcpy(
|
||
|
&(pIpsecInterface->gInterfaceID),
|
||
|
&(pIpsecIf->gInterfaceID),
|
||
|
sizeof(GUID)
|
||
|
);
|
||
|
|
||
|
pIpsecInterface->dwIndex = pIpsecIf->dwIndex;
|
||
|
|
||
|
if (!(pIpsecIf->pszInterfaceName)) {
|
||
|
(VOID) GetInterfaceName(
|
||
|
pIpsecIf->gInterfaceID,
|
||
|
&pIpsecIf->pszInterfaceName
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if (pIpsecIf->pszInterfaceName) {
|
||
|
|
||
|
dwError = SPDApiBufferAllocate(
|
||
|
wcslen(pIpsecIf->pszInterfaceName)*sizeof(WCHAR)
|
||
|
+ sizeof(WCHAR),
|
||
|
&(pIpsecInterface->pszInterfaceName)
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
wcscpy(pIpsecInterface->pszInterfaceName, pIpsecIf->pszInterfaceName);
|
||
|
|
||
|
}
|
||
|
|
||
|
dwError = SPDApiBufferAllocate(
|
||
|
wcslen(pIpsecIf->pszDeviceName)*sizeof(WCHAR)
|
||
|
+ sizeof(WCHAR),
|
||
|
&(pIpsecInterface->pszDeviceName)
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
wcscpy(pIpsecInterface->pszDeviceName, pIpsecIf->pszDeviceName);
|
||
|
|
||
|
pIpsecInterface->dwInterfaceType = pIpsecIf->dwInterfaceType;
|
||
|
|
||
|
pIpsecInterface->uIpAddr = pIpsecIf->IpAddress;
|
||
|
|
||
|
return (dwError);
|
||
|
|
||
|
error:
|
||
|
|
||
|
if (pIpsecInterface->pszInterfaceName) {
|
||
|
SPDApiBufferFree(pIpsecInterface->pszInterfaceName);
|
||
|
}
|
||
|
|
||
|
return (dwError);
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
FreeIpsecInterfaceInfos(
|
||
|
DWORD dwNumInterfaces,
|
||
|
PIPSEC_INTERFACE_INFO pIpsecInterfaces
|
||
|
)
|
||
|
{
|
||
|
PIPSEC_INTERFACE_INFO pTempInterface = NULL;
|
||
|
DWORD i = 0;
|
||
|
|
||
|
|
||
|
if (!pIpsecInterfaces) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
pTempInterface = pIpsecInterfaces;
|
||
|
|
||
|
for (i = 0; i < dwNumInterfaces; i++) {
|
||
|
|
||
|
if (pTempInterface->pszInterfaceName) {
|
||
|
SPDApiBufferFree(pTempInterface->pszInterfaceName);
|
||
|
}
|
||
|
|
||
|
if (pTempInterface->pszDeviceName) {
|
||
|
SPDApiBufferFree(pTempInterface->pszDeviceName);
|
||
|
}
|
||
|
|
||
|
pTempInterface++;
|
||
|
|
||
|
}
|
||
|
|
||
|
SPDApiBufferFree(pIpsecInterfaces);
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
GetInterfaceName(
|
||
|
GUID gInterfaceID,
|
||
|
LPWSTR * ppszInterfaceName
|
||
|
)
|
||
|
{
|
||
|
DWORD dwError = 0;
|
||
|
DWORD dwSize = 0;
|
||
|
WCHAR szInterfaceName[512];
|
||
|
|
||
|
|
||
|
*ppszInterfaceName = NULL;
|
||
|
szInterfaceName[0] = L'\0';
|
||
|
|
||
|
dwSize = sizeof(szInterfaceName)/sizeof(WCHAR);
|
||
|
|
||
|
dwError = NhGetInterfaceNameFromGuid(
|
||
|
&gInterfaceID,
|
||
|
szInterfaceName,
|
||
|
&dwSize,
|
||
|
FALSE,
|
||
|
FALSE
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
*ppszInterfaceName = AllocSPDStr(
|
||
|
szInterfaceName
|
||
|
);
|
||
|
|
||
|
error:
|
||
|
|
||
|
return (dwError);
|
||
|
}
|
||
|
|