|
|
//============================================================================
// Copyright (c) 1995, Microsoft Corporation
//
// File: update.c
//
// History:
// Abolade Gbadegesin July-24-1995 Created
//
// Routing table update thread
//============================================================================
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#ifndef CHICAGO
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#endif
#include <windows.h>
#include <string.h>
#include <malloc.h>
#include <io.h>
#include <winsvc.h>
#include "ipinfo.h"
#include "llinfo.h"
#include "ntddtcp.h"
#include "tdiinfo.h"
#include "routetab.h"
#include "rtdefs.h"
#define POS_DHCP 0
#define POS_EXIT 1
#define POS_LAST 2
//----------------------------------------------------------------------------
// Function: RTUpdateThread
//
// This is the main function for the background thread which is responsible
// for updating our tables of interfaces and addresses whenever DHCP
// notifies us of an address change.
//----------------------------------------------------------------------------
DWORD RTUpdateThread( LPVOID lpvParam ) {
DWORD dwErr; HMODULE hmodule; HANDLE hEvents[POS_LAST];
//
// Save the module-handle, which is passed to us
// as the thread-parameter
//
hmodule = (HMODULE)lpvParam;
//
// set up the event array for waiting
//
hEvents[POS_DHCP] = g_rtCfg.hDHCPEvent; hEvents[POS_EXIT] = g_rtCfg.hUpdateThreadExit;
while(TRUE) {
dwErr = WaitForMultipleObjects(POS_LAST, hEvents, FALSE, INFINITE);
//
// wait returned, find out why
//
if (dwErr == POS_EXIT) { break; } else if (dwErr == POS_DHCP) {
//
// an IP address changed.
// we reload the interface table and IP address table
// and signal the attached application
//
RT_LOCK();
if (g_rtCfg.lpIfTable != NULL) {
HeapFree(GetProcessHeap(), 0, g_rtCfg.lpIfTable);
g_rtCfg.lpIfTable = NULL; }
if (g_rtCfg.lpIPAddressTable != NULL) {
HeapFree(GetProcessHeap(), 0, g_rtCfg.lpIPAddressTable);
g_rtCfg.lpIPAddressTable = NULL; }
//
// reload the tables
//
dwErr = RTGetTables( &g_rtCfg.lpIfTable, &g_rtCfg.dwIfCount, &g_rtCfg.lpIPAddressTable, &g_rtCfg.dwIPAddressCount );
if (dwErr != 0) { RT_UNLOCK(); break; }
//
// signal the application if it has requested notification
//
if (g_rtCfg.hUserNotifyEvent != NULL) { SetEvent(g_rtCfg.hUserNotifyEvent); }
RT_UNLOCK(); } }
//
// Clean up the resources we're using
//
RTCleanUp();
//
// Unload the library and exit; this call never returns
//
FreeLibraryAndExitThread(hmodule, 0);
return 0; }
DWORD RTGetTables( LPIF_ENTRY* lplpIfTable, LPDWORD lpdwIfCount, LPIPADDRESS_ENTRY* lplpAddrTable, LPDWORD lpdwAddrCount ) {
ULONG_PTR *lpContext; IPSNMPInfo ipsiInfo; TDIObjectID *lpObject;
DWORD dwErr, dwInSize, dwOutSize; TCP_REQUEST_QUERY_INFORMATION_EX trqiBuffer;
//
// first get interface and address count
//
dwInSize = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX); dwOutSize = sizeof(IPSNMPInfo);
lpContext = trqiBuffer.Context; ZeroMemory(lpContext, CONTEXT_SIZE);
lpObject = &trqiBuffer.ID; lpObject->toi_id = IP_MIB_STATS_ID; lpObject->toi_type = INFO_TYPE_PROVIDER; lpObject->toi_class = INFO_CLASS_PROTOCOL; lpObject->toi_entity.tei_entity = CL_NL_ENTITY; lpObject->toi_entity.tei_instance = 0;
dwErr = TCPQueryInformationEx(&trqiBuffer, &dwInSize, &ipsiInfo, &dwOutSize); if (dwErr != NO_ERROR || ipsiInfo.ipsi_numaddr == 0) { return dwErr; }
// save the interface and address counts
//
*lpdwIfCount = ipsiInfo.ipsi_numif; *lpdwAddrCount = ipsiInfo.ipsi_numaddr;
// now get the interface table and address table
//
dwErr = RTGetIfTable(lplpIfTable, lpdwIfCount); if (dwErr == 0) { dwErr = RTGetAddrTable(lplpAddrTable, lpdwAddrCount); }
return dwErr; }
DWORD RTGetIfTable( LPIF_ENTRY* lplpIfTable, LPDWORD lpdwIfCount ) {
LPIF_ENTRY lpIfTable, lpif;
ULONG_PTR *lpContext; TDIObjectID *lpObject;
DWORD dwErr, dwi, dwInSize, dwOutSize; TCP_REQUEST_QUERY_INFORMATION_EX trqiBuffer;
if (*lpdwIfCount == 0) { return ERROR_INVALID_PARAMETER; }
dwInSize = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX); lpContext = trqiBuffer.Context;
lpObject = &trqiBuffer.ID; lpObject->toi_id = IF_MIB_STATS_ID; lpObject->toi_type = INFO_TYPE_PROVIDER; lpObject->toi_class = INFO_CLASS_PROTOCOL; lpObject->toi_entity.tei_entity = IF_ENTITY;
lpIfTable = HeapAlloc(GetProcessHeap(), 0, *lpdwIfCount * sizeof(IF_ENTRY)); if (lpIfTable == NULL) { *lpdwIfCount = 0; *lplpIfTable = NULL; return GetLastError(); }
lpif = lpIfTable; for (dwi = 0; dwi < *lpdwIfCount; dwi++) { dwOutSize = sizeof(IF_ENTRY); lpObject->toi_entity.tei_instance = dwi; ZeroMemory(lpContext, CONTEXT_SIZE); dwErr = TCPQueryInformationEx(&trqiBuffer, &dwInSize, lpif, &dwOutSize); if (dwErr == NO_ERROR) { ++lpif; } }
*lpdwIfCount = (DWORD)(lpif - lpIfTable); if (*lpdwIfCount == 0) { *lpdwIfCount = 0; *lplpIfTable = NULL; HeapFree(GetProcessHeap(), 0, lpIfTable); return ERROR_INVALID_PARAMETER; }
*lplpIfTable = lpIfTable;
return 0; }
DWORD RTGetAddrTable( LPIPADDRESS_ENTRY* lplpAddrTable, LPDWORD lpdwAddrCount ) {
ULONG_PTR *lpContext; TDIObjectID *lpObject;
LPIPADDRESS_ENTRY lpAddrTable; DWORD dwErr, dwInSize, dwOutSize; TCP_REQUEST_QUERY_INFORMATION_EX trqiBuffer;
if (*lpdwAddrCount == 0) { return ERROR_INVALID_PARAMETER; }
dwInSize = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX); dwOutSize = *lpdwAddrCount * sizeof(IPADDRESS_ENTRY);
lpAddrTable = HeapAlloc(GetProcessHeap(), 0, dwOutSize); if (lpAddrTable == NULL) { *lpdwAddrCount = 0; *lplpAddrTable = NULL; return GetLastError(); }
lpContext = trqiBuffer.Context; ZeroMemory(lpContext, CONTEXT_SIZE);
lpObject = &trqiBuffer.ID; lpObject->toi_id = IP_MIB_ADDRTABLE_ENTRY_ID; lpObject->toi_type = INFO_TYPE_PROVIDER; lpObject->toi_class = INFO_CLASS_PROTOCOL; lpObject->toi_entity.tei_entity = CL_NL_ENTITY; lpObject->toi_entity.tei_instance = 0;
dwErr = TCPQueryInformationEx(&trqiBuffer, &dwInSize, lpAddrTable, &dwOutSize); if (dwErr != NO_ERROR) { *lpdwAddrCount = 0; *lplpAddrTable = NULL; HeapFree(GetProcessHeap(), 0, lpAddrTable); return dwErr; }
*lpdwAddrCount = dwOutSize / sizeof(IPADDRESS_ENTRY); *lplpAddrTable = lpAddrTable;
return 0;
}
|