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
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);
|
|
}
|