Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

2591 lines
63 KiB

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
net\sockets\tcpcmd\iphlpapi\internal.c
Abstract:
Contains the private APIs exported by IPHLPAP.DLL These
are exposed because of the MIB-II subagent, and to allow
more flexible use of the dll
Revision History:
Amritansh Raghav
--*/
#include "inc.h"
#pragma hdrstop
HANDLE AddressChangeNotification = NULL;
HANDLE RouteChangeNotification = NULL;
HANDLE ChangeNotificationHandle = INVALID_HANDLE_VALUE;
extern HANDLE g_hIPDriverHandle;
extern HANDLE g_hIPGetDriverHandle;
HANDLE Change6NotificationHandle = INVALID_HANDLE_VALUE;
extern HANDLE g_hIP6DriverHandle;
extern HANDLE g_hIP6GetDriverHandle;
#define ROUTE_CHANGE 0
#define ADDRESS_CHANGE 1
#define TERMINATE_EVENT 2
int ThreadCreated=0;
typedef VOID (*PFNChangeHandler)(PVOID pContext);
typedef VOID (*PFNChangeHandler)(PVOID pContext);
DWORD
NotifyRouteChangeEx(
PHANDLE pHandle,
LPOVERLAPPED pOverLapped,
BOOL bExQueue
);
typedef struct
{
LIST_ENTRY ListEntry;
PVOID context;
PFNChangeHandler Proc;
}NotifyContext;
DWORD
WINAPI
GetNumberOfInterfaces(
PDWORD pdwNumIf
);
LIST_ENTRY AddrNotifyListHead;
LIST_ENTRY RouteNotifyListHead;
int
TCPSendIoctl(
HANDLE hHandle,
ulong Ioctl,
void *InBuf,
ulong *InBufLen,
void *OutBuf,
ulong *OutBufLen
);
BOOL
IsRouterRunning(VOID);
BOOL
IsRouterSettingRoutes(VOID);
extern DWORD IPv4ToMibOperStatus[];
#define NUM_IPV4_OPER_STATUSES (IF_OPER_STATUS_OPERATIONAL+1)
DWORD
InternalGetIfTable(
OUT MIB_IFTABLE **ppIfTable,
IN HANDLE hHeap,
IN DWORD dwAllocFlags
)
{
MIB_OPAQUE_QUERY mqQuery;
PMIB_OPAQUE_INFO pInfo;
PMIB_IFTABLE pTable;
DWORD dwResult, dwOutEntrySize, i;
TraceEnter("InternalGetIfTable");
*ppIfTable = NULL;
#ifndef CHICAGO
if(IsRouterRunning())
{
mqQuery.dwVarId = IF_TABLE;
dwResult = MprAdminMIBEntryGet(g_hMIBServer,
PID_IP,
IPRTRMGR_PID,
(PVOID)&mqQuery,
sizeof(MIB_OPAQUE_QUERY),
(PVOID)&pInfo,
&dwOutEntrySize);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"InternalGetIfTable: MprAdminMIBEntryGet failed with error %x",
dwResult);
TraceLeave("InternalGetIfTable");
return dwResult;
}
*ppIfTable = HeapAlloc(hHeap,
dwAllocFlags,
dwOutEntrySize);
if(*ppIfTable is NULL)
{
dwResult = ERROR_NOT_ENOUGH_MEMORY;
Trace1(ERR,"InternalGetIfTable: Allocation failed with error %d",
dwResult);
TraceLeave("InternalGetIfTable");
MprAdminMIBBufferFree((PVOID)pInfo);
return dwResult;
}
CAST_MIB_INFO(pInfo, PMIB_IFTABLE, pTable);
Trace3(ERR, "**pTable %x pInfo %x rgdata %x\n",
pTable, pInfo, pInfo->rgbyData);
CopyMemory((PVOID)(*ppIfTable),
(PVOID)pTable,
SIZEOF_IFTABLE(pTable->dwNumEntries));
MprAdminMIBBufferFree((PVOID)pInfo);
}
else
{
#endif
dwResult = AllocateAndGetIfTableFromStack(ppIfTable,
TRUE,
hHeap,
dwAllocFlags,
TRUE);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,
"InternalGetIfTable: AllocateAndGetIfTableFromStack failed with error %x",
dwResult);
TraceLeave("InternalGetIfTable");
return dwResult;
}
#ifndef CHICAGO
}
#endif
//
// Convert operational status to the numbering space used in the
// MIB RFC's.
//
for (i = 0; i < (*ppIfTable)->dwNumEntries; i++)
{
(*ppIfTable)->table[i].dwOperStatus =
((*ppIfTable)->table[i].dwOperStatus < NUM_IPV4_OPER_STATUSES)
? IPv4ToMibOperStatus[(*ppIfTable)->table[i].dwOperStatus]
: IF_STATUS_UNKNOWN;
}
TraceLeave("InternalGetIfTable");
return NO_ERROR;
}
DWORD
InternalGetIpAddrTable(
OUT MIB_IPADDRTABLE **ppIpAddrTable,
IN HANDLE hHeap,
IN DWORD dwAllocFlags
)
{
PMIB_OPAQUE_INFO pInfo;
MIB_OPAQUE_QUERY mqQuery;
DWORD dwResult, dwOutEntrySize;
PMIB_IPADDRTABLE pTable;
TraceEnter("InternalGetIpAddrTable");
*ppIpAddrTable = NULL;
#ifndef CHICAGO
if(IsRouterRunning())
{
mqQuery.dwVarId = IP_ADDRTABLE;
dwResult = MprAdminMIBEntryGet(g_hMIBServer,
PID_IP,
IPRTRMGR_PID,
(PVOID)&mqQuery,
sizeof(MIB_OPAQUE_QUERY),
(PVOID)&pInfo,
&dwOutEntrySize);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"MprAdminMIBEntryGet failed with error %x",
dwResult);
TraceLeave("InternalGetIpAddrTable");
return dwResult;
}
*ppIpAddrTable = HeapAlloc(hHeap,
dwAllocFlags,
dwOutEntrySize);
if(*ppIpAddrTable is NULL)
{
dwResult = ERROR_NOT_ENOUGH_MEMORY;
Trace1(ERR,"Allocation failed with error %d",
dwResult);
TraceLeave("InternalGetIpAddrTable");
MprAdminMIBBufferFree((PVOID)pInfo);
return dwResult;
}
CAST_MIB_INFO(pInfo, PMIB_IPADDRTABLE, pTable);
CopyMemory((PVOID)(*ppIpAddrTable),
(PVOID)pTable,
SIZEOF_IPADDRTABLE(pTable->dwNumEntries));
MprAdminMIBBufferFree((PVOID)pInfo);
}
else
{
#endif
dwResult = AllocateAndGetIpAddrTableFromStack(ppIpAddrTable,
TRUE,
hHeap,
dwAllocFlags);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"InternalGetIpAddrTableFromStack failed with error %x",
dwResult);
TraceLeave("InternalGetIpAddrTable");
return dwResult;
}
#ifndef CHICAGO
}
#endif
TraceLeave("InternalGetIpAddrTable");
return NO_ERROR;
}
DWORD
InternalGetIpNetTable(
OUT MIB_IPNETTABLE **ppIpNetTable,
IN HANDLE hHeap,
IN DWORD dwAllocFlags
)
{
PMIB_OPAQUE_INFO pInfo;
MIB_OPAQUE_QUERY mqQuery;
DWORD dwResult, dwOutEntrySize;
PMIB_IPNETTABLE pTable;
TraceEnter("InternalGetIpNetTable");
*ppIpNetTable = NULL;
#ifndef CHICAGO
if(IsRouterRunning())
{
mqQuery.dwVarId = IP_NETTABLE;
dwResult = MprAdminMIBEntryGet(g_hMIBServer,
PID_IP,
IPRTRMGR_PID,
(PVOID)&mqQuery,
sizeof(MIB_OPAQUE_QUERY),
(PVOID)&pInfo,
&dwOutEntrySize);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"MprAdminMIBEntryGet failed with error %x",
dwResult);
TraceLeave("InternalGetIpNetTable");
return dwResult;
}
*ppIpNetTable = HeapAlloc(hHeap,
dwAllocFlags,
dwOutEntrySize);
if(*ppIpNetTable is NULL)
{
dwResult = ERROR_NOT_ENOUGH_MEMORY;
Trace1(ERR,"Allocation failed with error %d",
dwResult);
TraceLeave("InternalGetIpNetTable");
MprAdminMIBBufferFree((PVOID)pInfo);
return dwResult;
}
CAST_MIB_INFO(pInfo, PMIB_IPNETTABLE, pTable);
CopyMemory((PVOID)(*ppIpNetTable),
(PVOID)pTable,
SIZEOF_IPNETTABLE(pTable->dwNumEntries));
MprAdminMIBBufferFree((PVOID)pInfo);
}
else
{
#endif
dwResult = AllocateAndGetIpNetTableFromStack(ppIpNetTable,
TRUE,
hHeap,
dwAllocFlags,
FALSE);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"AllocateAndGetIpNetTableFromStack failed with error %x",
dwResult);
TraceLeave("InternalGetIpNetTable");
return dwResult;
}
#ifndef CHICAGO
}
#endif
TraceLeave("InternalGetIpNetTable");
return NO_ERROR;
}
DWORD
InternalGetIpForwardTable(
OUT MIB_IPFORWARDTABLE **ppIpForwardTable,
IN HANDLE hHeap,
IN DWORD dwAllocFlags
)
{
PMIB_OPAQUE_INFO pInfo;
MIB_OPAQUE_QUERY mqQuery;
DWORD dwResult, dwOutEntrySize;
PMIB_IPFORWARDTABLE pTable;
TraceEnter("InternalGetIpForwardTable");
*ppIpForwardTable = NULL;
#ifndef CHICAGO
if(IsRouterRunning() &&
IsRouterSettingRoutes())
{
mqQuery.dwVarId = IP_FORWARDTABLE;
dwResult = MprAdminMIBEntryGet(g_hMIBServer,
PID_IP,
IPRTRMGR_PID,
(PVOID)&mqQuery,
sizeof(MIB_OPAQUE_QUERY),
(PVOID)&pInfo,
&dwOutEntrySize);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"MprAdminMIBEntryGet failed with error %x",
dwResult);
TraceLeave("InternalGetIpForwardTable");
return dwResult;
}
*ppIpForwardTable = HeapAlloc(hHeap,
dwAllocFlags,
dwOutEntrySize);
if(*ppIpForwardTable is NULL)
{
dwResult = ERROR_NOT_ENOUGH_MEMORY;
Trace1(ERR,"Allocation failed with error %d",
dwResult);
TraceLeave("InternalGetIpForwardTable");
MprAdminMIBBufferFree((PVOID)pInfo);
return dwResult;
}
CAST_MIB_INFO(pInfo, PMIB_IPFORWARDTABLE, pTable);
CopyMemory((PVOID)(*ppIpForwardTable),
(PVOID)pTable,
SIZEOF_IPFORWARDTABLE(pTable->dwNumEntries));
MprAdminMIBBufferFree((PVOID)pInfo);
}
else
{
#endif
dwResult = AllocateAndGetIpForwardTableFromStack(ppIpForwardTable,
TRUE,
hHeap,
dwAllocFlags);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"InternalGetIpForwardTableFromStack failed with error %x",
dwResult);
TraceLeave("InternalGetIpForwardTable");
return dwResult;
}
#ifndef CHICAGO
}
#endif
TraceLeave("InternalGetIpForwardTable");
return NO_ERROR;
}
DWORD
InternalGetTcpTable(
OUT MIB_TCPTABLE **ppTcpTable,
IN HANDLE hHeap,
IN DWORD dwAllocFlags
)
{
PMIB_OPAQUE_INFO pInfo;
MIB_OPAQUE_QUERY mqQuery;
DWORD dwResult, dwOutEntrySize;
PMIB_TCPTABLE pTable;
TraceEnter("InternalGetTcpTable");
*ppTcpTable = NULL;
#ifndef CHICAGO
if(IsRouterRunning())
{
mqQuery.dwVarId = TCP_TABLE;
dwResult = MprAdminMIBEntryGet(g_hMIBServer,
PID_IP,
IPRTRMGR_PID,
(PVOID)&mqQuery,
sizeof(MIB_OPAQUE_QUERY),
(PVOID)&pInfo,
&dwOutEntrySize);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"MprAdminMIBEntryGet failed with error %x",
dwResult);
TraceLeave("InternalGetTcpTable");
return dwResult;
}
*ppTcpTable = HeapAlloc(hHeap,
dwAllocFlags,
dwOutEntrySize);
if(*ppTcpTable is NULL)
{
dwResult = ERROR_NOT_ENOUGH_MEMORY;
Trace1(ERR,"Allocation failed with error %d",
dwResult);
TraceLeave("InternalGetTcpTable");
MprAdminMIBBufferFree((PVOID)pInfo);
return dwResult;
}
CAST_MIB_INFO(pInfo, PMIB_TCPTABLE, pTable);
CopyMemory((PVOID)(*ppTcpTable),
(PVOID)pTable,
SIZEOF_TCPTABLE(pTable->dwNumEntries));
MprAdminMIBBufferFree((PVOID)pInfo);
}
else
{
#endif
dwResult = AllocateAndGetTcpTableFromStack(ppTcpTable,
TRUE,
hHeap,
dwAllocFlags);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"InternalGetTcpTableFromStack failed with error %x",
dwResult);
TraceLeave("InternalGetTcpTable");
return dwResult;
}
#ifndef CHICAGO
}
#endif
TraceLeave("InternalGetTcpTable");
return NO_ERROR;
}
DWORD
InternalGetUdpTable(
OUT MIB_UDPTABLE **ppUdpTable,
IN HANDLE hHeap,
IN DWORD dwAllocFlags
)
{
PMIB_OPAQUE_INFO pInfo;
MIB_OPAQUE_QUERY mqQuery;
DWORD dwResult, dwOutEntrySize;
PMIB_UDPTABLE pTable;
TraceEnter("InternalGetUdpTable");
*ppUdpTable = NULL;
#ifndef CHICAGO
if(IsRouterRunning())
{
mqQuery.dwVarId = UDP_TABLE;
dwResult = MprAdminMIBEntryGet(g_hMIBServer,
PID_IP,
IPRTRMGR_PID,
(PVOID)&mqQuery,
sizeof(MIB_OPAQUE_QUERY),
(PVOID)&pInfo,
&dwOutEntrySize);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"MprAdminMIBEntryGet failed with error %x",
dwResult);
TraceLeave("InternalGetUdpTable");
return dwResult;
}
*ppUdpTable = HeapAlloc(hHeap,
dwAllocFlags,
dwOutEntrySize);
if(*ppUdpTable is NULL)
{
dwResult = ERROR_NOT_ENOUGH_MEMORY;
Trace1(ERR,"Allocation failed with error %d",
dwResult);
MprAdminMIBBufferFree((PVOID)pInfo);
return dwResult;
}
CAST_MIB_INFO(pInfo, PMIB_UDPTABLE, pTable);
CopyMemory((PVOID)(*ppUdpTable),
(PVOID)pTable,
SIZEOF_UDPTABLE(pTable->dwNumEntries));
MprAdminMIBBufferFree((PVOID)pInfo);
}
else
{
#endif
dwResult = AllocateAndGetUdpTableFromStack(ppUdpTable,
TRUE,
hHeap,
dwAllocFlags);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"InternalGetUdpTableFromStack failed with error %x",
dwResult);
TraceLeave("InternalGetUdpTable");
return dwResult;
}
#ifndef CHICAGO
}
#endif
TraceLeave("InternalGetUdpTable");
return NO_ERROR;
}
DWORD
InternalSetIfEntry(
IN PMIB_OPAQUE_INFO pInfoRow
)
{
PMIB_IFROW pIfRow = (PMIB_IFROW)(pInfoRow->rgbyData);
DWORD dwResult;
TraceEnter("SetIfEntry");
#ifndef CHICAGO
if(IsRouterRunning())
{
pInfoRow->dwId = IF_ROW;
dwResult = MprAdminMIBEntrySet(g_hMIBServer,
PID_IP,
IPRTRMGR_PID,
(PVOID)pInfoRow,
MIB_INFO_SIZE(MIB_IFROW));
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"MprAdminMIBEntrySet failed with error %x",
dwResult);
TraceLeave("SetIfEntry");
return dwResult;
}
}
else
{
#endif
dwResult = SetIfEntryToStack(pIfRow,
FALSE);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"SetIfEntryToStack failed with error %d",
dwResult);
TraceLeave("SetIfEntry");
return dwResult;
}
#ifndef CHICAGO
}
#endif
TraceLeave("SetIfEntry");
return NO_ERROR;
}
DWORD
InternalCreateIpForwardEntry(
IN PMIB_OPAQUE_INFO pInfoRow
)
{
PMIB_IPFORWARDROW pIpForwardRow = (PMIB_IPFORWARDROW)(pInfoRow->rgbyData);
DWORD dwResult;
TraceEnter("CreateIpForwardEntry");
#ifndef CHICAGO
if(IsRouterRunning() &&
IsRouterSettingRoutes())
{
pInfoRow->dwId = IP_FORWARDROW;
dwResult = MprAdminMIBEntryCreate(g_hMIBServer,
PID_IP,
IPRTRMGR_PID,
(PVOID)pInfoRow,
MIB_INFO_SIZE(MIB_IPFORWARDROW));
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"MprAdminMIBEntryCreate failed with error %x",
dwResult);
TraceLeave("CreateIpForwardEntry");
return dwResult;
}
}
else
{
#endif
dwResult = SetIpForwardEntryToStack(pIpForwardRow);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"SetIpForwarEntryToStack failed with error %d",
dwResult);
TraceLeave("CreateIpForwardEntry");
return dwResult;
}
#ifndef CHICAGO
}
#endif
TraceLeave("CreateIpForwardEntry");
return NO_ERROR;
}
DWORD
InternalSetIpForwardEntry(
IN PMIB_OPAQUE_INFO pInfoRow
)
{
PMIB_IPFORWARDROW pIpForwardRow = (PMIB_IPFORWARDROW)(pInfoRow->rgbyData);
DWORD dwResult;
TraceEnter("SetIpForwardEntry");
#ifndef CHICAGO
if(IsRouterRunning() &&
IsRouterSettingRoutes())
{
pInfoRow->dwId = IP_FORWARDROW;
dwResult = MprAdminMIBEntrySet(g_hMIBServer,
PID_IP,
IPRTRMGR_PID,
(PVOID)pInfoRow,
MIB_INFO_SIZE(MIB_IPFORWARDROW));
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"MprAdminMIBEntrySet failed with error %x",
dwResult);
TraceLeave("SetIpForwardEntry");
return dwResult;
}
}
else
{
#endif
dwResult = SetIpForwardEntryToStack(pIpForwardRow);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"SetIpForwarEntryToStack failed with error %d",
dwResult);
TraceLeave("SetIpForwardEntry");
return dwResult;
}
#ifndef CHICAGO
}
#endif
TraceLeave("SetIpForwardEntry");
return NO_ERROR;
}
DWORD
InternalDeleteIpForwardEntry(
IN PMIB_OPAQUE_INFO pInfoRow
)
{
PMIB_IPFORWARDROW pIpForwardRow = (PMIB_IPFORWARDROW)(pInfoRow->rgbyData);
DWORD dwResult;
TraceEnter("DeleteIpForwardEntry");
pIpForwardRow->dwForwardType = MIB_IPROUTE_TYPE_INVALID;
#ifndef CHICAGO
if(IsRouterRunning() &&
IsRouterSettingRoutes())
{
DWORD rgdwInfo[5];
PMIB_OPAQUE_QUERY pIndex = (PMIB_OPAQUE_QUERY)rgdwInfo;
pIndex->dwVarId = IP_FORWARDROW;
pIndex->rgdwVarIndex[0] = pIpForwardRow->dwForwardDest;
pIndex->rgdwVarIndex[1] = pIpForwardRow->dwForwardProto;
pIndex->rgdwVarIndex[2] = pIpForwardRow->dwForwardPolicy;
pIndex->rgdwVarIndex[3] = pIpForwardRow->dwForwardNextHop;
dwResult = MprAdminMIBEntryDelete(g_hMIBServer,
PID_IP,
IPRTRMGR_PID,
(PVOID)pIndex,
sizeof(rgdwInfo));
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"MprAdminMIBEntryDelete failed with error %x",
dwResult);
TraceLeave("DeleteIpForwardEntry");
return dwResult;
}
}
else
{
#endif
dwResult = SetIpForwardEntryToStack(pIpForwardRow);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"SetIpForwarEntryToStack failed with error %d",
dwResult);
TraceLeave("CreateIpForwardEntry");
return dwResult;
}
#ifndef CHICAGO
}
#endif
TraceLeave("CreateIpForwardEntry");
return NO_ERROR;
}
DWORD
InternalSetIpStats(
IN PMIB_OPAQUE_INFO pInfoRow
)
{
PMIB_IPSTATS pIpStats = (PMIB_IPSTATS)(pInfoRow->rgbyData);
DWORD dwResult;
TraceEnter("SetIpStats");
#ifndef CHICAGO
if(IsRouterRunning())
{
pInfoRow->dwId = IP_STATS;
dwResult = MprAdminMIBEntrySet(g_hMIBServer,
PID_IP,
IPRTRMGR_PID,
(PVOID)pInfoRow,
MIB_INFO_SIZE(MIB_IPSTATS));
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"MprAdminMIBEntrySet failed with error %x",
dwResult);
TraceLeave("SetIpStats");
return dwResult;
}
}
else
{
#endif
dwResult = SetIpStatsToStack(pIpStats);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"SetIpStatsToStack failed with error %d",
dwResult);
TraceLeave("SetIpStats");
return dwResult;
}
#ifndef CHICAGO
}
#endif
TraceLeave("SetIpStats");
return NO_ERROR;
}
DWORD
InternalCreateIpNetEntry(
IN PMIB_OPAQUE_INFO pInfoRow
)
{
PMIB_IPNETROW pIpNetRow = (PMIB_IPNETROW)(pInfoRow->rgbyData);
DWORD dwResult;
TraceEnter("CreateIpNetEntry");
#ifndef CHICAGO
if(IsRouterRunning())
{
pInfoRow->dwId = IP_NETROW;
dwResult = MprAdminMIBEntryCreate(g_hMIBServer,
PID_IP,
IPRTRMGR_PID,
(PVOID)pInfoRow,
MIB_INFO_SIZE(MIB_IPNETROW));
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"MprAdminMIBEntryCreate failed with error %x",
dwResult);
TraceLeave("CreateIpNetEntry");
return dwResult;
}
}
else
{
#endif
dwResult = SetIpNetEntryToStack(pIpNetRow,
FALSE);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"SetIpNetEntryToStack failed with error %d",
dwResult);
TraceLeave("CreateIpNetEntry");
return dwResult;
}
#ifndef CHICAGO
}
#endif
TraceLeave("CreateIpNetEntry");
return NO_ERROR;
}
DWORD
InternalSetIpNetEntry(
PMIB_OPAQUE_INFO pInfoRow
)
{
PMIB_IPNETROW pIpNetRow = (PMIB_IPNETROW)(pInfoRow->rgbyData);
DWORD dwResult;
TraceEnter("SetIpNetEntry");
#ifndef CHICAGO
if(IsRouterRunning())
{
pInfoRow->dwId = IP_NETROW;
dwResult = MprAdminMIBEntrySet(g_hMIBServer,
PID_IP,
IPRTRMGR_PID,
(PVOID)pInfoRow,
MIB_INFO_SIZE(MIB_IPNETROW));
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"MprAdminMIBEntrySet failed with error %x",
dwResult);
TraceLeave("SetIpNetEntry");
return dwResult;
}
}
else
{
#endif
dwResult = SetIpNetEntryToStack(pIpNetRow,
FALSE);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"SetIpNetEntryToStack failed with error %d",
dwResult);
TraceLeave("SetIpNetEntry");
return dwResult;
}
#ifndef CHICAGO
}
#endif
TraceLeave("SetIpNetEntry");
return NO_ERROR;
}
DWORD
InternalDeleteIpNetEntry(
PMIB_OPAQUE_INFO pInfoRow
)
{
PMIB_IPNETROW pIpNetRow = (PMIB_IPNETROW)(pInfoRow->rgbyData);
DWORD dwResult;
TraceEnter("DeleteIpNetEntry");
pIpNetRow->dwType = MIB_IPNET_TYPE_INVALID;
#ifndef CHICAGO
if(IsRouterRunning())
{
DWORD rgdwInfo[3];
PMIB_OPAQUE_QUERY pIndex = (PMIB_OPAQUE_QUERY)rgdwInfo;
pIndex->dwVarId = IP_NETROW;
pIndex->rgdwVarIndex[0] = pIpNetRow->dwIndex;
pIndex->rgdwVarIndex[1] = pIpNetRow->dwAddr;
dwResult = MprAdminMIBEntryDelete(g_hMIBServer,
PID_IP,
IPRTRMGR_PID,
(PVOID)pIndex,
sizeof(rgdwInfo));
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"MprAdminMIBEntryDelete failed with error %x",
dwResult);
TraceLeave("DeleteIpNetEntry");
return dwResult;
}
}
else
{
#endif
dwResult = SetIpNetEntryToStack(pIpNetRow,
FALSE);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"SetIpNetEntryToStack failed with error %d",
dwResult);
TraceLeave("DeleteIpNetEntry");
return dwResult;
}
#ifndef CHICAGO
}
#endif
TraceLeave("DeleteIpNetEntry");
return NO_ERROR;
}
DWORD
InternalSetTcpEntry(
PMIB_OPAQUE_INFO pInfoRow
)
{
PMIB_TCPROW pTcpRow = (PMIB_TCPROW)(pInfoRow->rgbyData);
DWORD dwResult;
TraceEnter("SetTcpEntry");
#ifndef CHICAGO
if(IsRouterRunning())
{
pInfoRow->dwId = TCP_ROW;
dwResult = MprAdminMIBEntrySet(g_hMIBServer,
PID_IP,
IPRTRMGR_PID,
(PVOID)pInfoRow,
MIB_INFO_SIZE(MIB_TCPROW));
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"MprAdminMIBEntrySet failed with error %x",
dwResult);
TraceLeave("SetTcpEntry");
return dwResult;
}
}
else
{
#endif
dwResult = SetTcpEntryToStack(pTcpRow);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"SetTcpEntryToStack failed with error %d",
dwResult);
TraceLeave("SetTcpEntry");
return dwResult;
}
#ifndef CHICAGO
}
#endif
TraceLeave("SetTcpEntry");
return NO_ERROR;
}
//#define MAX_ADAPTER_NAME_LENGTH 256
DWORD
OpenAdapterKey(
LPSTR Name,
PHKEY Key
)
{
DWORD dwResult;
CHAR keyName[MAX_ADAPTER_NAME_LENGTH +
sizeof("\\Parameters\\Tcpip") +
sizeof("SYSTEM\\CurrentControlSet\\Services\\")];
//
// open the handle to this adapter's TCPIP parameter key
//
strcpy(keyName, "SYSTEM\\CurrentControlSet\\Services\\");
strcat(keyName, Name);
strcat(keyName, "\\Parameters\\Tcpip");
Trace1(ERR,"OpenAdapterKey: %s", keyName);
dwResult = RegOpenKey(HKEY_LOCAL_MACHINE,
keyName,
Key);
return dwResult;
}
DWORD
ReadRegistryDword(HKEY Key, LPSTR ParameterName, PULONG Value)
{
DWORD dwResult, valueLength, valueType;
valueLength = sizeof(*Value);
dwResult = RegQueryValueEx(Key,
ParameterName,
NULL, // reserved
&valueType,
(LPBYTE)Value,
&valueLength);
return dwResult;
}
DWORD
GetAdapterIPInterfaceContext(LPSTR AdapterName, PULONG Context)
{
HKEY key;
DWORD dwResult;
if ((dwResult = OpenAdapterKey(AdapterName, &key)) != NO_ERROR) {
return(dwResult);
}
if ((dwResult = ReadRegistryDword(key, "IPInterfaceContext", Context))
!= NO_ERROR) {
return(dwResult);
}
RegCloseKey(key);
return(NO_ERROR);
}
DWORD
GetInterfaceInfo(PIP_INTERFACE_INFO pIPIfInfo, PULONG dwOutBufLen)
{
#if defined(NT4) || defined(_WIN95_)
return ERROR_NOT_SUPPORTED;
#else
DWORD status=0;
DWORD dwNumIf, NumAdapters;
int i;
DWORD dwResult;
MIB_IPSTATS IpSnmpInfo;
if (IsBadWritePtr(dwOutBufLen, sizeof(ULONG))) {
return ERROR_INVALID_PARAMETER;
}
if (IsBadWritePtr(pIPIfInfo, *dwOutBufLen)) {
return ERROR_INVALID_PARAMETER;
}
dwResult = GetIpStatsFromStack(&IpSnmpInfo);
if(dwResult isnot NO_ERROR) {
Trace1(ERR,"GetInterfaceInfo: GetIpStatsFromStack returned error %d",
dwResult);
return dwResult;
}
dwNumIf = IpSnmpInfo.dwNumIf;
if(dwNumIf is 0) {
Trace0(ERR,"GetInterfaceInfo: No interfaces");
return ERROR_NO_DATA;
}
if (dwOutBufLen == NULL) {
return ERROR_INVALID_PARAMETER;
}
if (!pIPIfInfo ||
(*dwOutBufLen <
(ULONG)sizeof(IP_ADAPTER_INDEX_MAP)*(dwNumIf + OVERFLOW_COUNT))) {
*dwOutBufLen =
(ULONG)sizeof(IP_ADAPTER_INDEX_MAP)*(dwNumIf + OVERFLOW_COUNT);
return ERROR_INSUFFICIENT_BUFFER;
}
Trace1(ERR, "GetInterfaceInfo: outbuflen %d", *dwOutBufLen);
return TCPSendIoctl(g_hIPGetDriverHandle,
IOCTL_IP_INTERFACE_INFO,
NULL,
&status,
pIPIfInfo,
dwOutBufLen);
#endif
}
DWORD
GetUniDirectionalAdapterInfo(PIP_UNIDIRECTIONAL_ADAPTER_ADDRESS pIPIfInfo,
PULONG dwOutBufLen)
{
DWORD status=0;
if (dwOutBufLen == NULL) {
return ERROR_INVALID_PARAMETER;
}
return TCPSendIoctl(g_hIPGetDriverHandle,
IOCTL_IP_UNIDIRECTIONAL_ADAPTER_ADDRESS,
NULL,
&status,
pIPIfInfo,
dwOutBufLen);
}
DWORD
GetIgmpList(IPAddr NTEAddr, IPAddr *pIgmpList, PULONG pdwOutBufLen)
/*++
Routine Description:
When pIgmpList is NULL, get the amount of space necessary to hold
the group addresses joined on a given interface address.
When pIgmpList is non-NULL and *pdwOutBufLen is more than 4 bytes,
get the actual group addresses.
Arguments:
NTEAddr - Supplies the address of an interface whose multicast
group information is being requested.
pIgmpList - Supplies a buffer in which to put group addresses, or
NULL to just request amount of space desired.
pdwOutBufLen - When pIgmpList is NULL, returns the amount of space
the caller should allocate to get all groups.
When pIgmpList is non-NULL, supplies the size of
the buffer supplied, and returns the amount of
space actually used.
Return Value:
NO_ERROR
ERROR_INVALID_PARAMETER if the arguments don't meet the requirements.
ERROR_INSUFFICIENT_BUFFER if more groups are available than fit.
--*/
{
DWORD inlen = sizeof(IPAddr);
DWORD dwStatus;
if (pdwOutBufLen == NULL) {
return ERROR_INVALID_PARAMETER;
}
if (IsBadWritePtr(pdwOutBufLen, sizeof(ULONG))) {
return ERROR_INVALID_PARAMETER;
}
if (pIgmpList == NULL) {
DWORD dwSize;
//
// When pIgmpList is NULL, the caller is just asking for the
// amount of space needed, so use pdwOutBufLen as the buffer.
//
dwSize = sizeof(*pdwOutBufLen);
dwStatus = TCPSendIoctl(g_hIPGetDriverHandle,
IOCTL_IP_GET_IGMPLIST,
&NTEAddr,
&inlen,
pdwOutBufLen,
&dwSize);
} else {
//
// Otherwise the caller wants the list of groups.
//
if (IsBadWritePtr(pIgmpList, *pdwOutBufLen)) {
return ERROR_INVALID_PARAMETER;
}
if (*pdwOutBufLen <= sizeof(ULONG)) {
//
// Make sure the buffer is bigger than a ULONG or we'll get
// the size back, not group data. The IOCTL insures that
// when the caller requests the size needed, the amount
// returned will be bigger than a ULONG.
//
return ERROR_INVALID_PARAMETER;
}
dwStatus = TCPSendIoctl(g_hIPGetDriverHandle,
IOCTL_IP_GET_IGMPLIST,
&NTEAddr,
&inlen,
pIgmpList,
pdwOutBufLen);
}
if (dwStatus == ERROR_MORE_DATA) {
//
// Callers expect ERROR_INSUFFICIENT_BUFFER when *pdwOutBufLen is
// too small. However, the stack actually generates a warning
// (ERROR_MORE_DATA), rather than an error (ERROR_INSUFFICIENT_BUFFER)
// so that the data gets passed back to the caller.
//
dwStatus = ERROR_INSUFFICIENT_BUFFER;
}
return dwStatus;
}
DWORD
SetBlockRoutes(IPRouteBlock *RouteBlock, PULONG poutbuflen, PULONG statusblock)
{
DWORD inlen;
if (IsRouterRunning()) {
return ERROR_NOT_SUPPORTED;
}
if (poutbuflen == NULL) {
// Null pointers ?
return ERROR_INVALID_PARAMETER;
}
if (IsBadReadPtr(poutbuflen, sizeof(ULONG))) {
return ERROR_INVALID_PARAMETER;
}
if (IsBadReadPtr(RouteBlock, sizeof(IPRouteBlock))) {
return ERROR_INVALID_PARAMETER;
}
inlen = (RouteBlock->numofroutes * sizeof(IPRouteEntry)) + sizeof(ulong);
if (IsBadReadPtr(RouteBlock, inlen)) {
return ERROR_INVALID_PARAMETER;
}
return TCPSendIoctl(g_hIPDriverHandle,
IOCTL_IP_SET_BLOCKOFROUTES,
RouteBlock,
&inlen,
statusblock,
poutbuflen);
}
DWORD
SetRouteWithRef(IN IPRouteEntry *RouteEntry
)
{
DWORD inlen = sizeof(IPRouteEntry);
ULONG outbuflen;
if (IsRouterRunning()) {
return ERROR_NOT_SUPPORTED;
}
if (IsBadReadPtr(RouteEntry, inlen)) {
return ERROR_INVALID_PARAMETER;
}
return TCPSendIoctl(g_hIPDriverHandle,
IOCTL_IP_SET_ROUTEWITHREF,
RouteEntry,
&inlen,
NULL,
&outbuflen);
}
DWORD
GetAdapterIndex(
IN LPWSTR AdapterName,
OUT PULONG IfIndex
)
/*++
Routine Description:
Gets the target IP interface given the name of the adapter associated with it.
Arguments:
AdapterName - A unicode string identifying the adapter/interface to which
to add the new NTE.
ifIndex - Interface index associated with the adapter name.
Return Value:
ERROR_SUCCESS or windows error
--*/
{
#ifdef CHICAGO
return ERROR_NOT_SUPPORTED;
#else
int i;
DWORD dwResult;
MIB_IPADDRTABLE *pIpAddrTable;
MIB_IPADDRROW *pIpAddrEntry;
ULONG Context;
int NumEntries;
IP_INTERFACE_INFO *pIPIfInfo=NULL;
DWORD dwNumIf, NumAdapters;
ULONG dwOutBufLen;
if (AdapterName == NULL || IfIndex == NULL)
{
return(ERROR_INVALID_PARAMETER);
}
dwResult = GetNumberOfInterfaces(&dwNumIf);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"GetAdapterIndex: GetNumberOfInterfaces returned error %d",
dwResult);
return dwResult;
}
if(dwNumIf is 0)
{
Trace0(ERR,"GetAdapterIndex: No interfaces");
return ERROR_NO_DATA;
}
dwOutBufLen = (ULONG)sizeof(IP_ADAPTER_INDEX_MAP)*(dwNumIf + OVERFLOW_COUNT);
pIPIfInfo = HeapAlloc(g_hPrivateHeap, FALSE, dwOutBufLen);
if(pIPIfInfo is NULL)
{
dwResult = ERROR_NOT_ENOUGH_MEMORY;
Trace1(ERR,
"GetAdapterIndex: Couldnt allocate memory. Error %d",
dwResult);
return dwResult;
}
dwResult = GetInterfaceInfo(pIPIfInfo, &dwOutBufLen);
if (dwResult isnot NO_ERROR)
{
Trace1(ERR,
"GetAdapterIndex: Error %d calling GetInterfaceInfo",
dwResult);
HeapFree(g_hPrivateHeap, 0, pIPIfInfo);
return dwResult;
}
// search for the adaptername within this info and return the index.
NumAdapters = pIPIfInfo->NumAdapters;
for (i = 0; i < (int)pIPIfInfo->NumAdapters; i++) {
if (lstrcmpiW(AdapterName, pIPIfInfo->Adapter[i].Name) == 0)
{
break;
}
}
if (i < (int)pIPIfInfo->NumAdapters)
{
*IfIndex = pIPIfInfo->Adapter[i].Index;
HeapFree(g_hPrivateHeap, 0, pIPIfInfo);
return(NO_ERROR);
}
HeapFree(g_hPrivateHeap, 0, pIPIfInfo);
return(ERROR_DEV_NOT_EXIST);
#endif
}
DWORD
AddIPAddress(IPAddr Address, IPMask IpMask, DWORD IfIndex, PULONG NTEContext,
PULONG NTEInstance)
{
#ifdef CHICAGO
return ERROR_NOT_SUPPORTED;
#else
IP_ADD_NTE_REQUEST requestBuffer;
PIP_ADD_NTE_RESPONSE responseBuffer =
(PIP_ADD_NTE_RESPONSE) &requestBuffer;
DWORD requestBufferSize = sizeof(requestBuffer);
DWORD responseBufferSize = sizeof(requestBuffer);
DWORD status;
//
// Validate the IP address to be added. Check for
// * broadcast address,
// * loopback address,
// * zero address,
// * Class D address,
// * zero subnet-broadcast address
// * all-ones subnet-broadcast address
// * non-contiguous mask (which we test by negating the host-order mask
// and verifying that all the bits change when we add 1, i.e. that
// the negation is of the form 2^n-1).
//
if ((Address == INADDR_BROADCAST) ||
((ntohl(Address) & IN_CLASSA_NET) ==
(INADDR_LOOPBACK & IN_CLASSA_NET)) ||
(Address == 0) ||
(IN_CLASSD(ntohl(Address))) ||
((Address & ~IpMask) == 0) ||
((Address & ~IpMask) == ~IpMask) ||
((~ntohl(IpMask) + 1) & ~ntohl(IpMask))) {
return ERROR_INVALID_PARAMETER;
}
if ( (NTEContext == NULL) || (NTEInstance == NULL) ) {
return ERROR_INVALID_PARAMETER;
}
if (IsBadWritePtr(NTEContext, sizeof(ULONG))) {
return ERROR_INVALID_PARAMETER;
}
if (IsBadWritePtr(NTEInstance, sizeof(ULONG))) {
return ERROR_INVALID_PARAMETER;
}
requestBuffer.InterfaceContext = (unsigned long) IfIndex;
requestBuffer.Address = Address;
requestBuffer.SubnetMask = IpMask;
status = TCPSendIoctl(g_hIPDriverHandle,
IOCTL_IP_ADD_NTE,
&requestBuffer,
&requestBufferSize,
responseBuffer,
&responseBufferSize);
if (status == NO_ERROR) {
*NTEContext = (ULONG) responseBuffer->Context;
*NTEInstance = responseBuffer->Instance;
} else if (status == STATUS_DUPLICATE_OBJECTID) {
status = ERROR_DUP_DOMAINNAME;
}
return(status);
#endif
}
DWORD
DeleteIPAddress(ULONG NTEContext)
{
#ifdef CHICAGO
return ERROR_NOT_SUPPORTED;
#else
IP_DELETE_NTE_REQUEST requestBuffer;
DWORD requestBufferSize = sizeof(requestBuffer);
DWORD responseBufferSize = 0;
DWORD status;
requestBuffer.Context = (unsigned short) NTEContext;
status = TCPSendIoctl(g_hIPDriverHandle,
IOCTL_IP_DELETE_NTE,
&requestBuffer,
&requestBufferSize,
NULL,
&responseBufferSize);
return(status);
#endif
}
#define DEFAULT_TTL 32
#define DEFAULT_TOS 0
#define DEFAULT_TIMEOUT 5000L
#include <icmpapi.h>
#ifndef CHICAGO
#include <ntddip.h>
#endif
BOOL
GetRTT(IPAddr DestIpAddress, PULONG Rtt)
{
uchar FAR *Opt = (uchar FAR *)0; // Pointer to send options
uint OptLength = 0;
int OptIndex = 0; // Current index into SendOptions
uchar Flags = 0;
ulong Timeout = DEFAULT_TIMEOUT;
IP_OPTION_INFORMATION SendOpts;
HANDLE IcmpHandle;
PICMP_ECHO_REPLY reply;
char SendBuffer[32], RcvBuffer[4096];
uint RcvSize=4096;
uint SendSize = 32;
uint i;
DWORD numberOfReplies;
IcmpHandle = IcmpCreateFile();
if (IcmpHandle == INVALID_HANDLE_VALUE) {
return(FALSE);
}
if (IsBadWritePtr(Rtt, sizeof(ULONG))) {
return ERROR_INVALID_PARAMETER;
}
//
// Initialize the send buffer pattern.
//
for (i = 0; i < SendSize; i++) {
SendBuffer[i] = (char) ('a' + (i % 23));
}
//
// Initialize the send options
//
SendOpts.OptionsData = Opt;
SendOpts.OptionsSize = (UCHAR) OptLength;
SendOpts.Ttl = DEFAULT_TTL;
SendOpts.Tos = DEFAULT_TOS;
SendOpts.Flags = Flags;
numberOfReplies = IcmpSendEcho(IcmpHandle,
DestIpAddress,
SendBuffer,
(unsigned short) SendSize,
&SendOpts,
RcvBuffer,
RcvSize,
DEFAULT_TIMEOUT);
if (numberOfReplies) {
numberOfReplies = IcmpSendEcho(IcmpHandle,
DestIpAddress,
SendBuffer,
(unsigned short) SendSize,
&SendOpts,
RcvBuffer,
RcvSize,
Timeout);
if (numberOfReplies) {
reply = (PICMP_ECHO_REPLY) RcvBuffer;
*Rtt = reply->RoundTripTime;
IcmpCloseHandle(IcmpHandle);
return(TRUE);
}
}
IcmpCloseHandle(IcmpHandle);
return(FALSE);
}
BOOL
GetRTTAndHopCount(IPAddr DestIpAddress, PULONG HopCount, ULONG MaxHops,
PULONG RTT)
{
DWORD numberOfReplies;
uchar FAR *Opt = (uchar FAR *)0; // Pointer to send options
uint OptLength = 0;
int OptIndex = 0; // Current index into SendOptions
uchar Flags = 0;
ulong Timeout = DEFAULT_TIMEOUT;
IP_OPTION_INFORMATION SendOpts;
HANDLE IcmpHandle;
PICMP_ECHO_REPLY reply;
char SendBuffer[32], RcvBuffer[4096];
uint RcvSize=4096;
uint SendSize = 32;
uint i,status;
ULONG RTT1;
IcmpHandle = IcmpCreateFile();
if (IcmpHandle == INVALID_HANDLE_VALUE) {
return(FALSE);
}
if (!HopCount || !RTT) {
return (FALSE);
}
if (DestIpAddress == -1L) {
return(FALSE);
}
if (IsBadWritePtr(RTT, sizeof(ULONG))) {
return (FALSE);
}
if (IsBadWritePtr(HopCount, sizeof(ULONG))) {
return (FALSE);
}
//
// Initialize the send buffer pattern.
//
for (i = 0; i < SendSize; i++) {
SendBuffer[i] = (char) ('a' + (i % 23));
}
//
// Initialize the send options
//
SendOpts.OptionsData = Opt;
SendOpts.OptionsSize = (UCHAR) OptLength;
SendOpts.Ttl = 1;
SendOpts.Tos = DEFAULT_TOS;
SendOpts.Flags = Flags;
while (SendOpts.Ttl <= MaxHops) {
numberOfReplies = IcmpSendEcho(IcmpHandle,
DestIpAddress,
SendBuffer,
(unsigned short) SendSize,
&SendOpts,
RcvBuffer,
RcvSize,
Timeout);
if (numberOfReplies == 0) {
status = GetLastError();
reply = NULL;
} else {
reply = (PICMP_ECHO_REPLY)RcvBuffer;
status = reply->Status;
}
if (status == IP_SUCCESS) {
*HopCount = SendOpts.Ttl;
IcmpCloseHandle(IcmpHandle);
if (GetRTT(DestIpAddress, &RTT1)) {
*RTT = RTT1;
return TRUE;
} else {
return FALSE;
}
} else if (status == IP_TTL_EXPIRED_TRANSIT) {
SendOpts.Ttl++;
} else {
IcmpCloseHandle(IcmpHandle);
return FALSE;
}
}
IcmpCloseHandle(IcmpHandle);
return FALSE;
}
#define LOOPBACK_ADDR 0x0100007f
DWORD
IsLocalAddress(IPAddr InAddress)
{
int i;
DWORD dwResult;
int NumEntries;
PMIB_IPADDRTABLE pIpAddrTable;
PMIB_IPADDRROW pIpAddrEntry;
dwResult = AllocateAndGetIpAddrTableFromStack(&pIpAddrTable,
FALSE,
g_hPrivateHeap,
0);
if(dwResult isnot NO_ERROR) {
Trace1(ERR,"GetIpAddrTableFromStack failed with error %x",dwResult);
TraceLeave("IsLocalAddress");
return dwResult;
}
if (InAddress == LOOPBACK_ADDR) {
HeapFree(g_hPrivateHeap, 0, pIpAddrTable);
return(NO_ERROR);
}
NumEntries = (*pIpAddrTable).dwNumEntries;
Trace2(ERR,"IsLocalAddress number of addresses %d chking %x",
NumEntries,InAddress);
for (i = 0; i < NumEntries; i++) {
pIpAddrEntry = &(*pIpAddrTable).table[i];
Trace1(ERR,"IsLocalAddress cmparing %x",pIpAddrEntry->dwAddr);
if (pIpAddrEntry->dwAddr == (DWORD)InAddress) {
HeapFree(g_hPrivateHeap, 0, pIpAddrTable);
return(NO_ERROR);
}
}
HeapFree(g_hPrivateHeap, 0, pIpAddrTable);
return(ERROR_INVALID_ADDRESS);
}
DWORD
GetArpTable(PMIB_IPNETTABLE pIpNetTable, PDWORD pdwSize)
{
return(GetIpNetTable(pIpNetTable,pdwSize,TRUE));
}
DWORD
AddArpEntry(IPAddr IPAddress, PUCHAR pPhyAddress, ULONG PhyAddrLen,
ULONG IfIndex, BOOLEAN Dynamic)
{
MIB_IPNETROW NetRow;
uint i;
DWORD dwResult;
NetRow.dwIndex = IfIndex;
NetRow.dwPhysAddrLen = PhyAddrLen;
if (pPhyAddress == NULL) {
return(ERROR_INVALID_PARAMETER);
}
if (PhyAddrLen > MAXLEN_PHYSADDR) {
return(ERROR_INVALID_PARAMETER);
}
// Check for bcast, loopback and class D address
if ((IPAddress == 0xffffffff) ||
(ntohl(IPAddress) == 0x7f000001) ||
((ntohl(IPAddress) >= 0xe0000000) &&
(ntohl(IPAddress) <= 0xefffffff))) {
return ERROR_INVALID_PARAMETER;
}
for (i=0; i < PhyAddrLen; i++) {
NetRow.bPhysAddr[i] = pPhyAddress[i];
}
NetRow.dwAddr = IPAddress;
NetRow.dwType = MIB_IPNET_TYPE_DYNAMIC;
if (!Dynamic) {
NetRow.dwType = MIB_IPNET_TYPE_STATIC;
}
dwResult = SetIpNetEntryToStack(&NetRow, FALSE);
if (dwResult == STATUS_INVALID_PARAMETER) {
return(ERROR_INVALID_PARAMETER);
} else if (dwResult == STATUS_INVALID_DEVICE_REQUEST) {
return(ERROR_INVALID_PARAMETER);
}
if (dwResult == STATUS_SUCCESS) {
return(NO_ERROR);
} else {
return(dwResult);
}
}
DWORD
DeleteArpEntry(IPAddr IPAddress, ULONG IfIndex)
{
MIB_IPNETROW NetRow;
DWORD dwResult;
NetRow.dwIndex = IfIndex;
NetRow.dwAddr = IPAddress;
NetRow.dwType = MIB_IPNET_TYPE_INVALID;
dwResult = SetIpNetEntryToStack(&NetRow, FALSE);
if (dwResult == STATUS_INVALID_PARAMETER) {
return(ERROR_INVALID_PARAMETER);
}
return(dwResult);
}
DWORD
NotifyAddrChange(HANDLE *pHandle, OVERLAPPED *pOverLapped)
{
#if defined(NT4) || defined(CHICAGO)
return ERROR_NOT_SUPPORTED;
#else
BOOL b;
DWORD dwResult;
DWORD temp;
if ((pHandle != NULL) && (pOverLapped != NULL)) {
Trace0(ERR, "NotifyAddressChange: overlapped request");
if (IsBadWritePtr(pHandle, sizeof(HANDLE))) {
return ERROR_INVALID_PARAMETER;
}
if (IsBadWritePtr(pOverLapped, sizeof(OVERLAPPED))) {
return ERROR_INVALID_PARAMETER;
}
*pHandle = ChangeNotificationHandle;
if (*pHandle == INVALID_HANDLE_VALUE){
Trace1(ERR, "NotifyAddressChange: CreateFile=%d", GetLastError());
return ERROR_OPEN_FAILED;
}
b = DeviceIoControl(*pHandle,
IOCTL_IP_ADDCHANGE_NOTIFY_REQUEST,
NULL,
0,
NULL,
0,
&temp,
pOverLapped);
if (!b) {
dwResult = GetLastError();
Trace1(ERR, "NotifyAddrChange: DeviceIoControl=%d", dwResult);
return dwResult;
}
} else {
// Synchronous change notification
// This call will block
Trace0(ERR, "NotifyAddrChange: synchronous request");
b = DeviceIoControl(g_hIPGetDriverHandle,
IOCTL_IP_ADDCHANGE_NOTIFY_REQUEST,
NULL,
0,
NULL,
0,
&temp,
NULL);
if (!b) {
dwResult = GetLastError();
Trace1(ERR, "NotifyAddressChange: DeviceIoControl=%d", dwResult);
return dwResult;
}
}
return NO_ERROR;
#endif
}
DWORD
NotifyRouteChange(HANDLE *pHandle, OVERLAPPED *pOverLapped)
{
return NotifyRouteChangeEx(pHandle, pOverLapped, FALSE);
}
DWORD
NotifyRouteChangeEx(
PHANDLE pHandle,
LPOVERLAPPED pOverLapped,
BOOL bExQueue
)
{
#if defined(NT4) || defined(CHICAGO)
return ERROR_NOT_SUPPORTED;
#else
BOOL b;
DWORD dwResult;
DWORD temp;
DWORD dwIoctl;
if(bExQueue) {
dwIoctl = IOCTL_IP_RTCHANGE_NOTIFY_REQUEST_EX;
} else {
dwIoctl = IOCTL_IP_RTCHANGE_NOTIFY_REQUEST;
}
if ((pHandle != NULL) && (pOverLapped != NULL)) {
Trace0(ERR, "NotifyRouteChange: overlapped request");
if (IsBadWritePtr(pHandle, sizeof(HANDLE))) {
return ERROR_INVALID_PARAMETER;
}
if (IsBadWritePtr(pOverLapped, sizeof(OVERLAPPED))) {
return ERROR_INVALID_PARAMETER;
}
*pHandle = ChangeNotificationHandle;
if(*pHandle == INVALID_HANDLE_VALUE){
Trace1(ERR, "NotifyRouteChange: CreateFile=%d", GetLastError());
return ERROR_OPEN_FAILED;
}
b = DeviceIoControl(*pHandle,
dwIoctl,
NULL,
0,
NULL,
0,
&temp,
pOverLapped);
if (!b) {
dwResult = GetLastError();
Trace1(ERR, "NotifyRouteChange: DeviceIoControl=%d", dwResult);
return dwResult;
}
} else {
// Synchronous change notification
// This call will block
Trace0(ERR, "NotifyRouteChange: synchronous request");
b = DeviceIoControl(g_hIPGetDriverHandle,
dwIoctl,
NULL,
0,
NULL,
0,
&temp,
NULL);
if (!b) {
dwResult = GetLastError();
Trace1(ERR, "NotifyRouteChange: DeviceIoControl=%d", dwResult);
return dwResult;
}
}
return NO_ERROR;
#endif
}
DWORD WINAPI
EnableRouter(HANDLE *pHandle, OVERLAPPED *pOverLapped)
{
#if defined(NT4) || defined(CHICAGO)
return ERROR_NOT_SUPPORTED;
#else
BOOL b;
DWORD dwResult;
DWORD temp;
if ((pHandle != NULL) && (pOverLapped != NULL)) {
Trace0(ERR,"EnableRouter: overlapped request");
if (IsBadWritePtr(pHandle, sizeof(HANDLE)) ||
IsBadWritePtr(pOverLapped, sizeof(OVERLAPPED))) {
return ERROR_INVALID_PARAMETER;
}
*pHandle = g_hIPDriverHandle;
if (*pHandle == INVALID_HANDLE_VALUE) {
return ERROR_OPEN_FAILED;
}
b = DeviceIoControl(
*pHandle,
IOCTL_IP_ENABLE_ROUTER_REQUEST,
NULL,
0,
NULL,
0,
&temp,
pOverLapped
);
if (!b) { return GetLastError(); }
} else {
Trace0(ERR,"EnableRouter: synchronous request");
b = DeviceIoControl(
g_hIPDriverHandle,
IOCTL_IP_ENABLE_ROUTER_REQUEST,
NULL,
0,
NULL,
0,
&temp,
NULL
);
if (!b) {
dwResult = GetLastError();
Trace1(ERR,"EnableRouter: DeviceIoControl=%d", dwResult);
return dwResult;
}
}
return NO_ERROR;
#endif
}
DWORD WINAPI
UnenableRouter(OVERLAPPED* pOverlapped, LPDWORD lpdwEnableCount OPTIONAL)
{
#if defined(NT4) || defined(CHICAGO)
return ERROR_NOT_SUPPORTED;
#else
BOOL b;
DWORD EnableCount;
DWORD temp;
if (lpdwEnableCount && IsBadWritePtr(lpdwEnableCount, sizeof(DWORD))) {
return ERROR_INVALID_PARAMETER;
}
if (g_hIPDriverHandle == INVALID_HANDLE_VALUE) {
return ERROR_OPEN_FAILED;
}
b = DeviceIoControl(
g_hIPDriverHandle,
IOCTL_IP_UNENABLE_ROUTER_REQUEST,
(PVOID)&pOverlapped,
sizeof(PVOID),
&EnableCount,
sizeof(DWORD),
&temp,
NULL
);
if (!b) { return GetLastError(); }
if (lpdwEnableCount) { *lpdwEnableCount = EnableCount; }
return NO_ERROR;
#endif
}
DWORD WINAPI
DisableMediaSense(HANDLE *pHandle, OVERLAPPED *pOverLapped)
{
#if defined(NT4) || defined(CHICAGO)
return ERROR_NOT_SUPPORTED;
#else
BOOL b;
DWORD dwResult;
DWORD temp;
if ((pHandle != NULL) && (pOverLapped != NULL)) {
Trace0(ERR,"DisableMediaSense: overlapped request");
if (IsBadWritePtr(pHandle, sizeof(HANDLE)) ||
IsBadWritePtr(pOverLapped, sizeof(OVERLAPPED))) {
return ERROR_INVALID_PARAMETER;
}
*pHandle = g_hIPDriverHandle;
if (*pHandle == INVALID_HANDLE_VALUE) {
return ERROR_OPEN_FAILED;
}
b = DeviceIoControl(
*pHandle,
IOCTL_IP_DISABLE_MEDIA_SENSE_REQUEST,
NULL,
0,
NULL,
0,
&temp,
pOverLapped
);
if (!b) { return GetLastError(); }
} else {
Trace0(ERR,"DisableMediaSense: synchronous request");
b = DeviceIoControl(
g_hIPDriverHandle,
IOCTL_IP_DISABLE_MEDIA_SENSE_REQUEST,
NULL,
0,
NULL,
0,
&temp,
NULL
);
if (!b) {
dwResult = GetLastError();
Trace1(ERR,"DisableMediaSense: DeviceIoControl=%d", dwResult);
return dwResult;
}
}
return NO_ERROR;
#endif
}
DWORD WINAPI
RestoreMediaSense(OVERLAPPED* pOverlapped, LPDWORD lpdwEnableCount OPTIONAL)
{
#if defined(NT4) || defined(CHICAGO)
return ERROR_NOT_SUPPORTED;
#else
BOOL b;
DWORD EnableCount;
DWORD temp;
if (lpdwEnableCount && IsBadWritePtr(lpdwEnableCount, sizeof(DWORD))) {
return ERROR_INVALID_PARAMETER;
}
if (g_hIPDriverHandle == INVALID_HANDLE_VALUE) {
return ERROR_OPEN_FAILED;
}
b = DeviceIoControl(
g_hIPDriverHandle,
IOCTL_IP_ENABLE_MEDIA_SENSE_REQUEST,
(PVOID)&pOverlapped,
sizeof(PVOID),
&EnableCount,
sizeof(DWORD),
&temp,
NULL
);
if (!b) { return GetLastError(); }
if (lpdwEnableCount) { *lpdwEnableCount = EnableCount; }
return NO_ERROR;
#endif
}
#if !defined(NT4) && !defined(_WIN95_)
extern DWORD GetFixedInfoEx(PFIXED_INFO pFixedInfo, PULONG pOutBufLen);
extern DWORD GetAdapterInfoEx(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen);
extern DWORD GetAdapterAddressesEx(ULONG Family, DWORD Flags, PIP_ADAPTER_ADDRESSES pAdapterInfo, PULONG pOutBufLen);
#endif
#if !defined(NT4) && !defined(CHICAGO)
extern DWORD GetPerAdapterInfoEx(ULONG IfIndex, PIP_PER_ADAPTER_INFO pPerAdapterInfo, PULONG pOutBufLen);
#endif
DWORD
GetNetworkParams(PFIXED_INFO pFixedInfo, PULONG pOutBufLen)
{
#if !defined(NT4) && !defined(_WIN95_)
CheckTcpipState();
if (IsBadReadPtr(pOutBufLen, sizeof(ULONG))) {
return ERROR_INVALID_PARAMETER;
}
if (IsBadWritePtr(pOutBufLen, sizeof(ULONG))) {
return ERROR_INVALID_PARAMETER;
}
if (pFixedInfo != NULL &&
IsBadWritePtr(pFixedInfo, sizeof(FIXED_INFO))) {
return ERROR_INVALID_PARAMETER;
}
return GetFixedInfoEx(pFixedInfo, pOutBufLen);
#else
return ERROR_NOT_SUPPORTED;
#endif
}
DWORD
GetAdaptersAddresses(ULONG Family, DWORD Flags, PVOID Reserved,
PIP_ADAPTER_ADDRESSES pAdapterAddresses,
PULONG pOutBufLen)
{
#if !defined(NT4) && !defined(_WIN95_)
CheckTcpipState();
if (IsBadReadPtr(pOutBufLen, sizeof(ULONG))) {
return ERROR_INVALID_PARAMETER;
}
if (IsBadWritePtr(pOutBufLen, sizeof(ULONG))) {
return ERROR_INVALID_PARAMETER;
}
if (Reserved != NULL) {
return ERROR_INVALID_PARAMETER;
}
if (pAdapterAddresses != NULL &&
IsBadWritePtr(pAdapterAddresses, sizeof(IP_ADAPTER_ADDRESSES))) {
return ERROR_INVALID_PARAMETER;
}
return GetAdapterAddressesEx(Family, Flags, pAdapterAddresses, pOutBufLen);
#else
return ERROR_NOT_SUPPORTED;
#endif
}
DWORD
GetAdaptersInfo(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen)
{
#if !defined(NT4) && !defined(_WIN95_)
// call the init
CheckTcpipState();
if (IsBadReadPtr(pOutBufLen, sizeof(ULONG))) {
return ERROR_INVALID_PARAMETER;
}
if (IsBadWritePtr(pOutBufLen, sizeof(ULONG))) {
return ERROR_INVALID_PARAMETER;
}
if (pAdapterInfo != NULL &&
IsBadWritePtr(pAdapterInfo, sizeof(IP_ADAPTER_INFO))) {
return ERROR_INVALID_PARAMETER;
}
return GetAdapterInfoEx(pAdapterInfo, pOutBufLen);
#else
return ERROR_NOT_SUPPORTED;
#endif
}
DWORD
GetPerAdapterInfo(ULONG IfIndex, PIP_PER_ADAPTER_INFO pPerAdapterInfo,
PULONG pOutBufLen)
{
#if !defined(NT4) && !defined(CHICAGO)
CheckTcpipState();
if (IsBadReadPtr(pOutBufLen, sizeof(ULONG))) {
return ERROR_INVALID_PARAMETER;
}
if (IsBadWritePtr(pOutBufLen, sizeof(ULONG))) {
return ERROR_INVALID_PARAMETER;
}
if (pPerAdapterInfo != NULL &&
IsBadWritePtr(pPerAdapterInfo, sizeof(IP_PER_ADAPTER_INFO))) {
return ERROR_INVALID_PARAMETER;
}
return GetPerAdapterInfoEx(IfIndex, pPerAdapterInfo, pOutBufLen);
#else
return ERROR_NOT_SUPPORTED;
#endif
}
extern DWORD
DhcpReleaseParameters(
LPWSTR AdapterName
);
extern DWORD
DhcpAcquireParameters(
LPWSTR AdapterName);
#define TCP_EXPORT_STRING_PREFIX L"\\DEVICE\\TCPIP_"
DWORD
IpReleaseAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo)
{
#if defined(NT4) || defined(_WIN95_)
return ERROR_NOT_SUPPORTED;
#else
DWORD status;
if (!AdapterInfo) {
return ERROR_INVALID_PARAMETER;
}
if (IsBadReadPtr(AdapterInfo, sizeof(IP_ADAPTER_INDEX_MAP))) {
return ERROR_INVALID_PARAMETER;
}
#ifdef CHICAGO
{
// Convert the string to a widechar name
WCHAR Name[11];
uint i;
uint Index = AdapterInfo->Index;
i = sizeof(Name)/sizeof(Name[0]);
Name[--i] = L'\0';
while (i > 0 ) {
Name[--i] = L'0' + (Index%10);
Index /= 10;
}
status = DhcpReleaseParameters(Name);
}
#else
{
LPWSTR tmpstr;
if (wcslen(AdapterInfo->Name) <= wcslen(TCP_EXPORT_STRING_PREFIX)) {
return ERROR_INVALID_PARAMETER;
}
tmpstr = AdapterInfo->Name + wcslen(TCP_EXPORT_STRING_PREFIX);
__try {
status = DhcpReleaseParameters(tmpstr);
} __except(EXCEPTION_EXECUTE_HANDLER) {
status = ERROR_PROC_NOT_FOUND;
}
}
#endif
return(status);
#endif
}
DWORD
IpRenewAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo)
{
#if defined(NT4) || defined(_WIN95_)
return ERROR_NOT_SUPPORTED;
#else
DWORD status;
if (!AdapterInfo) {
return ERROR_INVALID_PARAMETER;
}
if (IsBadReadPtr(AdapterInfo, sizeof(IP_ADAPTER_INDEX_MAP))) {
return ERROR_INVALID_PARAMETER;
}
#ifdef CHICAGO
{
// Convert the string to a widechar name
WCHAR Name[11];
uint i;
uint Index = AdapterInfo->Index;
i = sizeof(Name)/sizeof(Name[0]);
Name[--i] = L'\0';
while (i > 0 ) {
Name[--i] = L'0' + (Index%10);
Index /= 10;
}
status = DhcpAcquireParameters(Name);
}
#else
{
LPWSTR tmpstr;
if (wcslen(AdapterInfo->Name) <= wcslen(TCP_EXPORT_STRING_PREFIX)) {
return ERROR_INVALID_PARAMETER;
}
tmpstr = AdapterInfo->Name + wcslen(TCP_EXPORT_STRING_PREFIX);
__try {
status = DhcpAcquireParameters(tmpstr);
} __except(EXCEPTION_EXECUTE_HANDLER) {
status = ERROR_PROC_NOT_FOUND;
}
}
#endif
return(status);
#endif
}
DWORD
SendARP(IPAddr DestIP, IPAddr SrcIP, PULONG pMacAddr, PULONG PhyAddrLen)
{
#if defined(NT4) || defined(_WIN95_)
return ERROR_NOT_SUPPORTED;
#else
ARP_SEND_REPLY requestBuffer;
DWORD requestBufferSize = sizeof(requestBuffer);
DWORD status;
requestBuffer.DestAddress = DestIP;
requestBuffer.SrcAddress = SrcIP;
if (IsBadWritePtr(pMacAddr, sizeof(ULONG))) {
return ERROR_INVALID_PARAMETER;
}
if (IsBadWritePtr(PhyAddrLen, sizeof(ULONG))) {
return ERROR_INVALID_PARAMETER;
}
status = TCPSendIoctl(g_hIPGetDriverHandle,
IOCTL_ARP_SEND_REQUEST,
&requestBuffer,
&requestBufferSize,
pMacAddr,
PhyAddrLen);
return(status);
#endif
}