diff options
Diffstat (limited to '')
-rw-r--r-- | private/ntos/tdi/isn/nb/bind.c | 594 |
1 files changed, 594 insertions, 0 deletions
diff --git a/private/ntos/tdi/isn/nb/bind.c b/private/ntos/tdi/isn/nb/bind.c new file mode 100644 index 000000000..58509f692 --- /dev/null +++ b/private/ntos/tdi/isn/nb/bind.c @@ -0,0 +1,594 @@ +/*++ + +Copyright (c) 1989-1993 Microsoft Corporation + +Module Name: + + driver.c + +Abstract: + + This module contains the DriverEntry and other initialization + code for the Netbios module of the ISN transport. + +Author: + + Adam Barr (adamba) 16-November-1993 + +Environment: + + Kernel mode + +Revision History: + + +--*/ + +#include "precomp.h" +#pragma hdrstop + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT,NbiBind) +#endif + +#if defined(_PNP_POWER) +// +// local functions. +// +VOID +NbiPnPNotification( + IN IPX_PNP_OPCODE OpCode, + IN PVOID PnPData + ); +#endif _PNP_POWER + + +NTSTATUS +NbiBind( + IN PDEVICE Device, + IN PCONFIG Config + ) + +/*++ + +Routine Description: + + This routine binds the Netbios module of ISN to the IPX + module, which provides the NDIS binding services. + +Arguments: + + Device - Pointer to the Netbios device. + + Config - Pointer to the configuration information. + +Return Value: + + The function value is the final status from the initialization operation. + +--*/ + +{ + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + OBJECT_ATTRIBUTES ObjectAttributes; +/* union { + IPX_INTERNAL_BIND_INPUT Input; + IPX_INTERNAL_BIND_OUTPUT Output; + } Bind; +*/ + InitializeObjectAttributes( + &ObjectAttributes, + &Config->BindName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = ZwCreateFile( + &Device->BindHandle, + SYNCHRONIZE | GENERIC_READ, + &ObjectAttributes, + &IoStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN, + FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0L); + + if (!NT_SUCCESS(Status)) { + + NB_DEBUG (BIND, ("Could not open IPX (%ws) %lx\n", + Config->BindName.Buffer, Status)); + NbiWriteGeneralErrorLog( + Device, + EVENT_TRANSPORT_ADAPTER_NOT_FOUND, + 1, + Status, + Config->BindName.Buffer, + 0, + NULL); + return Status; + } + + // + // Fill in our bind data. + // + +#if defined(_PNP_POWER) + Device->BindInput.Version = ISN_VERSION; +#else + Device->BindInput.Version = 1; +#endif _PNP_POWER + Device->BindInput.Identifier = IDENTIFIER_NB; + Device->BindInput.BroadcastEnable = TRUE; + Device->BindInput.LookaheadRequired = 192; + Device->BindInput.ProtocolOptions = 0; + Device->BindInput.ReceiveHandler = NbiReceive; + Device->BindInput.ReceiveCompleteHandler = NbiReceiveComplete; + Device->BindInput.StatusHandler = NbiStatus; + Device->BindInput.SendCompleteHandler = NbiSendComplete; + Device->BindInput.TransferDataCompleteHandler = NbiTransferDataComplete; + Device->BindInput.FindRouteCompleteHandler = NbiFindRouteComplete; + Device->BindInput.LineUpHandler = NbiLineUp; + Device->BindInput.LineDownHandler = NbiLineDown; + Device->BindInput.ScheduleRouteHandler = NULL; +#if defined(_PNP_POWER) + Device->BindInput.PnPHandler = NbiPnPNotification; +#endif _PNP_POWER + + + Status = ZwDeviceIoControlFile( + Device->BindHandle, // HANDLE to File + NULL, // HANDLE to Event + NULL, // ApcRoutine + NULL, // ApcContext + &IoStatusBlock, // IO_STATUS_BLOCK + IOCTL_IPX_INTERNAL_BIND, // IoControlCode + &Device->BindInput, // Input Buffer + sizeof(Device->BindInput), // Input Buffer Length + &Device->Bind, // OutputBuffer + sizeof(Device->Bind)); // OutputBufferLength + + // + // We open synchronous, so this shouldn't happen. + // + + CTEAssert (Status != STATUS_PENDING); + + // + // Save the bind data. + // + + if (Status == STATUS_SUCCESS) { + + NB_DEBUG2 (BIND, ("Successfully bound to IPX (%ws)\n", + Config->BindName.Buffer)); +// RtlCopyMemory (&Device->Bind, &Bind.Output, sizeof(IPX_INTERNAL_BIND_OUTPUT)); + +#if !defined(_PNP_POWER) + RtlZeroMemory (Device->ReservedNetbiosName, 16); + RtlCopyMemory (&Device->ReservedNetbiosName[10], Device->Bind.Node, 6); + + Status = (*Device->Bind.QueryHandler)( // BUGBUG: Check return code + IPX_QUERY_MAXIMUM_NIC_ID, + (USHORT)0, + &Device->MaximumNicId, + sizeof(Device->MaximumNicId), + NULL); + CTEAssert (Status == STATUS_SUCCESS); +#endif !_PNP_POWER + + } else { + + NB_DEBUG (BIND, ("Could not bind to IPX (%ws) %lx\n", + Config->BindName.Buffer, Status)); + NbiWriteGeneralErrorLog( + Device, + EVENT_TRANSPORT_BINDING_FAILED, + 1, + Status, + Config->BindName.Buffer, + 0, + NULL); + ZwClose(Device->BindHandle); + } + + return Status; + +} /* NbiBind */ + + +VOID +NbiUnbind( + IN PDEVICE Device + ) + +/*++ + +Routine Description: + + This function closes the binding between the Netbios over + IPX module and the IPX module previously established by + NbiBind. + +Arguments: + + Device - The netbios device object. + +Return Value: + + None. + +--*/ + +{ + ZwClose (Device->BindHandle); + +} /* NbiUnbind */ + + +VOID +NbiStatus( + IN USHORT NicId, + IN NDIS_STATUS GeneralStatus, + IN PVOID StatusBuffer, + IN UINT StatusBufferLength + ) + +/*++ + +Routine Description: + + This function receives a status indication from IPX, + corresponding to a status indication from an underlying + NDIS driver. + +Arguments: + + NicId - The NIC ID of the underlying adapter. + + GeneralStatus - The general status code. + + StatusBuffer - The status buffer. + + StatusBufferLength - The length of the status buffer. + +Return Value: + + None. + +--*/ + +{ + +} /* NbiStatus */ + + +VOID +NbiLineUp( + IN USHORT NicId, + IN PIPX_LINE_INFO LineInfo, + IN NDIS_MEDIUM DeviceType, + IN PVOID ConfigurationData + ) + + +/*++ + +Routine Description: + + This function receives line up indications from IPX, + indicating that the specified adapter is now up with + the characteristics shown. + +Arguments: + + NicId - The NIC ID of the underlying adapter. + + LineInfo - Information about the adapter's medium. + + DeviceType - The type of the adapter. + + ConfigurationData - IPX-specific configuration data. + +Return Value: + + None. + +--*/ + +{ + PIPXCP_CONFIGURATION Configuration = (PIPXCP_CONFIGURATION)ConfigurationData; + + // + // Update queries have NULL as the ConfigurationData. These + // only indicate changes in LineInfo. BUGBUG Ignore these + // for the moment. + // + + if (Configuration == NULL) { + return; + } + +#if !defined(_PNP_POWER) + // + // Since Netbios outgoing queries only go out on network 1, + // we ignore this (BUGBUG for the moment) unless that is + // the NIC it is on. + // + + if (NicId == 1) { + + RtlCopyMemory(NbiDevice->ConnectionlessHeader.SourceNetwork, Configuration->Network, 4); + RtlCopyMemory(NbiDevice->ConnectionlessHeader.SourceNode, Configuration->LocalNode, 6); + + } +#endif !_PNP_POWER +} /* NbiLineUp */ + + +VOID +NbiLineDown( + IN USHORT NicId, + IN ULONG FwdAdapterContext + ) + + +/*++ + +Routine Description: + + This function receives line down indications from IPX, + indicating that the specified adapter is no longer + up. + +Arguments: + + NicId - The NIC ID of the underlying adapter. + +Return Value: + + None. + +--*/ + +{ + +} /* NbiLineDown */ + +#if defined(_PNP_POWER) + +VOID +NbiPnPNotification( + IN IPX_PNP_OPCODE OpCode, + IN PVOID PnPData + ) + +/*++ + +Routine Description: + + This function receives the notification about PnP events from IPX. + +Arguments: + + OpCode - Type of the PnP event + + PnPData - Data associated with this event. + +Return Value: + + None. + +--*/ + +{ + + PDEVICE Device = NbiDevice; + USHORT MaximumNicId = 0; + CTELockHandle LockHandle; + UCHAR PrevReservedName[NB_NETBIOS_NAME_SIZE]; + UNICODE_STRING UnicodeDeviceName; + + + NB_DEBUG2( DEVICE, ("Received a pnp notification, opcode %d\n",OpCode )); + + switch( OpCode ) { + case IPX_PNP_ADD_DEVICE : { + IPX_PNP_INFO UNALIGNED *PnPInfo = (IPX_PNP_INFO UNALIGNED *)PnPData; + BOOLEAN ReallocReceiveBuffers = FALSE; + + NB_GET_LOCK( &Device->Lock, &LockHandle ); + + if ( PnPInfo->NewReservedAddress ) { + + *(UNALIGNED ULONG *)Device->Bind.Network = PnPInfo->NetworkAddress; + RtlCopyMemory( Device->Bind.Node, PnPInfo->NodeAddress, 6); + +// RtlZeroMemory(Device->ReservedNetbiosName, NB_NETBIOS_NAME_SIZE); +// RtlCopyMemory(&Device->ReservedNetbiosName[10], Device->Bind.Node, 6); + + *(UNALIGNED ULONG *)Device->ConnectionlessHeader.SourceNetwork = *(UNALIGNED ULONG *)Device->Bind.Network; + RtlCopyMemory(Device->ConnectionlessHeader.SourceNode, Device->Bind.Node, 6); + } + + if ( PnPInfo->FirstORLastDevice ) { + CTEAssert( PnPInfo->NewReservedAddress ); + CTEAssert( Device->State != DEVICE_STATE_OPEN ); + + + // + // we must do this while we still have the device lock. + // + if ( !Device->LongTimerRunning ) { + Device->LongTimerRunning = TRUE; + NbiReferenceDevice (Device, DREF_LONG_TIMER); + + CTEStartTimer( + &Device->LongTimer, + LONG_TIMER_DELTA, + NbiLongTimeout, + (PVOID)Device); + + } + + Device->State = DEVICE_STATE_OPEN; + + CTEAssert( !Device->MaximumNicId ); + + Device->Bind.LineInfo.MaximumSendSize = PnPInfo->LineInfo.MaximumSendSize; + Device->Bind.LineInfo.MaximumPacketSize = PnPInfo->LineInfo.MaximumSendSize; + ReallocReceiveBuffers = TRUE; + } else { + if ( PnPInfo->LineInfo.MaximumPacketSize > Device->CurMaxReceiveBufferSize ) { + ReallocReceiveBuffers = TRUE; + } + // + // MaxSendSize could become smaller. + // + Device->Bind.LineInfo.MaximumSendSize = PnPInfo->LineInfo.MaximumSendSize; + } + + Device->MaximumNicId++; + + + // + // + NbiCreateAdapterAddress( PnPInfo->NodeAddress ); + + // + // And finally remove all the failed cache entries since we might + // find those routes using this new adapter + // + FlushFailedNetbiosCacheEntries(Device->NameCache); + + NB_FREE_LOCK( &Device->Lock, LockHandle ); + + + if ( ReallocReceiveBuffers ) { + PWORK_QUEUE_ITEM WorkItem; + + WorkItem = NbiAllocateMemory( sizeof(WORK_QUEUE_ITEM), MEMORY_WORK_ITEM, "Alloc Rcv Buffer work item"); + + if ( WorkItem ) { + ExInitializeWorkItem( WorkItem, NbiReAllocateReceiveBufferPool, (PVOID) WorkItem ); + ExQueueWorkItem( WorkItem, DelayedWorkQueue ); + } else { + NB_DEBUG( DEVICE, ("Cannt schdule work item to realloc receive buffer pool\n")); + } + } + // + // Notify the TDI clients about the device creation + // + if ( PnPInfo->FirstORLastDevice ) { + UnicodeDeviceName.Buffer = Device->DeviceName; + UnicodeDeviceName.MaximumLength = Device->DeviceNameLength; + UnicodeDeviceName.Length = Device->DeviceNameLength - sizeof(WCHAR); + + if ( !NT_SUCCESS( TdiRegisterDeviceObject( + &UnicodeDeviceName, + &Device->TdiRegistrationHandle ) )) { + NB_DEBUG( DEVICE, ("Failed to register nwlnknb with TDI\n")); + } + } + + break; + } + case IPX_PNP_DELETE_DEVICE : { + + IPX_PNP_INFO UNALIGNED *PnPInfo = (IPX_PNP_INFO UNALIGNED *)PnPData; + + PLIST_ENTRY p; + PNETBIOS_CACHE CacheName; + USHORT i,j,NetworksRemoved; + + NB_GET_LOCK( &Device->Lock, &LockHandle ); + + CTEAssert( Device->MaximumNicId ); + Device->MaximumNicId--; + + if ( PnPInfo->FirstORLastDevice ) { + Device->State = DEVICE_STATE_LOADED; + Device->MaximumNicId = 0; + + } + + + // + // MaximumSendSize could change if the card with the smallest send size just + // got removed. MaximumPacketSize could only become smaller and we ignore that + // since we dont need to(want to) realloc ReceiveBuffers. + // + + Device->Bind.LineInfo.MaximumSendSize = PnPInfo->LineInfo.MaximumSendSize; + + // + // Flush all the cache entries that are using this NicId in the local + // target. + // + RemoveInvalidRoutesFromNetbiosCacheTable( Device->NameCache, &PnPInfo->NicHandle ); + + NbiDestroyAdapterAddress( NULL, PnPInfo->NodeAddress ); + + NB_FREE_LOCK( &Device->Lock, LockHandle ); + +/* // + // Now mark the previous reserved name in conflict if it has + // been registered by any of our client + // + if ( Address = NbiFindAddress( Device, PrevReservedName ) ) { + NB_GET_LOCK( &Address->Lock, &LockHandle ); + Address->Flags |= ADDRESS_FLAGS_CONFLICT; + NB_FREE_LOCK( &Address->Lock, LockHandle ); + + NB_DEBUG( ADDRESS, ("Reserved Address %lx<%.16s> is marked CONFLICT\n",Address,Address->NetbiosAddress.NetbiosName)); + // + // nbifindaddress added a reference, so deref + // + NbiDereferenceAddress( Address, AREF_FIND ); + } +*/ + + // + // inform tdi clients about the device deletion + // + if ( PnPInfo->FirstORLastDevice ) { + if ( !NT_SUCCESS( TdiDeregisterDeviceObject( + Device->TdiRegistrationHandle ) )) { + NB_DEBUG( DEVICE, ("Failed to Deregister nwlnknb with TDI\n")); + } + } + + break; + } + case IPX_PNP_ADDRESS_CHANGE: { + IPX_PNP_INFO UNALIGNED *PnPInfo = (IPX_PNP_INFO UNALIGNED *)PnPData; + PADDRESS Address; + BOOLEAN ReservedNameClosing = FALSE; + + CTEAssert( PnPInfo->NewReservedAddress ); + + NB_GET_LOCK( &Device->Lock, &LockHandle ); + *(UNALIGNED ULONG *)Device->Bind.Network = PnPInfo->NetworkAddress; + RtlCopyMemory( Device->Bind.Node, PnPInfo->NodeAddress, 6); + + *(UNALIGNED ULONG *)Device->ConnectionlessHeader.SourceNetwork = *(UNALIGNED ULONG *)Device->Bind.Network; + RtlCopyMemory(Device->ConnectionlessHeader.SourceNode, Device->Bind.Node, 6); + + NB_FREE_LOCK( &Device->Lock, LockHandle ); + + + break; + } + case IPX_PNP_TRANSLATE_DEVICE: + break; + case IPX_PNP_TRANSLATE_ADDRESS: + break; + default: + CTEAssert( FALSE ); + } +} /* NbiPnPNotification */ + +#endif _PNP_POWER |