windows-nt/Source/XPSP1/NT/net/wins/netsh/check.c
2020-09-26 16:20:57 +08:00

730 lines
16 KiB
C

/*++
Copyright (C) 1999 Microsoft Corporation
--*/
#include "precomp.h"
#define WCHARTONUM(wchr) (iswalpha(wchr)?(towlower(wchr)-L'a')+10:wchr-L'0')
UCHAR StringToHexA(IN LPCWSTR pwcString)
{
UCHAR ch = (CHAR)0x00;
if( pwcString is NULL )
return ch;
while(*pwcString != L'\0')
{
ch <<= 4;
ch |= WCHARTONUM(*pwcString);
pwcString++;
}
return ch;
}
ULONG LA_TableSize = 0;
VOID
FreeLATable(ULONG TableSize)
{
DWORD i = 0;
if( IsBadReadPtr((void *)LA_Table, TableSize) is FALSE &&
TableSize > 0 )
{
for( i=0; i<TableSize; i++ )
{
if( IsBadStringPtr(LA_Table[i], 20*sizeof(WCHAR)) is FALSE )
{
WinsFreeMemory((PVOID)LA_Table[i]);
LA_Table[i] = NULL;
}
}
WinsFreeMemory((PVOID)LA_Table);
LA_Table = NULL;
}
}
VOID
FreeSOTable(ULONG TableSize)
{
DWORD i = 0;
if( SO_Table )
{
for( i=0; i<TableSize; i++ )
{
if( SO_Table[i] )
{
WinsFreeMemory((PVOID)SO_Table[i]);
SO_Table[i] = NULL;
}
}
WinsFreeMemory((PVOID)SO_Table);
SO_Table = NULL;
}
}
VOID
DumpSOTable(
IN DWORD MasterOwners,
IN BOOL fFile,
IN FILE * pFile
)
{
ULONG i;
ULONG j;
DisplayMessage(g_hModule,
MSG_WINS_SOTABLE_HEADER);
if( fFile is TRUE )
{
DumpMessage(g_hModule,
pFile,
FMSG_WINS_SOTABLE_HEADER);
}
for (i = 0; i < MasterOwners; i++)
{
DisplayMessage(g_hModule,
MSG_WINS_MASTEROWNER_INDEX,
i);
if( fFile )
{
DumpMessage(g_hModule,
pFile,
FMSG_WINS_MASTEROWNER_INDEX,
i);
}
}
DisplayMessage(g_hModule,
WINS_FORMAT_LINE);
if( fFile )
{
DumpMessage(g_hModule,
pFile,
WINS_FORMAT_LINE);
}
for (i = 0; i < MasterOwners; i++)
{
DisplayMessage(g_hModule,
MSG_WINS_MASTEROWNER_INDEX1,
i);
if( fFile )
{
DumpMessage(g_hModule,
pFile,
FMSG_WINS_MASTEROWNER_INDEX1,
i);
}
for (j = 0; j < MasterOwners; j++)
{
DisplayMessage(g_hModule,
MSG_WINS_MASTEROWNER_INDEX,
SO_Table[i][j]);
if( fFile )
{
DumpMessage(g_hModule,
pFile,
FMSG_WINS_MASTEROWNER_INDEX,
SO_Table[i][j]);
}
}
DisplayMessage(g_hModule,
WINS_FORMAT_LINE);
if( fFile )
{
DumpMessage(g_hModule,
pFile,
WINS_FORMAT_LINE);
}
}
DisplayMessage(g_hModule,
MSG_WINS_MAP_SOURCE);
if( fFile )
{
DumpMessage(g_hModule,
pFile,
FMSG_WINS_MAP_SOURCE);
}
DumpLATable(MasterOwners, fFile, pFile);
}
VOID
DumpLATable(
IN DWORD MasterOwners,
IN BOOL fFile,
IN FILE * pFile
)
{
ULONG i;
ULONG j;
DisplayMessage(g_hModule,
MSG_WINS_INDEXTOIP_TABLE);
if( fFile )
{
DumpMessage(g_hModule,
pFile,
FMSG_WINS_INDEXTOIP_TABLE);
}
for (i = 0; i < MasterOwners; i++)
{
if (LA_Table[i][0] == '0')
{
break;
}
DisplayMessage(g_hModule,
MSG_WINS_INDEXTOIP_ENTRY,
i,
LA_Table[i]);
if( pFile )
{
DumpMessage(g_hModule,
pFile,
FMSG_WINS_INDEXTOIP_ENTRY,
i,
LA_Table[i]);
}
}
DisplayMessage(g_hModule,
WINS_FORMAT_LINE);
if( fFile )
{
DumpMessage(g_hModule,
pFile,
WINS_FORMAT_LINE);
}
}
LONG
IPToIndex(
IN LPWSTR IpAddr,
DWORD NoOfOwners
)
{
ULONG i=0;
WCHAR **pTempLA = NULL;
//
// Get the Row #
//
for ( i = 0; i < NoOfOwners; i++) {
if (wcscmp(LA_Table[i], IpAddr) == 0) {
return i;
}
//
// The first NULL entry indicates end
//
if (LA_Table[i][0] is L'0') {
break;
}
}
//
// Entry not found - add
//
wcscpy(LA_Table[i], IpAddr);
LA_TableSize = i+1;
return i;
}
//
// Check if the diagonal elements are the max in their cols.
//
VOID
CheckSOTableConsistency(
DWORD MasterOwners
)
{
ULONG i;
ULONG j;
BOOLEAN fProblem = FALSE;
for (i = 0; i < MasterOwners; i++)
{
//
// Is the diagonal element at i the largest in its column?
//
for (j = 0; j < MasterOwners; j++)
{
if (i == j)
{
continue;
}
//
// Compare only non-zero values
//
if (SO_Table[i][i].QuadPart &&
SO_Table[j][i].QuadPart &&
(SO_Table[i][i].QuadPart < SO_Table[j][i].QuadPart))
{
DisplayMessage(g_hModule, EMSG_WINS_VERSION_HIGHER, LA_Table[j], LA_Table[i]);
fProblem = TRUE;
}
}
}
if ( fProblem is FALSE )
{
DisplayMessage(g_hModule, EMSG_WINS_VERSION_CORRECT);
}
}
DWORD
InitLATable(
PWINSINTF_ADD_VERS_MAP_T pAddVersMaps,
DWORD MasterOwners, // 0 first time
DWORD NoOfOwners
)
{
ULONG i, j, k;
if( LA_Table is NULL )
{
LA_Table = WinsAllocateMemory(MAX_WINS*sizeof(LPWSTR));
if( LA_Table is NULL )
{
return 0;
}
for( i=0; i< MAX_WINS; i++ )
{
LA_Table[i] = WinsAllocateMemory(20*sizeof(WCHAR));
if( LA_Table[i] is NULL )
{
FreeLATable(i);
return 0;
}
}
}
if (MasterOwners == 0)
{
//
// first time - init the LA table
//
for (i = 0; i < NoOfOwners; i++, pAddVersMaps++)
{
struct in_addr InAddr;
LPWSTR pwsz = IpAddressToString(pAddVersMaps->Add.IPAdd);
if( pwsz is NULL )
{
FreeLATable(MAX_WINS);
return 0;
}
wcscpy(LA_Table[i], pwsz);
WinsFreeMemory(pwsz);
pwsz = NULL;
}
}
else
{
//
// More came in this time - add them to the LA table after the others
//
for (i = 0; i < NoOfOwners; i++, pAddVersMaps++)
{
LPWSTR pwszIp = IpAddressToString(pAddVersMaps->Add.IPAdd);
if( pwszIp is NULL )
{
FreeLATable(MAX_WINS);
return 0;
}
//
// If this entry is not in the LA table, insert
//
for (j = 0; j < MasterOwners; j++)
{
if (wcscmp(LA_Table[j], pwszIp) is 0 )
{
WinsFreeMemory(pwszIp);
pwszIp = NULL;
break;
}
}
if (j == MasterOwners)
{
//
// Insert
//
wcscpy(LA_Table[MasterOwners], pwszIp);
MasterOwners++;
}
if( pwszIp )
{
WinsFreeMemory(pwszIp);
pwszIp = NULL;
}
}
}
if( SO_Table is NULL )
{
SO_Table = WinsAllocateMemory((MAX_WINS+1)*sizeof(LARGE_INTEGER *));
if (SO_Table == NULL)
{
FreeLATable(MAX_WINS);
return 0;
}
for( i=0; i<MAX_WINS+1; i++ )
{
SO_Table[i] = WinsAllocateMemory((MAX_WINS+1)*sizeof(LARGE_INTEGER));
if( SO_Table[i] is NULL )
{
FreeLATable(MAX_WINS);
FreeSOTable(MAX_WINS+1);
return 0;
}
}
}
LA_TableSize = NoOfOwners;
return MasterOwners;
}
VOID
AddSOTableEntry (
IN LPWSTR IpAddr,
PWINSINTF_ADD_VERS_MAP_T pMasterMaps,
DWORD NoOfOwners,
DWORD MasterOwners
)
{
ULONG i;
LONG Row;
struct in_addr InAddr;
Row = IPToIndex(IpAddr, MasterOwners);
//
// Fill the row
//
for ( i = 0; i < NoOfOwners; i++, pMasterMaps++)
{
LONG col;
LPTSTR pstr;
InAddr.s_addr = htonl(pMasterMaps->Add.IPAdd);
pstr = IpAddressToString(pMasterMaps->Add.IPAdd);
if (pstr == NULL)
break;
col = IPToIndex(pstr, MasterOwners);
//
// Place only a non-deleted entry
//
if (!((pMasterMaps->VersNo.HighPart == MAXLONG) &&
(pMasterMaps->VersNo.LowPart == MAXULONG))) {
//
// Also if the entry above us was 0, write 0 there so as to make the fail case stand out
//
if (Row && SO_Table[Row-1][col].QuadPart == 0)
{
SO_Table[Row][col].QuadPart = 0;
}
else
{
SO_Table[Row][col] = pMasterMaps->VersNo;
}
}
}
}
VOID
RemoveFromSOTable(
IN LPWSTR IpAddr,
IN DWORD MasterOwners
)
{
ULONG i;
LONG Row;
struct in_addr InAddr;
Row = IPToIndex(IpAddr, MasterOwners);
//
// Mark the row and col as down (0's)
//
for (i = 0; i < MasterOwners; i++)
{
SO_Table[Row][i].QuadPart = SO_Table[i][Row].QuadPart = 0;
}
}
//
// Get the <owner address> - <version #> [OV table] mapping tables from each WINS server on the net and check for inconsistencies.
//
VOID
CheckVersionNumbers(
IN LPCSTR pStartIp,
IN BOOL fFile,
OUT FILE * pFile
)
{
DWORD Status = NO_ERROR;
ULONG i, k;
PWINSINTF_ADD_VERS_MAP_T pAddVersMaps;
PWINSINTF_ADD_VERS_MAP_T pMasterMaps; // master OV maps used to place into the OV table
DWORD NoOfOwners=0;
DWORD MasterOwners=0;
struct in_addr InAddr;
WINSINTF_RESULTS_NEW_T ResultsN;
DWORD ret;
handle_t hBindTemp = g_hBind;
WINSINTF_BIND_DATA_T BindDataTemp = g_BindData;
LPWSTR wszStartIp = NULL;
if( pStartIp is NULL )
return;
wszStartIp = WinsOemToUnicode(pStartIp, NULL);
if( wszStartIp is NULL )
{
DisplayMessage(g_hModule,
EMSG_WINS_OUT_OF_MEMORY);
return;
}
//
// Get the OV table from this server
//
if (NO_ERROR isnot (Status = GetStatus(TRUE, &ResultsN, TRUE, FALSE, pStartIp)) )
{
DisplayErrorMessage(EMSG_SRVR_CHECK_VERSION,
Status);
WinsFreeMemory(wszStartIp);
wszStartIp = NULL;
return;
}
else
{
DisplayMessage(g_hModule,
MSG_WINS_GETSTATUS_SUCCESS);
DisplayMessage(g_hModule,
WINS_FORMAT_LINE);
}
MasterOwners = NoOfOwners = ResultsN.NoOfOwners;
pMasterMaps = pAddVersMaps = ResultsN.pAddVersMaps;
ret = InitLATable(pAddVersMaps, 0, NoOfOwners);
if( LA_Table is NULL )
{
DisplayMessage(g_hModule,
EMSG_WINS_OUT_OF_MEMORY);
WinsFreeMemory(wszStartIp);
wszStartIp = NULL;
return;
}
if( SO_Table is NULL )
{
DisplayMessage(g_hModule,
EMSG_WINS_OUT_OF_MEMORY);
FreeLATable(MAX_WINS);
WinsFreeMemory(wszStartIp);
wszStartIp = NULL;
return;
}
AddSOTableEntry(wszStartIp, pMasterMaps, NoOfOwners, MasterOwners);
if( ResultsN.pAddVersMaps )
{
WinsFreeMem(ResultsN.pAddVersMaps);
ResultsN.pAddVersMaps = NULL;
}
//
// For each server X (other than Start addr) in the LA table:
//
for ( i = 0; i < MasterOwners; i++)
{
LPSTR pszName = NULL;
if( wcscmp(LA_Table[i], wszStartIp) is 0 )
{
continue;
}
//
// Get X's OV table
//
pszName = WinsUnicodeToOem(LA_Table[i], NULL);
if( pszName is NULL )
{
DisplayMessage(g_hModule,
EMSG_WINS_OUT_OF_MEMORY);
if( SO_Table )
{
FreeSOTable(MAX_WINS+1);
}
if( wszStartIp )
{
WinsFreeMemory(wszStartIp);
wszStartIp = NULL;
}
if( LA_Table )
{
FreeLATable(MAX_WINS);
}
return;
}
if( NO_ERROR isnot (Status = GetStatus(TRUE, &ResultsN, TRUE, FALSE, pszName) ) )
{
RemoveFromSOTable(LA_Table[i], MasterOwners);
if( pszName )
{
WinsFreeMemory(pszName);
pszName = NULL;
}
if( ResultsN.pAddVersMaps )
{
WinsFreeMem(ResultsN.pAddVersMaps);
ResultsN.pAddVersMaps = NULL;
}
DisplayErrorMessage(EMSG_WINS_GETSTATUS_FAILED,
Status);
continue;
}
else
{
DisplayMessage(g_hModule,
MSG_WINS_GETSTATUS_SUCCESS);
}
if (MasterOwners < ResultsN.NoOfOwners)
{
ret = InitLATable(ResultsN.pAddVersMaps, MasterOwners, ResultsN.NoOfOwners);
if( LA_Table is NULL or
SO_Table is NULL )
{
DisplayMessage(g_hModule,
EMSG_WINS_OUT_OF_MEMORY);
if( pszName )
{
WinsFreeMemory(pszName);
pszName = NULL;
}
if( ResultsN.pAddVersMaps )
{
WinsFreeMem(ResultsN.pAddVersMaps);
ResultsN.pAddVersMaps = NULL;
}
if( SO_Table )
{
WinsFreeMemory(SO_Table);
SO_Table = NULL;
}
if( LA_Table )
{
WinsFreeMemory(LA_Table);
LA_Table = NULL;
}
if( wszStartIp )
{
WinsFreeMemory(wszStartIp);
wszStartIp = NULL;
}
return;
}
MasterOwners = ret;
}
//
// Place entry in the SO Table in proper order
//
AddSOTableEntry(LA_Table[i], ResultsN.pAddVersMaps, ResultsN.NoOfOwners, MasterOwners);
if( pszName )
{
WinsFreeMemory(pszName);
pszName = NULL;
}
if( ResultsN.pAddVersMaps )
{
WinsFreeMem(ResultsN.pAddVersMaps);
ResultsN.pAddVersMaps = NULL;
}
}
//
// Check if diagonal elements in the [SO] table are the highest in their cols.
//
CheckSOTableConsistency(MasterOwners);
DumpSOTable(MasterOwners,
fFile,
pFile);
//
// Destroy SO table
//
FreeSOTable(MasterOwners+1);
FreeLATable(MasterOwners);
}