|
|
/*++
Copyright (c) 1989-1993 Microsoft Corporation
Module Name:
spxutils.c
Abstract:
This contains all utility routines for the ISN SPX module.
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
// Define module number for event logging entries
#define FILENUM SPXUTILS
UINT SpxUtilWstrLength( IN PWSTR Wstr ) /*++
Routine Description:
Arguments:
Return Value:
--*/ { UINT length = 0;
while (*Wstr++) { length += sizeof(WCHAR); }
return length; }
LONG SpxRandomNumber( VOID ) /*++
Routine Description:
Arguments:
Return Value:
--*/ { LARGE_INTEGER Li; static LONG seed = 0;
// Return a positive pseudo-random number; simple linear congruential
// algorithm. ANSI C "rand()" function.
if (seed == 0) { KeQuerySystemTime(&Li); seed = Li.LowPart; }
seed *= (0x41C64E6D + 0x3039);
return (seed & 0x7FFFFFFF); }
NTSTATUS SpxUtilGetSocketType( PUNICODE_STRING RemainingFileName, PBYTE SocketType ) /*++
Routine Description:
For PROTO_SPX, i'd return a device name from the dll of the form \Device\IsnSpx\SpxStream (for SOCK_STREAM) or \Device\IsnSpx\Spx (for SOCK_SEQPKT) and for PROTO_SPXII (the more common case we hope, even if internally we degrade to SPX1 cause of the remote client's limitations) \Device\IsnSpx\Stream (for SOCK_STREAM) or \Device\IsnSpx (for SOCK_SEQPKT)
Arguments:
Return Value:
--*/ { NTSTATUS status = STATUS_SUCCESS; UNICODE_STRING typeString;
*SocketType = SOCKET2_TYPE_SEQPKT;
// Check for the socket type
do { if (RemainingFileName->Length == 0) { break; }
if ((UINT)RemainingFileName->Length == SpxUtilWstrLength(SOCKET1STREAM_SUFFIX)) { RtlInitUnicodeString(&typeString, SOCKET1STREAM_SUFFIX); // Case insensitive compare
if (RtlEqualUnicodeString(&typeString, RemainingFileName, TRUE)) { *SocketType = SOCKET1_TYPE_STREAM; break; } }
if ((UINT)RemainingFileName->Length == SpxUtilWstrLength(SOCKET1_SUFFIX)) { RtlInitUnicodeString(&typeString, SOCKET1_SUFFIX); // Case insensitive compare
if (RtlEqualUnicodeString(&typeString, RemainingFileName, TRUE)) { *SocketType = SOCKET1_TYPE_SEQPKT; break; } }
if ((UINT)RemainingFileName->Length == SpxUtilWstrLength(SOCKET2STREAM_SUFFIX)) { RtlInitUnicodeString(&typeString, SOCKET2STREAM_SUFFIX); // Case insensitive compare
if (RtlEqualUnicodeString(&typeString, RemainingFileName, TRUE)) { *SocketType = SOCKET2_TYPE_STREAM; break; } }
status = STATUS_NO_SUCH_DEVICE; } while (FALSE);
return(status); }
#define ONE_MS_IN_100ns -10000L // 1ms in 100ns units
VOID SpxSleep( IN ULONG TimeInMs ) /*++
Routine Description:
Arguments:
Return Value:
--*/ { KTIMER SleepTimer;
ASSERT (KeGetCurrentIrql() == LOW_LEVEL);
KeInitializeTimer(&SleepTimer);
KeSetTimer(&SleepTimer, RtlConvertLongToLargeInteger(TimeInMs * ONE_MS_IN_100ns), NULL);
KeWaitForSingleObject(&SleepTimer, UserRequest, KernelMode, FALSE, NULL); return; }
TDI_ADDRESS_IPX UNALIGNED * SpxParseTdiAddress( IN TRANSPORT_ADDRESS UNALIGNED * TransportAddress )
/*++
Routine Description:
This routine scans a TRANSPORT_ADDRESS, looking for an address of type TDI_ADDRESS_TYPE_IPX.
Arguments:
Transport - The generic TDI address.
Return Value:
A pointer to the IPX address, or NULL if none is found.
--*/
{ TA_ADDRESS * addressName; INT i;
addressName = &TransportAddress->Address[0];
// The name can be passed with multiple entries; we'll take and use only
// the IPX one.
for (i=0;i<TransportAddress->TAAddressCount;i++) { if (addressName->AddressType == TDI_ADDRESS_TYPE_IPX) { if (addressName->AddressLength >= sizeof(TDI_ADDRESS_IPX)) { return ((TDI_ADDRESS_IPX UNALIGNED *)(addressName->Address)); } } addressName = (TA_ADDRESS *)(addressName->Address + addressName->AddressLength); } return NULL;
} // SpxParseTdiAddress
BOOLEAN SpxValidateTdiAddress( IN TRANSPORT_ADDRESS UNALIGNED * TransportAddress, IN ULONG TransportAddressLength )
/*++
Routine Description:
This routine scans a TRANSPORT_ADDRESS, verifying that the components of the address do not extend past the specified length.
Arguments:
TransportAddress - The generic TDI address.
TransportAddressLength - The specific length of TransportAddress.
Return Value:
TRUE if the address is valid, FALSE otherwise.
--*/
{ PUCHAR AddressEnd = ((PUCHAR)TransportAddress) + TransportAddressLength; TA_ADDRESS * addressName; INT i;
if (TransportAddressLength < sizeof(TransportAddress->TAAddressCount)) { DBGPRINT(TDI, ERR, ("SpxValidateTdiAddress: runt address\n"));
return FALSE; }
addressName = &TransportAddress->Address[0];
for (i=0;i<TransportAddress->TAAddressCount;i++) { if (addressName->Address > AddressEnd) { DBGPRINT(TDI, ERR, ("SpxValidateTdiAddress: address too short\n"));
return FALSE; } addressName = (TA_ADDRESS *)(addressName->Address + addressName->AddressLength); }
if ((PUCHAR)addressName > AddressEnd) { DBGPRINT(TDI, ERR, ("SpxValidateTdiAddress: address too short\n"));
return FALSE; } return TRUE;
} // SpxValidateTdiAddress
ULONG SpxBuildTdiAddress( IN PVOID AddressBuffer, IN ULONG AddressBufferLength, IN UCHAR Network[4], IN UCHAR Node[6], IN USHORT Socket )
/*++
Routine Description:
This routine fills in a TRANSPORT_ADDRESS in the specified buffer, given the socket, network and node. It will write less than the full address if the buffer is too short.
Arguments:
AddressBuffer - The buffer that will hold the address.
AddressBufferLength - The length of the buffer.
Network - The network number.
Node - The node address.
Socket - The socket.
Return Value:
The number of bytes written into AddressBuffer.
--*/
{ TA_IPX_ADDRESS UNALIGNED * SpxAddress; TA_IPX_ADDRESS TempAddress;
if (AddressBufferLength >= sizeof(TA_IPX_ADDRESS)) { SpxAddress = (TA_IPX_ADDRESS UNALIGNED *)AddressBuffer; } else { SpxAddress = (TA_IPX_ADDRESS UNALIGNED *)&TempAddress; }
SpxAddress->TAAddressCount = 1; SpxAddress->Address[0].AddressLength = sizeof(TDI_ADDRESS_IPX); SpxAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IPX; SpxAddress->Address[0].Address[0].NetworkAddress = *(UNALIGNED LONG *)Network; SpxAddress->Address[0].Address[0].Socket = Socket; RtlCopyMemory(SpxAddress->Address[0].Address[0].NodeAddress, Node, 6);
if (AddressBufferLength >= sizeof(TA_IPX_ADDRESS)) { return sizeof(TA_IPX_ADDRESS); } else { RtlCopyMemory(AddressBuffer, &TempAddress, AddressBufferLength); return AddressBufferLength; }
} // SpxBuildTdiAddress
VOID SpxBuildTdiAddressFromIpxAddr( IN PVOID AddressBuffer, IN PBYTE pIpxAddr ) { TA_IPX_ADDRESS UNALIGNED * SpxAddress;
SpxAddress = (TA_IPX_ADDRESS UNALIGNED *)AddressBuffer; SpxAddress->TAAddressCount = 1; SpxAddress->Address[0].AddressLength = sizeof(TDI_ADDRESS_IPX); SpxAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IPX; SpxAddress->Address[0].Address[0].NetworkAddress = *(UNALIGNED LONG *)pIpxAddr; RtlCopyMemory( SpxAddress->Address[0].Address[0].NodeAddress, pIpxAddr+4, 6);
GETSHORT2SHORT( &SpxAddress->Address[0].Address[0].Socket, pIpxAddr + 10);
return; }
VOID SpxCalculateNewT1( IN struct _SPX_CONN_FILE * pSpxConnFile, IN int NewT1 ) /*++
Routine Description:
Arguments:
NewT1 - New value for the RTT in ms.
Return Value:
--*/ { int baseT1, error;
//
// VAN JACOBSEN Algorithm. From Internetworking with Tcp/ip
// (Comer) book.
//
error = NewT1 - (pSpxConnFile->scf_AveT1 >> 3); pSpxConnFile->scf_AveT1 += error; if (pSpxConnFile->scf_AveT1 <= 0) // Make sure not too small
{ pSpxConnFile->scf_AveT1 = SPX_T1_MIN; }
if (error < 0) error = -error;
error -= (pSpxConnFile->scf_DevT1 >> 2); pSpxConnFile->scf_DevT1 += error; if (pSpxConnFile->scf_DevT1 <= 0) pSpxConnFile->scf_DevT1 = 1;
baseT1 = (((pSpxConnFile->scf_AveT1 >> 2) + pSpxConnFile->scf_DevT1) >> 1);
// If less then min - set it
if (baseT1 < SPX_T1_MIN) baseT1 = SPX_T1_MIN;
// Set the new value
DBGPRINT(TDI, DBG, ("SpxCalculateNewT1: Old value %lx New %lx\n", pSpxConnFile->scf_BaseT1, baseT1));
pSpxConnFile->scf_BaseT1 = baseT1;
// At the time of restarting the timer,we convert this to a tick value.
return; }
|