600 lines
12 KiB
C
600 lines
12 KiB
C
/*++
|
||
|
||
Copyright (c) 1996-2000 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
table.c
|
||
|
||
Abstract:
|
||
|
||
Domain Name System (DNS) Library
|
||
|
||
Routines to handle general table lookup.
|
||
|
||
Author:
|
||
|
||
Jim Gilroy (jamesg) December 1996
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
|
||
#include "local.h"
|
||
|
||
#include "time.h"
|
||
|
||
|
||
//
|
||
// Comparison function
|
||
//
|
||
|
||
typedef INT (__cdecl * COMPARISON_FUNCTION)(
|
||
const CHAR *,
|
||
const CHAR *,
|
||
size_t );
|
||
|
||
|
||
|
||
//
|
||
// Table lookup.
|
||
//
|
||
// Many DNS Records have human readable mnemonics for given data values.
|
||
// These are used for data file formats, and display in nslookup or debug
|
||
// output or cmdline tools.
|
||
//
|
||
// To simplify this process, have a single mapping functionality that
|
||
// supports DWORD \ LPSTR mapping tables. Tables for indivual types
|
||
// may then be layered on top of this.
|
||
//
|
||
// Support two table types.
|
||
// VALUE_TABLE_ENTRY is simple value-string mapping
|
||
// FLAG_TABLE_ENTRY is designed for bit field flag mappings where
|
||
// several flag strings might be contained in flag; this table
|
||
// contains additional mask field to allow multi-bit fields
|
||
// within the flag
|
||
//
|
||
|
||
#if 0
|
||
//
|
||
// Defined in local.h here only for reference
|
||
//
|
||
typedef struct
|
||
{
|
||
DWORD dwValue; // flag value
|
||
PCHAR pszString; // string representation of value
|
||
}
|
||
DNS_VALUE_TABLE_ENTRY;
|
||
|
||
typedef struct
|
||
{
|
||
DWORD dwFlag; // flag value
|
||
DWORD dwMask; // flag value mask
|
||
PCHAR pszString; // string representation of value
|
||
}
|
||
DNS_FLAG_TABLE_ENTRY;
|
||
|
||
// Error return on unmatched string
|
||
|
||
#define DNS_TABLE_LOOKUP_ERROR (-1)
|
||
|
||
#endif
|
||
|
||
|
||
|
||
DWORD
|
||
Dns_ValueForString(
|
||
IN DNS_VALUE_TABLE_ENTRY * Table,
|
||
IN BOOL fIgnoreCase,
|
||
IN PCHAR pchName,
|
||
IN INT cchNameLength
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Retrieve value for given string.
|
||
|
||
Arguments:
|
||
|
||
Table - table with value\string mapping
|
||
|
||
fIgnoreCase - TRUE if case-insensitive string lookup
|
||
|
||
pchName - ptr to string
|
||
|
||
cchNameLength - length of string
|
||
|
||
Return Value:
|
||
|
||
Flag value corresponding to string, if found.
|
||
DNS_TABLE_LOOKUP_ERROR otherwise.
|
||
|
||
--*/
|
||
{
|
||
INT i = 0;
|
||
// INT (* pcompareFunction)( const char *, const char *, size_t );
|
||
COMPARISON_FUNCTION pcompareFunction;
|
||
|
||
|
||
//
|
||
// if not given get string length
|
||
//
|
||
|
||
if ( !cchNameLength )
|
||
{
|
||
cchNameLength = strlen( pchName );
|
||
}
|
||
|
||
//
|
||
// determine comparison routine
|
||
//
|
||
|
||
if ( fIgnoreCase )
|
||
{
|
||
pcompareFunction = _strnicmp;
|
||
}
|
||
else
|
||
{
|
||
pcompareFunction = strncmp;
|
||
}
|
||
|
||
//
|
||
// find value matching name
|
||
//
|
||
|
||
while( Table[i].pszString != NULL )
|
||
{
|
||
if ( pcompareFunction( pchName, Table[i].pszString, cchNameLength ) == 0 )
|
||
{
|
||
return( Table[i].dwValue );
|
||
}
|
||
i++;
|
||
}
|
||
|
||
return( (DWORD)DNS_TABLE_LOOKUP_ERROR );
|
||
}
|
||
|
||
|
||
|
||
PCHAR
|
||
Dns_GetStringForValue(
|
||
IN DNS_VALUE_TABLE_ENTRY * Table,
|
||
IN DWORD dwValue
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Retrieve string representation of given value.
|
||
|
||
Arguments:
|
||
|
||
Table - table with value\string mapping
|
||
|
||
dwValue - value to map to strings
|
||
|
||
Return Value:
|
||
|
||
Ptr to mapping mneumonic string.
|
||
NULL if unknown mapping type.
|
||
|
||
--*/
|
||
{
|
||
INT i = 0;
|
||
|
||
//
|
||
// check all supported values for match
|
||
//
|
||
|
||
while( Table[i].pszString != NULL )
|
||
{
|
||
if ( dwValue == Table[i].dwValue )
|
||
{
|
||
return( Table[i].pszString );
|
||
}
|
||
i++;
|
||
}
|
||
return( NULL );
|
||
}
|
||
|
||
|
||
|
||
DWORD
|
||
Dns_FlagForString(
|
||
IN DNS_FLAG_TABLE_ENTRY * Table,
|
||
IN BOOL fIgnoreCase,
|
||
IN PCHAR pchName,
|
||
IN INT cchNameLength
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Retrieve flag value for given string.
|
||
|
||
This may be called repeatedly with additional strings and OR the result
|
||
together to build flag with independent bit settings.
|
||
|
||
Arguments:
|
||
|
||
Table - table with value\string mapping
|
||
|
||
fIgnoreCase - TRUE if case-insensitive string lookup
|
||
|
||
pchName - ptr to string
|
||
|
||
cchNameLength - length of string
|
||
|
||
Return Value:
|
||
|
||
Flag value corresponding to string, if found.
|
||
DNS_TABLE_LOOKUP_ERROR otherwise.
|
||
|
||
--*/
|
||
{
|
||
INT i = 0;
|
||
|
||
//
|
||
// if not given get string length
|
||
//
|
||
|
||
if ( !cchNameLength )
|
||
{
|
||
cchNameLength = strlen( pchName );
|
||
}
|
||
|
||
//
|
||
// check all supported values for name match
|
||
//
|
||
|
||
if ( fIgnoreCase )
|
||
{
|
||
while( Table[i].pszString != NULL )
|
||
{
|
||
if ( cchNameLength == (INT)strlen( Table[i].pszString )
|
||
&&
|
||
! _strnicmp( pchName, Table[i].pszString, cchNameLength ) )
|
||
{
|
||
return( Table[i].dwFlag );
|
||
}
|
||
i++;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
while( Table[i].pszString != NULL )
|
||
{
|
||
if ( cchNameLength == (INT)strlen( Table[i].pszString )
|
||
&&
|
||
! strncmp( pchName, Table[i].pszString, cchNameLength ) )
|
||
{
|
||
return( Table[i].dwFlag );
|
||
}
|
||
i++;
|
||
}
|
||
}
|
||
|
||
return( (DWORD) DNS_TABLE_LOOKUP_ERROR );
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
DnsPrint_ValueTable(
|
||
IN PRINT_ROUTINE PrintRoutine,
|
||
IN PPRINT_CONTEXT pPrintContext,
|
||
IN LPSTR pszHeader,
|
||
IN PDNS_VALUE_TABLE Table
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Print value table.
|
||
|
||
Arguments:
|
||
|
||
PrintRoutine - routine to print with
|
||
|
||
pPrintContext - print context
|
||
|
||
pszHeader - header to print
|
||
|
||
Table - value table to print
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
{
|
||
DWORD i = 0;
|
||
|
||
if ( !pszHeader )
|
||
{
|
||
pszHeader = "Table";
|
||
}
|
||
|
||
if ( ! pszHeader )
|
||
{
|
||
PrintRoutine(
|
||
pPrintContext,
|
||
"%s NULL value table to print",
|
||
pszHeader );
|
||
}
|
||
|
||
//
|
||
// print each value in table
|
||
//
|
||
|
||
DnsPrint_Lock();
|
||
|
||
PrintRoutine(
|
||
pPrintContext,
|
||
"%s\n",
|
||
pszHeader );
|
||
|
||
while( Table[i].pszString != NULL )
|
||
{
|
||
PrintRoutine(
|
||
pPrintContext,
|
||
"\t%40s\t\t%08x\n",
|
||
Table[i].pszString,
|
||
Table[i].dwValue );
|
||
i++;
|
||
}
|
||
|
||
DnsPrint_Unlock();
|
||
}
|
||
|
||
|
||
|
||
PCHAR
|
||
Dns_WriteStringsForFlag(
|
||
IN DNS_FLAG_TABLE_ENTRY * Table,
|
||
IN DWORD dwFlag,
|
||
IN OUT PCHAR pchFlag
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Retrieve flag string(s) corresponding to a given flag value.
|
||
|
||
This function is specifically for mapping a flag value into the
|
||
corresponding flag mnemonics.
|
||
|
||
No attempt is made to insure that every bit of dwValue is mapped,
|
||
nor are bits eliminated as they are mapped. Every value in table
|
||
that exactly matches bits in the table is returned.
|
||
|
||
Arguments:
|
||
|
||
Table - table with value\string mapping
|
||
|
||
dwFlag - flag value to map to strings
|
||
|
||
pchFlag - buffer to write flag to
|
||
|
||
Return Value:
|
||
|
||
Ptr to next location in pchFlag buffer.
|
||
If this is same as input, then no strings were written.
|
||
|
||
--*/
|
||
{
|
||
INT i = 0;
|
||
|
||
// init buffer for no-match
|
||
|
||
DNS_ASSERT( pchFlag != NULL );
|
||
*pchFlag = 0;
|
||
|
||
//
|
||
// check all supported flags types for name match
|
||
// - note comparing flag within mask to allow match of multi-bit
|
||
// flags
|
||
//
|
||
|
||
while( Table[i].pszString != NULL )
|
||
{
|
||
if ( (dwFlag & Table[i].dwMask) == Table[i].dwFlag )
|
||
{
|
||
pchFlag += sprintf( pchFlag, "%s ", Table[i].pszString );
|
||
}
|
||
i++;
|
||
}
|
||
return( pchFlag );
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
//
|
||
// Specific simple tables
|
||
//
|
||
|
||
//
|
||
// RnR Flag mappings
|
||
//
|
||
|
||
DNS_VALUE_TABLE_ENTRY RnrLupFlagTable[] =
|
||
{
|
||
LUP_DEEP , "LUP_DEEP" ,
|
||
LUP_CONTAINERS , "LUP_CONTAINERS" ,
|
||
LUP_NOCONTAINERS , "LUP_NOCONTAINERS" ,
|
||
LUP_RETURN_NAME , "LUP_RETURN_NAME" ,
|
||
LUP_RETURN_TYPE , "LUP_RETURN_TYPE" ,
|
||
LUP_RETURN_VERSION , "LUP_RETURN_VERSION" ,
|
||
LUP_RETURN_COMMENT , "LUP_RETURN_COMMENT" ,
|
||
LUP_RETURN_ADDR , "LUP_RETURN_ADDR" ,
|
||
LUP_RETURN_BLOB , "LUP_RETURN_BLOB" ,
|
||
LUP_RETURN_ALIASES , "LUP_RETURN_ALIASES" ,
|
||
LUP_RETURN_QUERY_STRING , "LUP_RETURN_QUERY_STRING" ,
|
||
LUP_RETURN_ALL , "LUP_RETURN_ALL" ,
|
||
LUP_RES_SERVICE , "LUP_RES_SERVICE" ,
|
||
LUP_FLUSHCACHE , "LUP_FLUSHCACHE" ,
|
||
LUP_FLUSHPREVIOUS , "LUP_FLUSHPREVIOUS" ,
|
||
|
||
0, NULL,
|
||
};
|
||
|
||
|
||
|
||
DWORD
|
||
Dns_RnrLupFlagForString(
|
||
IN PCHAR pchName,
|
||
IN INT cchNameLength
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Retrieve RnR LUP flag corresponding to string.
|
||
|
||
Arguments:
|
||
|
||
pchName - ptr to string
|
||
cchNameLength - length of string
|
||
|
||
Return Value:
|
||
|
||
Flag corresponding to string, if found.
|
||
Zero otherwise.
|
||
|
||
--*/
|
||
{
|
||
return Dns_ValueForString(
|
||
RnrLupFlagTable,
|
||
FALSE, // always upper case
|
||
pchName,
|
||
cchNameLength );
|
||
}
|
||
|
||
|
||
|
||
PCHAR
|
||
Dns_GetRnrLupFlagString(
|
||
IN DWORD dwFlag
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Get string corresponding to a given RnR LUP flag.
|
||
|
||
Arguments:
|
||
|
||
dwFlag -- flag
|
||
|
||
Return Value:
|
||
|
||
Ptr to flag mneumonic string.
|
||
NULL if unknown flag.
|
||
|
||
--*/
|
||
{
|
||
return Dns_GetStringForValue(
|
||
RnrLupFlagTable,
|
||
dwFlag );
|
||
}
|
||
|
||
|
||
//
|
||
// RnR Name Space ID mappings
|
||
//
|
||
|
||
DNS_VALUE_TABLE_ENTRY RnrNameSpaceMappingTable[] =
|
||
{
|
||
NS_ALL , "NS_ALL" ,
|
||
//NS_DEFAULT , "NS_DEFAULT" ,
|
||
NS_SAP , "NS_SAP" ,
|
||
NS_NDS , "NS_NDS" ,
|
||
NS_PEER_BROWSE , "NS_PEER_BROWSEE" ,
|
||
NS_SLP , "NS_SLP" ,
|
||
NS_DHCP , "NS_DHCP" ,
|
||
NS_TCPIP_LOCAL , "NS_TCPIP_LOCAL" ,
|
||
NS_TCPIP_HOSTS , "NS_TCPIP_HOSTS" ,
|
||
NS_DNS , "NS_DNS" ,
|
||
NS_NETBT , "NS_NETBT" ,
|
||
NS_WINS , "NS_WINS" ,
|
||
NS_NLA , "NS_NLA" ,
|
||
NS_NBP , "NS_NBP" ,
|
||
NS_MS , "NS_MS" ,
|
||
NS_STDA , "NS_STDA" ,
|
||
NS_NTDS , "NS_NTDS" ,
|
||
NS_X500 , "NS_X500" ,
|
||
NS_NIS , "NS_NIS" ,
|
||
NS_NISPLUS , "NS_NISPLUS" ,
|
||
NS_WRQ , "NS_WRQ" ,
|
||
NS_NETDES , "NS_NETDES" ,
|
||
|
||
0, NULL,
|
||
};
|
||
|
||
|
||
DWORD
|
||
Dns_RnrNameSpaceIdForString(
|
||
IN PCHAR pchName,
|
||
IN INT cchNameLength
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Retrieve RnR Name Space Id corresponding to string.
|
||
|
||
Arguments:
|
||
|
||
pchName - ptr to string
|
||
cchNameLength - length of string
|
||
|
||
Return Value:
|
||
|
||
Name space ID corresponding to string, if found.
|
||
Zero otherwise.
|
||
|
||
--*/
|
||
{
|
||
return Dns_ValueForString(
|
||
RnrNameSpaceMappingTable,
|
||
FALSE, // always upper case
|
||
pchName,
|
||
cchNameLength );
|
||
}
|
||
|
||
|
||
|
||
PCHAR
|
||
Dns_GetRnrNameSpaceIdString(
|
||
IN DWORD dwFlag
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Get string corresponding to a given RnR name space id.
|
||
|
||
Arguments:
|
||
|
||
dwFlag -- flag
|
||
|
||
Return Value:
|
||
|
||
Ptr to name space mneumonic string.
|
||
NULL if unknown flag.
|
||
|
||
--*/
|
||
{
|
||
return Dns_GetStringForValue(
|
||
RnrNameSpaceMappingTable,
|
||
dwFlag );
|
||
}
|
||
|
||
//
|
||
// End table.c
|
||
//
|