summaryrefslogtreecommitdiffstats
path: root/private/ntos/bowser/bowipx.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/bowser/bowipx.c
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/bowser/bowipx.c')
-rw-r--r--private/ntos/bowser/bowipx.c383
1 files changed, 383 insertions, 0 deletions
diff --git a/private/ntos/bowser/bowipx.c b/private/ntos/bowser/bowipx.c
new file mode 100644
index 000000000..b2841c353
--- /dev/null
+++ b/private/ntos/bowser/bowipx.c
@@ -0,0 +1,383 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ bowtdi.c
+
+Abstract:
+
+ This module implements all of the routines that interface with the TDI
+ transport for NT
+
+Author:
+
+ Larry Osterman (LarryO) 21-Jun-1990
+
+Revision History:
+
+ 21-Jun-1990 LarryO
+
+ Created
+
+--*/
+
+
+#include "precomp.h"
+#include <isnkrnl.h>
+#include <smbipx.h>
+#pragma hdrstop
+
+NTSTATUS
+BowserHandleIpxDomainAnnouncement(
+ IN PTRANSPORT Transport,
+ IN PSMB_IPX_NAME_PACKET NamePacket,
+ IN PBROWSE_ANNOUNCE_PACKET_1 DomainAnnouncement,
+ IN DWORD RequestLength,
+ IN ULONG ReceiveFlags
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE4BROW, BowserHandleIpxDomainAnnouncement)
+#endif
+
+NTSTATUS
+BowserIpxDatagramHandler (
+ IN PVOID TdiEventContext,
+ IN LONG SourceAddressLength,
+ IN PVOID SourceAddress,
+ IN LONG OptionsLength,
+ IN PVOID Options,
+ IN ULONG ReceiveDatagramFlags,
+ IN ULONG BytesIndicated,
+ IN ULONG BytesAvailable,
+ OUT ULONG *BytesTaken,
+ IN PVOID Tsdu,
+ OUT PIRP *IoRequestPacket
+ )
+{
+ PVOID DatagramData;
+ PINTERNAL_TRANSACTION InternalTransaction = NULL;
+ ULONG DatagramDataSize;
+ PTRANSPORT Transport = TdiEventContext;
+ MAILSLOTTYPE Opcode;
+ PSMB_IPX_NAME_PACKET NamePacket = Tsdu;
+ PSMB_HEADER Smb = (PSMB_HEADER)(NamePacket+1);
+ PCHAR ComputerName;
+ PCHAR DomainName;
+ PTRANSPORT_NAME TransportName = Transport->ComputerName;
+ ULONG SmbLength = BytesIndicated - sizeof(SMB_IPX_NAME_PACKET);
+
+
+ if (BytesAvailable > Transport->DatagramSize) {
+ return STATUS_REQUEST_NOT_ACCEPTED;
+ }
+
+ if (BytesIndicated <= sizeof(SMB_IPX_NAME_PACKET)) {
+ return STATUS_REQUEST_NOT_ACCEPTED;
+ }
+
+ //
+ // If we're not fully initialized yet,
+ // simply ignore the packet.
+ //
+ if (Transport->ComputerName == NULL ||
+ Transport->PrimaryDomain == NULL ) {
+ return STATUS_REQUEST_NOT_ACCEPTED;
+ }
+
+
+ ComputerName = ((PTA_NETBIOS_ADDRESS)(Transport->ComputerName->TransportAddress.Buffer))->Address[0].Address->NetbiosName;
+ DomainName = ((PTA_NETBIOS_ADDRESS)(Transport->PrimaryDomain->TransportAddress.Buffer))->Address[0].Address->NetbiosName;
+
+ //
+ // It's not for us, ignore the announcement.
+ //
+
+ if (NamePacket->NameType == SMB_IPX_NAME_TYPE_MACHINE) {
+
+ // Mailslot messages are always sent as TYPE_MACHINE even when they're
+ // to the DomainName (so allow both).
+ if (!RtlEqualMemory(ComputerName, NamePacket->Name, SMB_IPX_NAME_LENGTH) &&
+ !RtlEqualMemory(DomainName, NamePacket->Name, SMB_IPX_NAME_LENGTH)) {
+ return STATUS_REQUEST_NOT_ACCEPTED;
+ }
+ } else if (NamePacket->NameType == SMB_IPX_NAME_TYPE_WORKKGROUP) {
+ if (!RtlEqualMemory(DomainName, NamePacket->Name, SMB_IPX_NAME_LENGTH)) {
+ return STATUS_REQUEST_NOT_ACCEPTED;
+ }
+ } else if (NamePacket->NameType != SMB_IPX_NAME_TYPE_BROWSER) {
+ return STATUS_REQUEST_NOT_ACCEPTED;
+ }
+
+ //
+ // Classify the incoming packet according to it's type. Depending on
+ // the type, either process it as:
+ //
+ // 1) A server announcement
+ // 2) An incoming mailslot
+ //
+
+ Opcode = BowserClassifyIncomingDatagram(Smb, SmbLength,
+ &DatagramData,
+ &DatagramDataSize);
+ if (Opcode == MailslotTransaction) {
+
+ //
+ // BowserHandleMailslotTransaction will always receive the indicated bytes
+ // expecting to find the SMB. Tell the TDI driver we've already consumed
+ // the IPX_NAME_PACKET to keep that assumption constant.
+ //
+
+ *BytesTaken = sizeof(SMB_IPX_NAME_PACKET);
+ return BowserHandleMailslotTransaction(
+ Transport->ComputerName,
+ NamePacket->SourceName,
+ sizeof(SMB_IPX_NAME_PACKET), // SMB offset into TSDU
+ ReceiveDatagramFlags,
+ BytesIndicated,
+ BytesAvailable,
+ BytesTaken,
+ Tsdu,
+ IoRequestPacket );
+
+ } else if (Opcode == Illegal) {
+
+ //
+ // This might be illegal because it's a short packet. In that
+ // case, handle it as if it were a short packet and deal with any
+ // other failures when we have the whole packet.
+ //
+
+ if (BytesAvailable != BytesIndicated) {
+ return BowserHandleShortBrowserPacket(Transport->ComputerName,
+ TdiEventContext,
+ SourceAddressLength,
+ SourceAddress,
+ OptionsLength,
+ Options,
+ ReceiveDatagramFlags,
+ BytesAvailable,
+ BytesTaken,
+ IoRequestPacket,
+ BowserIpxDatagramHandler
+ );
+ }
+
+ BowserLogIllegalDatagram( Transport->ComputerName,
+ Smb,
+ (USHORT)(SmbLength & 0xffff),
+ NamePacket->SourceName,
+ ReceiveDatagramFlags);
+ return STATUS_REQUEST_NOT_ACCEPTED;
+
+ } else {
+ PTA_NETBIOS_ADDRESS NetbiosAddress = SourceAddress;
+
+ if (BowserDatagramHandlerTable[Opcode] == NULL) {
+ return STATUS_SUCCESS;
+ }
+
+ //
+ // If this isn't the full packet, post a receive for it and
+ // handle it when we finally complete the receive.
+ //
+
+ if (BytesIndicated != BytesAvailable) {
+ return BowserHandleShortBrowserPacket(Transport->ComputerName,
+ TdiEventContext,
+ SourceAddressLength,
+ SourceAddress,
+ OptionsLength,
+ Options,
+ ReceiveDatagramFlags,
+ BytesAvailable,
+ BytesTaken,
+ IoRequestPacket,
+ BowserIpxDatagramHandler
+ );
+ }
+
+ InternalTransaction = DatagramData;
+
+ //
+ // If this is a workgroup announcement (a server announcement for another
+ // workgroup), handle it specially - regardless of the opcode, it's
+ // really a workgroup announcement.
+ //
+
+ if (NamePacket->NameType == SMB_IPX_NAME_TYPE_BROWSER) {
+
+ if (Opcode == LocalMasterAnnouncement ) {
+
+ NTSTATUS status;
+
+ //
+ // If we're processing these announcements, then handle this
+ // as a domain announcement.
+ //
+
+ if (Transport->MasterBrowser &&
+ Transport->MasterBrowser->ProcessHostAnnouncements) {
+
+ status = BowserHandleIpxDomainAnnouncement(Transport,
+ NamePacket,
+ (PBROWSE_ANNOUNCE_PACKET_1)&InternalTransaction->Union.Announcement,
+ SmbLength-((PCHAR)&InternalTransaction->Union.Announcement - (PCHAR)Smb),
+ ReceiveDatagramFlags);
+ } else {
+ status = STATUS_REQUEST_NOT_ACCEPTED;
+ }
+
+ //
+ // If this request isn't for our domain, we're done with it, if
+ // it's for our domain, then we need to do some more work.
+ //
+
+ if (!RtlEqualMemory(DomainName, NamePacket->Name, SMB_IPX_NAME_LENGTH)) {
+ return status;
+ }
+ } else {
+
+ //
+ // This isn't a master announcement, so ignore it.
+ //
+
+ return STATUS_REQUEST_NOT_ACCEPTED;
+ }
+
+ }
+
+ //
+ // Figure out which transportname is appropriate for the request:
+ //
+ // There are basically 3 choices:
+ //
+ // ComputeName (The default)
+ // MasterBrowser (if this is a server announcement)
+ // PrimaryDomain (if this is a request announcement)
+ // Election (if this is a local master announcement)
+
+ if ((Opcode == WkGroupAnnouncement) ||
+ (Opcode == HostAnnouncement)) {
+ if (Transport->MasterBrowser == NULL ||
+ !Transport->MasterBrowser->ProcessHostAnnouncements) {
+ return STATUS_REQUEST_NOT_ACCEPTED;
+ } else {
+ TransportName = Transport->MasterBrowser;
+ }
+
+ } else if (Opcode == AnnouncementRequest) {
+ TransportName = Transport->PrimaryDomain;
+
+ } else if (Opcode == LocalMasterAnnouncement) {
+ if (Transport->BrowserElection != NULL) {
+ TransportName = Transport->BrowserElection;
+ } else {
+ return STATUS_REQUEST_NOT_ACCEPTED;
+ }
+ }
+
+ ASSERT (DatagramDataSize == (SmbLength - ((PCHAR)InternalTransaction - (PCHAR)Smb)));
+
+ ASSERT (FIELD_OFFSET(INTERNAL_TRANSACTION, Union.Announcement) == FIELD_OFFSET(INTERNAL_TRANSACTION, Union.BrowseAnnouncement));
+ ASSERT (FIELD_OFFSET(INTERNAL_TRANSACTION, Union.Announcement) == FIELD_OFFSET(INTERNAL_TRANSACTION, Union.RequestElection));
+ ASSERT (FIELD_OFFSET(INTERNAL_TRANSACTION, Union.Announcement) == FIELD_OFFSET(INTERNAL_TRANSACTION, Union.BecomeBackup));
+ ASSERT (FIELD_OFFSET(INTERNAL_TRANSACTION, Union.Announcement) == FIELD_OFFSET(INTERNAL_TRANSACTION, Union.GetBackupListRequest));
+ ASSERT (FIELD_OFFSET(INTERNAL_TRANSACTION, Union.Announcement) == FIELD_OFFSET(INTERNAL_TRANSACTION, Union.GetBackupListResp));
+ ASSERT (FIELD_OFFSET(INTERNAL_TRANSACTION, Union.Announcement) == FIELD_OFFSET(INTERNAL_TRANSACTION, Union.ResetState));
+ ASSERT (FIELD_OFFSET(INTERNAL_TRANSACTION, Union.Announcement) == FIELD_OFFSET(INTERNAL_TRANSACTION, Union.MasterAnnouncement));
+
+ return BowserDatagramHandlerTable[Opcode](TransportName,
+ &InternalTransaction->Union.Announcement,
+ SmbLength-((PCHAR)&InternalTransaction->Union.Announcement - (PCHAR)Smb),
+ BytesTaken,
+ SourceAddress,
+ SourceAddressLength,
+ &NamePacket->SourceName,
+ SMB_IPX_NAME_LENGTH,
+ ReceiveDatagramFlags);
+ }
+
+ return STATUS_SUCCESS;
+
+ UNREFERENCED_PARAMETER(OptionsLength);
+ UNREFERENCED_PARAMETER(Options);
+ UNREFERENCED_PARAMETER(ReceiveDatagramFlags);
+}
+
+ NTSTATUS
+BowserHandleIpxDomainAnnouncement(
+ IN PTRANSPORT Transport,
+ IN PSMB_IPX_NAME_PACKET NamePacket,
+ IN PBROWSE_ANNOUNCE_PACKET_1 DomainAnnouncement,
+ IN DWORD RequestLength,
+ IN ULONG ReceiveFlags
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will process receive datagram indication messages, and
+ process them as appropriate.
+
+Arguments:
+
+ IN PTRANSPORT Transport - The transport provider for this request.
+ IN PSMB_IPX_NAME_PACKET NamePacket - The name packet for this request.
+
+Return Value:
+
+ NTSTATUS - Status of operation.
+
+--*/
+{
+ PVIEW_BUFFER ViewBuffer;
+
+ DISCARDABLE_CODE(BowserDiscardableCodeSection);
+
+ ExInterlockedAddLargeStatistic(&BowserStatistics.NumberOfDomainAnnouncements, 1);
+
+ ViewBuffer = BowserAllocateViewBuffer();
+
+ //
+ // If we are unable to allocate a view buffer, ditch this datagram on
+ // the floor.
+ //
+
+ if (ViewBuffer == NULL) {
+ return STATUS_REQUEST_NOT_ACCEPTED;
+ }
+
+ BowserCopyOemComputerName(ViewBuffer->ServerName, NamePacket->Name, SMB_IPX_NAME_LENGTH, ReceiveFlags);
+
+ BowserCopyOemComputerName(ViewBuffer->ServerComment, NamePacket->SourceName, SMB_IPX_NAME_LENGTH, ReceiveFlags);
+
+ if ( DomainAnnouncement->Type & SV_TYPE_NT ) {
+ ViewBuffer->ServerType = SV_TYPE_DOMAIN_ENUM | SV_TYPE_NT;
+ } else {
+ ViewBuffer->ServerType = SV_TYPE_DOMAIN_ENUM;
+ }
+
+ ASSERT (Transport->MasterBrowser != NULL);
+
+ ViewBuffer->TransportName = Transport->MasterBrowser;
+
+ ViewBuffer->ServerVersionMajor = DomainAnnouncement->VersionMajor;
+
+ ViewBuffer->ServerVersionMinor = DomainAnnouncement->VersionMinor;
+
+ ViewBuffer->ServerPeriodicity = (USHORT)((SmbGetUlong(&DomainAnnouncement->Periodicity) + 999) / 1000);
+
+ BowserReferenceTransportName(Transport->MasterBrowser);
+ BowserReferenceTransport( Transport );
+
+ ExInitializeWorkItem(&ViewBuffer->Overlay.WorkHeader, BowserProcessDomainAnnouncement, ViewBuffer);
+
+ ExQueueWorkItem(&ViewBuffer->Overlay.WorkHeader, DelayedWorkQueue);
+
+ return STATUS_SUCCESS;
+}
+