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.

390 lines
14 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. bowtdi.c
  5. Abstract:
  6. This module implements all of the routines that interface with the TDI
  7. transport for NT
  8. Author:
  9. Larry Osterman (LarryO) 21-Jun-1990
  10. Revision History:
  11. 21-Jun-1990 LarryO
  12. Created
  13. --*/
  14. #include "precomp.h"
  15. #include <isnkrnl.h>
  16. #include <smbipx.h>
  17. #pragma hdrstop
  18. NTSTATUS
  19. BowserHandleIpxDomainAnnouncement(
  20. IN PTRANSPORT Transport,
  21. IN PSMB_IPX_NAME_PACKET NamePacket,
  22. IN PBROWSE_ANNOUNCE_PACKET_1 DomainAnnouncement,
  23. IN DWORD RequestLength,
  24. IN ULONG ReceiveFlags
  25. );
  26. #ifdef ALLOC_PRAGMA
  27. #pragma alloc_text(PAGE4BROW, BowserHandleIpxDomainAnnouncement)
  28. #endif
  29. NTSTATUS
  30. BowserIpxDatagramHandler (
  31. IN PVOID TdiEventContext,
  32. IN LONG SourceAddressLength,
  33. IN PVOID SourceAddress,
  34. IN LONG OptionsLength,
  35. IN PVOID Options,
  36. IN ULONG ReceiveDatagramFlags,
  37. IN ULONG BytesIndicated,
  38. IN ULONG BytesAvailable,
  39. OUT ULONG *BytesTaken,
  40. IN PVOID Tsdu,
  41. OUT PIRP *IoRequestPacket
  42. )
  43. {
  44. PVOID DatagramData;
  45. PINTERNAL_TRANSACTION InternalTransaction = NULL;
  46. ULONG DatagramDataSize;
  47. PTRANSPORT Transport = TdiEventContext;
  48. MAILSLOTTYPE Opcode;
  49. PSMB_IPX_NAME_PACKET NamePacket = Tsdu;
  50. PSMB_HEADER Smb = (PSMB_HEADER)(NamePacket+1);
  51. PCHAR ComputerName;
  52. PCHAR DomainName;
  53. PTRANSPORT_NAME TransportName = Transport->ComputerName;
  54. ULONG SmbLength = BytesIndicated - sizeof(SMB_IPX_NAME_PACKET);
  55. if (BytesAvailable > Transport->DatagramSize) {
  56. return STATUS_REQUEST_NOT_ACCEPTED;
  57. }
  58. if (BytesIndicated <= sizeof(SMB_IPX_NAME_PACKET)) {
  59. return STATUS_REQUEST_NOT_ACCEPTED;
  60. }
  61. //
  62. // If we're not fully initialized yet,
  63. // simply ignore the packet.
  64. //
  65. if (Transport->ComputerName == NULL ) {
  66. return STATUS_REQUEST_NOT_ACCEPTED;
  67. }
  68. ComputerName = ((PTA_NETBIOS_ADDRESS)(Transport->ComputerName->TransportAddress.Buffer))->Address[0].Address->NetbiosName;
  69. DomainName = Transport->DomainInfo->DomNetbiosDomainName;
  70. //
  71. // It's not for us, ignore the announcement.
  72. //
  73. if (NamePacket->NameType == SMB_IPX_NAME_TYPE_MACHINE) {
  74. // Mailslot messages are always sent as TYPE_MACHINE even when they're
  75. // to the DomainName (so allow both).
  76. if (!RtlEqualMemory(ComputerName, NamePacket->Name, SMB_IPX_NAME_LENGTH) &&
  77. !RtlEqualMemory(DomainName, NamePacket->Name, SMB_IPX_NAME_LENGTH)) {
  78. return STATUS_REQUEST_NOT_ACCEPTED;
  79. }
  80. } else if (NamePacket->NameType == SMB_IPX_NAME_TYPE_WORKKGROUP) {
  81. if (!RtlEqualMemory(DomainName, NamePacket->Name, SMB_IPX_NAME_LENGTH)) {
  82. return STATUS_REQUEST_NOT_ACCEPTED;
  83. }
  84. } else if (NamePacket->NameType != SMB_IPX_NAME_TYPE_BROWSER) {
  85. return STATUS_REQUEST_NOT_ACCEPTED;
  86. }
  87. //
  88. // Classify the incoming packet according to it's type. Depending on
  89. // the type, either process it as:
  90. //
  91. // 1) A server announcement
  92. // 2) An incoming mailslot
  93. //
  94. Opcode = BowserClassifyIncomingDatagram(Smb, SmbLength,
  95. &DatagramData,
  96. &DatagramDataSize);
  97. if (Opcode == MailslotTransaction) {
  98. //
  99. // BowserHandleMailslotTransaction will always receive the indicated bytes
  100. // expecting to find the SMB. Tell the TDI driver we've already consumed
  101. // the IPX_NAME_PACKET to keep that assumption constant.
  102. //
  103. *BytesTaken = sizeof(SMB_IPX_NAME_PACKET);
  104. return BowserHandleMailslotTransaction(
  105. Transport->ComputerName,
  106. NamePacket->SourceName,
  107. 0, // No IP address
  108. sizeof(SMB_IPX_NAME_PACKET), // SMB offset into TSDU
  109. ReceiveDatagramFlags,
  110. BytesIndicated,
  111. BytesAvailable,
  112. BytesTaken,
  113. Tsdu,
  114. IoRequestPacket );
  115. } else if (Opcode == Illegal) {
  116. //
  117. // This might be illegal because it's a short packet. In that
  118. // case, handle it as if it were a short packet and deal with any
  119. // other failures when we have the whole packet.
  120. //
  121. if (BytesAvailable != BytesIndicated) {
  122. return BowserHandleShortBrowserPacket(Transport->ComputerName,
  123. TdiEventContext,
  124. SourceAddressLength,
  125. SourceAddress,
  126. OptionsLength,
  127. Options,
  128. ReceiveDatagramFlags,
  129. BytesAvailable,
  130. BytesTaken,
  131. IoRequestPacket,
  132. BowserIpxDatagramHandler
  133. );
  134. }
  135. BowserLogIllegalDatagram( Transport->ComputerName,
  136. Smb,
  137. (USHORT)(SmbLength & 0xffff),
  138. NamePacket->SourceName,
  139. ReceiveDatagramFlags);
  140. return STATUS_REQUEST_NOT_ACCEPTED;
  141. } else {
  142. // PTA_NETBIOS_ADDRESS NetbiosAddress = SourceAddress;
  143. if (BowserDatagramHandlerTable[Opcode] == NULL) {
  144. return STATUS_SUCCESS;
  145. }
  146. //
  147. // If this isn't the full packet, post a receive for it and
  148. // handle it when we finally complete the receive.
  149. //
  150. if (BytesIndicated != BytesAvailable) {
  151. return BowserHandleShortBrowserPacket(Transport->ComputerName,
  152. TdiEventContext,
  153. SourceAddressLength,
  154. SourceAddress,
  155. OptionsLength,
  156. Options,
  157. ReceiveDatagramFlags,
  158. BytesAvailable,
  159. BytesTaken,
  160. IoRequestPacket,
  161. BowserIpxDatagramHandler
  162. );
  163. }
  164. InternalTransaction = DatagramData;
  165. //
  166. // If this is a workgroup announcement (a server announcement for another
  167. // workgroup), handle it specially - regardless of the opcode, it's
  168. // really a workgroup announcement.
  169. //
  170. if (NamePacket->NameType == SMB_IPX_NAME_TYPE_BROWSER) {
  171. if (Opcode == LocalMasterAnnouncement ) {
  172. NTSTATUS status;
  173. //
  174. // If we're processing these announcements, then handle this
  175. // as a domain announcement.
  176. //
  177. if (Transport->MasterBrowser &&
  178. Transport->MasterBrowser->ProcessHostAnnouncements) {
  179. status = BowserHandleIpxDomainAnnouncement(Transport,
  180. NamePacket,
  181. (PBROWSE_ANNOUNCE_PACKET_1)&InternalTransaction->Union.Announcement,
  182. SmbLength-(ULONG)((PCHAR)&InternalTransaction->Union.Announcement - (PCHAR)Smb),
  183. ReceiveDatagramFlags);
  184. } else {
  185. status = STATUS_REQUEST_NOT_ACCEPTED;
  186. }
  187. //
  188. // If this request isn't for our domain, we're done with it, if
  189. // it's for our domain, then we need to do some more work.
  190. //
  191. if (!RtlEqualMemory(DomainName, NamePacket->Name, SMB_IPX_NAME_LENGTH)) {
  192. return status;
  193. }
  194. } else {
  195. //
  196. // This isn't a master announcement, so ignore it.
  197. //
  198. return STATUS_REQUEST_NOT_ACCEPTED;
  199. }
  200. }
  201. //
  202. // Figure out which transportname is appropriate for the request:
  203. //
  204. // There are basically 3 choices:
  205. //
  206. // ComputeName (The default)
  207. // MasterBrowser (if this is a server announcement)
  208. // PrimaryDomain (if this is a request announcement)
  209. // Election (if this is a local master announcement)
  210. if ((Opcode == WkGroupAnnouncement) ||
  211. (Opcode == HostAnnouncement)) {
  212. if (Transport->MasterBrowser == NULL ||
  213. !Transport->MasterBrowser->ProcessHostAnnouncements) {
  214. return STATUS_REQUEST_NOT_ACCEPTED;
  215. } else {
  216. TransportName = Transport->MasterBrowser;
  217. }
  218. } else if (Opcode == AnnouncementRequest) {
  219. TransportName = Transport->PrimaryDomain;
  220. } else if (Opcode == LocalMasterAnnouncement) {
  221. if (Transport->BrowserElection != NULL) {
  222. TransportName = Transport->BrowserElection;
  223. } else {
  224. return STATUS_REQUEST_NOT_ACCEPTED;
  225. }
  226. }
  227. ASSERT (DatagramDataSize == (SmbLength - ((PCHAR)InternalTransaction - (PCHAR)Smb)));
  228. ASSERT (FIELD_OFFSET(INTERNAL_TRANSACTION, Union.Announcement) == FIELD_OFFSET(INTERNAL_TRANSACTION, Union.BrowseAnnouncement));
  229. ASSERT (FIELD_OFFSET(INTERNAL_TRANSACTION, Union.Announcement) == FIELD_OFFSET(INTERNAL_TRANSACTION, Union.RequestElection));
  230. ASSERT (FIELD_OFFSET(INTERNAL_TRANSACTION, Union.Announcement) == FIELD_OFFSET(INTERNAL_TRANSACTION, Union.BecomeBackup));
  231. ASSERT (FIELD_OFFSET(INTERNAL_TRANSACTION, Union.Announcement) == FIELD_OFFSET(INTERNAL_TRANSACTION, Union.GetBackupListRequest));
  232. ASSERT (FIELD_OFFSET(INTERNAL_TRANSACTION, Union.Announcement) == FIELD_OFFSET(INTERNAL_TRANSACTION, Union.GetBackupListResp));
  233. ASSERT (FIELD_OFFSET(INTERNAL_TRANSACTION, Union.Announcement) == FIELD_OFFSET(INTERNAL_TRANSACTION, Union.ResetState));
  234. ASSERT (FIELD_OFFSET(INTERNAL_TRANSACTION, Union.Announcement) == FIELD_OFFSET(INTERNAL_TRANSACTION, Union.MasterAnnouncement));
  235. return BowserDatagramHandlerTable[Opcode](TransportName,
  236. &InternalTransaction->Union.Announcement,
  237. SmbLength-(ULONG)((PCHAR)&InternalTransaction->Union.Announcement - (PCHAR)Smb),
  238. BytesTaken,
  239. SourceAddress,
  240. SourceAddressLength,
  241. &NamePacket->SourceName,
  242. SMB_IPX_NAME_LENGTH,
  243. ReceiveDatagramFlags);
  244. }
  245. return STATUS_SUCCESS;
  246. UNREFERENCED_PARAMETER(OptionsLength);
  247. UNREFERENCED_PARAMETER(Options);
  248. UNREFERENCED_PARAMETER(ReceiveDatagramFlags);
  249. }
  250. NTSTATUS
  251. BowserHandleIpxDomainAnnouncement(
  252. IN PTRANSPORT Transport,
  253. IN PSMB_IPX_NAME_PACKET NamePacket,
  254. IN PBROWSE_ANNOUNCE_PACKET_1 DomainAnnouncement,
  255. IN DWORD RequestLength,
  256. IN ULONG ReceiveFlags
  257. )
  258. /*++
  259. Routine Description:
  260. This routine will process receive datagram indication messages, and
  261. process them as appropriate.
  262. Arguments:
  263. IN PTRANSPORT Transport - The transport provider for this request.
  264. IN PSMB_IPX_NAME_PACKET NamePacket - The name packet for this request.
  265. Return Value:
  266. NTSTATUS - Status of operation.
  267. --*/
  268. {
  269. PVIEW_BUFFER ViewBuffer;
  270. DISCARDABLE_CODE(BowserDiscardableCodeSection);
  271. #ifdef ENABLE_PSEUDO_BROWSER
  272. if ( BowserData.PseudoServerLevel == BROWSER_PSEUDO ) {
  273. // no-op for black hole server
  274. return STATUS_SUCCESS;
  275. }
  276. #endif
  277. ExInterlockedAddLargeStatistic(&BowserStatistics.NumberOfDomainAnnouncements, 1);
  278. ViewBuffer = BowserAllocateViewBuffer();
  279. //
  280. // If we are unable to allocate a view buffer, ditch this datagram on
  281. // the floor.
  282. //
  283. if (ViewBuffer == NULL) {
  284. return STATUS_REQUEST_NOT_ACCEPTED;
  285. }
  286. BowserCopyOemComputerName(ViewBuffer->ServerName, NamePacket->Name, SMB_IPX_NAME_LENGTH, ReceiveFlags);
  287. BowserCopyOemComputerName(ViewBuffer->ServerComment, NamePacket->SourceName, SMB_IPX_NAME_LENGTH, ReceiveFlags);
  288. if ( DomainAnnouncement->Type & SV_TYPE_NT ) {
  289. ViewBuffer->ServerType = SV_TYPE_DOMAIN_ENUM | SV_TYPE_NT;
  290. } else {
  291. ViewBuffer->ServerType = SV_TYPE_DOMAIN_ENUM;
  292. }
  293. ASSERT (Transport->MasterBrowser != NULL);
  294. ViewBuffer->TransportName = Transport->MasterBrowser;
  295. ViewBuffer->ServerVersionMajor = DomainAnnouncement->VersionMajor;
  296. ViewBuffer->ServerVersionMinor = DomainAnnouncement->VersionMinor;
  297. ViewBuffer->ServerPeriodicity = (USHORT)((SmbGetUlong(&DomainAnnouncement->Periodicity) + 999) / 1000);
  298. BowserReferenceTransportName(Transport->MasterBrowser);
  299. BowserReferenceTransport( Transport );
  300. ExInitializeWorkItem(&ViewBuffer->Overlay.WorkHeader, BowserProcessDomainAnnouncement, ViewBuffer);
  301. BowserQueueDelayedWorkItem( &ViewBuffer->Overlay.WorkHeader );
  302. return STATUS_SUCCESS;
  303. }