Leaked source code of windows server 2003
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.
 
 
 
 
 
 

258 lines
6.0 KiB

/*++
Copyright (c) 1989-2001 Microsoft Corporation
Module Name:
ip2netbios.c
Abstract:
Generate a Netbios name for IPv6 address
srv.sys cannot handle IPv6 address. It always expect a 15 characters Netbios name.
This is a temporary solution. The utilmate solution should be in srv.
Author:
Jiandong Ruan
Revision History:
--*/
#include "precomp.h"
struct SMB_IPV6_NETBIOS_TABLE {
PSMB_HASH_TABLE HashTable;
DWORD SerialNumber;
#ifndef NO_LOOKASIDE_LIST
NPAGED_LOOKASIDE_LIST LookasideList;
BOOL LookasideListInitialized;
#endif
} SmbIPv6Mapping;
typedef struct {
LIST_ENTRY Linkage;
BYTE IpAddress[16];
LONG RefCount;
DWORD Serial;
} SMB_IPV6_NETBIOS, *PSMB_IPV6_NETBIOS;
#define SMB_IPV6_NETBIOS_TAG 'MBMS'
#ifdef NO_LOOKASIDE_LIST
PSMB_IPV6_NETBIOS __inline SMB_NEW_MAPPING(VOID)
{
return ExAllocatePoolWithTag(NonPagedPool, sizeof(SMB_IPV6_NETBIOS), SMB_IPV6_NETBIOS_TAG);
}
VOID __inline SMB_FREE_MAPPING(PSMB_IPV6_NETBIOS mapping)
{
ExFreePool(mapping);
}
#else
PSMB_IPV6_NETBIOS __inline SMB_NEW_MAPPING(VOID)
{
return ExAllocateFromNPagedLookasideList(&SmbIPv6Mapping.LookasideList);
}
VOID __inline SMB_FREE_MAPPING(PSMB_IPV6_NETBIOS mapping)
{
ExFreeToNPagedLookasideList(&SmbIPv6Mapping.LookasideList, mapping);
}
#endif
static PVOID __inline
SmbIPv6MapGetIpAddress(
PLIST_ENTRY entry
)
{
PSMB_IPV6_NETBIOS mapping = NULL;
mapping = CONTAINING_RECORD(entry, SMB_IPV6_NETBIOS, Linkage);
return mapping->IpAddress;
}
static int
SmbCompareIPv6Address(
PLIST_ENTRY entry,
BYTE ip6[16]
)
{
return memcmp(SmbIPv6MapGetIpAddress(entry), ip6, 16);
}
static DWORD
SmbHashIPv6(BYTE ip6[16])
{
DWORD sum = 0;
int i;
for (sum = 0, i = 0; i < 16; i++) {
sum += ip6[i];
}
return sum;
}
static VOID
SmbOnAddMapping(
PLIST_ENTRY entry
)
{
PSMB_IPV6_NETBIOS mapping = NULL;
mapping = CONTAINING_RECORD(entry, SMB_IPV6_NETBIOS, Linkage);
mapping->Serial = InterlockedIncrement(&SmbIPv6Mapping.SerialNumber);
mapping->RefCount = 1;
}
static VOID
SmbOnDelMapping(
PLIST_ENTRY entry
)
{
PSMB_IPV6_NETBIOS mapping = NULL;
mapping = CONTAINING_RECORD(entry, SMB_IPV6_NETBIOS, Linkage);
ASSERT(mapping->RefCount == 0);
SMB_FREE_MAPPING(mapping);
}
static LONG
SmbReferenceMapping(
PLIST_ENTRY entry
)
{
PSMB_IPV6_NETBIOS mapping = NULL;
LONG RefCount;
mapping = CONTAINING_RECORD(entry, SMB_IPV6_NETBIOS, Linkage);
RefCount = InterlockedIncrement(&mapping->RefCount);
ASSERT(RefCount > 1);
return RefCount;
}
static LONG
SmbDereferenceMapping(
PLIST_ENTRY entry
)
{
PSMB_IPV6_NETBIOS mapping = NULL;
LONG RefCount;
mapping = CONTAINING_RECORD(entry, SMB_IPV6_NETBIOS, Linkage);
RefCount = InterlockedDecrement(&mapping->RefCount);
ASSERT(RefCount >= 0);
return RefCount;
}
NTSTATUS
SmbInitIPv6NetbiosMappingTable(
VOID
)
{
NTSTATUS status = STATUS_SUCCESS;
RtlZeroMemory(&SmbIPv6Mapping, sizeof(SmbIPv6Mapping));
SmbIPv6Mapping.HashTable =
SmbCreateHashTable(
256,
SmbHashIPv6,
SmbIPv6MapGetIpAddress,
SmbCompareIPv6Address,
SmbOnAddMapping,
SmbOnDelMapping,
SmbReferenceMapping,
SmbDereferenceMapping
);
if (NULL == SmbIPv6Mapping.HashTable) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto error;
}
SmbIPv6Mapping.SerialNumber = 0;
#ifndef NO_LOOKASIDE_LIST
ExInitializeNPagedLookasideList(
&SmbIPv6Mapping.LookasideList,
NULL,
NULL,
0,
sizeof(SMB_IPV6_NETBIOS),
SMB_IPV6_NETBIOS_TAG,
0
);
SmbIPv6Mapping.LookasideListInitialized = TRUE;
#endif
error:
return status;
}
VOID
SmbShutdownIPv6NetbiosMappingTable(
VOID
)
{
SmbDestroyHashTable(SmbIPv6Mapping.HashTable);
SmbIPv6Mapping.HashTable = NULL;
#ifndef NO_LOOKASIDE_LIST
if (SmbIPv6Mapping.LookasideListInitialized) {
ExDeleteNPagedLookasideList(&SmbIPv6Mapping.LookasideList);
SmbIPv6Mapping.LookasideListInitialized = FALSE;
}
#endif
}
#define xdigit2asc(x) ((CHAR)(((x) < 10)?((x)+'0'):((x)+'0' + 'a' - '9' - 1)))
static void
UlongToHex(
ULONG x,
CHAR *Buffer
)
{
Buffer[0] = xdigit2asc((x >> 28) & 0xf);
Buffer[1] = xdigit2asc((x >> 24) & 0xf);
Buffer[2] = xdigit2asc((x >> 20) & 0xf);
Buffer[3] = xdigit2asc((x >> 16) & 0xf);
Buffer[4] = xdigit2asc((x >> 12) & 0xf);
Buffer[5] = xdigit2asc((x >> 8) & 0xf);
Buffer[6] = xdigit2asc((x >> 4) & 0xf);
Buffer[7] = xdigit2asc(x & 0xf);
Buffer[8] = 0;
}
BOOL
GetNetbiosNameFromIp6Address(BYTE ip6[16], CHAR SmbName[16])
{
PSMB_IPV6_NETBIOS NewMapping = NULL;
PLIST_ENTRY FoundEntry = NULL, NewEntry = NULL;
NewMapping = SMB_NEW_MAPPING();
if (NULL == NewMapping) {
return FALSE;
}
NewEntry = &NewMapping->Linkage;
RtlCopyMemory(NewMapping->IpAddress, ip6, 16);
FoundEntry = SmbAddToHashTable(SmbIPv6Mapping.HashTable, NewEntry);
if (FoundEntry != NewEntry) {
SMB_FREE_MAPPING(NewMapping);
NewMapping = NULL;
NewEntry = NULL;
}
NewMapping = CONTAINING_RECORD(FoundEntry, SMB_IPV6_NETBIOS, Linkage);
RtlCopyMemory(SmbName, "*SMBSERVER ", 7);
UlongToHex(NewMapping->Serial, SmbName + 7);
return TRUE;
}
VOID
FreeNetbiosNameForIp6Address(BYTE ip6[16])
{
SmbRemoveFromHashTable(SmbIPv6Mapping.HashTable, ip6);
}