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.

6068 lines
208 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. ind.c
  5. Abstract:
  6. This module contains code which implements the indication handler
  7. for the IPX transport provider.
  8. Environment:
  9. Kernel mode
  10. Revision History:
  11. Sanjay Anand (SanjayAn) 3-Oct-1995
  12. Changes to support transfer of buffer ownership to transports
  13. 1. Added IpxReceivePacket which receives buffers that can be owned
  14. 2. Changed IpxReceiveIndication to call a new function IpxReceiveIndicationCommon
  15. which takes an extra parameter to indicate whether this is a chained receive or
  16. not.
  17. 3. Changed IpxProcessDatagram to take the MDL ptr to indicate chained receive,
  18. a client count and the headerbuffersize as params.
  19. Sanjay Anand (SanjayAn) 27-Oct-1995
  20. Changes to support Plug and Play
  21. --*/
  22. #include "precomp.h"
  23. #pragma hdrstop
  24. #include "isnnb.h"
  25. UINT
  26. IpxGetChainedMDLLength( PNDIS_BUFFER pMDL ) {
  27. UINT size = 0;
  28. if (pMDL != NULL) {
  29. do {
  30. size += NdisBufferLength(pMDL);
  31. pMDL = NDIS_BUFFER_LINKAGE(pMDL);
  32. } while (pMDL != NULL);
  33. }
  34. return size;
  35. }
  36. //
  37. // This is declared here so it will be in the same function
  38. // as IpxReceiveIndication and we can inline it.
  39. //
  40. #if defined(_M_IX86)
  41. _inline
  42. #endif
  43. VOID
  44. IpxProcessDatagram(
  45. IN PDEVICE Device,
  46. IN PADAPTER Adapter,
  47. IN PBINDING Binding,
  48. IN NDIS_HANDLE MacReceiveContext,
  49. IN PIPX_DATAGRAM_OPTIONS DatagramOptions,
  50. IN PUCHAR LookaheadBuffer,
  51. IN UINT LookaheadBufferSize,
  52. IN UINT LookaheadBufferOffset,
  53. IN UINT PacketSize,
  54. IN BOOLEAN Broadcast,
  55. IN PINT pTdiClientCount,
  56. IN UINT HeaderBufferSize,
  57. IN PMDL pMdl,
  58. IN NDIS_HANDLE BindingContext
  59. )
  60. /*++
  61. Routine Description:
  62. This routing handles incoming IPX datagrams.
  63. Arguments:
  64. Device - The IPX device.
  65. Adapter - The adapter the frame was received on.
  66. Binding - The binding of the adapter it was received on.
  67. MacReceiveContext - The context to use when calling
  68. NdisTransferData.
  69. DatagramOptions - Contains the datagram options, which
  70. consists of room for the packet type, padding, and
  71. the local target of the remote the frame was received from.
  72. LookaheadBuffer - The lookahead data.
  73. LookaheadBufferSize - The length of the lookahead data.
  74. LookaheadBufferOffset - The offset to add when calling
  75. NdisTransferData.
  76. PacketSize - The length of the packet, starting at the IPX
  77. header.
  78. Broadcast - TRUE if the packet was broadcast.
  79. pTdiClientCount - to return count of the number of TDI clients above us
  80. so NDIS can obtain that many ref counts on the buffer.
  81. HeaderBufferSize - the size of the MAC header buffer - used to determine
  82. the offsets into the TSDU.
  83. pMdl - Mdl chain pointer - non-NULL if chained receive
  84. BindingContext - In case of loopback, this contains IPX_LOOPBACK_COOKIE
  85. Return Value:
  86. NTSTATUS - status of operation.
  87. --*/
  88. {
  89. PIPX_HEADER IpxHeader = (PIPX_HEADER)LookaheadBuffer;
  90. PADDRESS Address;
  91. PADDRESS_FILE AddressFile;
  92. PADDRESS_FILE ReferencedAddressFile;
  93. PREQUEST Request;
  94. PIPX_RECEIVE_BUFFER ReceiveBuffer;
  95. PTDI_CONNECTION_INFORMATION DatagramInformation;
  96. TDI_ADDRESS_IPX UNALIGNED * DatagramAddress;
  97. ULONG IndicateBytesCopied;
  98. IPX_ADDRESS_EXTENDED_FLAGS SourceAddress;
  99. ULONG SourceAddressLength;
  100. ULONG RequestCount;
  101. PNDIS_BUFFER NdisBuffer;
  102. NDIS_STATUS NdisStatus;
  103. NTSTATUS Status;
  104. PIRP Irp;
  105. UINT ByteOffset, BytesToTransfer;
  106. ULONG BytesTransferred;
  107. BOOLEAN LastAddressFile;
  108. ULONG IndicateOffset;
  109. PNDIS_PACKET ReceivePacket;
  110. PIPX_RECEIVE_RESERVED Reserved;
  111. PLIST_ENTRY p, q;
  112. PSLIST_ENTRY s;
  113. USHORT DestinationSocket;
  114. USHORT SourceSocket;
  115. ULONG Hash;
  116. IPX_DEFINE_LOCK_HANDLE (LockHandle)
  117. PIPX_DATAGRAM_OPTIONS2 Options2;
  118. BOOLEAN RtProc = FALSE;
  119. UINT LookaheadBufferOffsetCopy = LookaheadBufferOffset;
  120. //
  121. // First scan the device's address database, looking for
  122. // the destination socket of this frame.
  123. //
  124. DestinationSocket = *(USHORT UNALIGNED *)&IpxHeader->DestinationSocket;
  125. IPX_GET_LOCK (&Device->Lock, &LockHandle);
  126. if ((Address = Device->LastAddress) &&
  127. (Address->Socket == DestinationSocket)) {
  128. //
  129. // Device->LastAddress cannot be stopping, so
  130. // we use it.
  131. //
  132. IpxReferenceAddressLock (Address, AREF_RECEIVE);
  133. IPX_FREE_LOCK (&Device->Lock, LockHandle);
  134. goto FoundAddress;
  135. }
  136. Hash = IPX_DEST_SOCKET_HASH (IpxHeader);
  137. for (p = Device->AddressDatabases[Hash].Flink;
  138. p != &Device->AddressDatabases[Hash];
  139. p = p->Flink) {
  140. Address = CONTAINING_RECORD (p, ADDRESS, Linkage);
  141. if ((Address->Socket == DestinationSocket) &&
  142. (!Address->Stopping)) {
  143. IpxReferenceAddressLock (Address, AREF_RECEIVE);
  144. Device->LastAddress = Address;
  145. IPX_FREE_LOCK (&Device->Lock, LockHandle);
  146. goto FoundAddress;
  147. }
  148. }
  149. IPX_FREE_LOCK (&Device->Lock, LockHandle);
  150. //
  151. // If we had found an address we would have jumped
  152. // past here.
  153. //
  154. #ifdef SNMP
  155. ++IPX_MIB_ENTRY(Device, SysInUnknownSockets);
  156. #endif SNMP
  157. return;
  158. FoundAddress:
  159. SourceSocket = *(USHORT UNALIGNED *)&IpxHeader->SourceSocket;
  160. IpxBuildTdiAddress(
  161. &SourceAddress.IpxAddress,
  162. (*(ULONG UNALIGNED *)(IpxHeader->SourceNetwork) == 0) ?
  163. Binding->LocalAddress.NetworkAddress :
  164. *(UNALIGNED ULONG *)(IpxHeader->SourceNetwork),
  165. IpxHeader->SourceNode,
  166. SourceSocket);
  167. DatagramOptions->PacketType = IpxHeader->PacketType;
  168. //
  169. // Now that we have found the address, scan its list of
  170. // address files for clients that want this datagram.
  171. //
  172. // If we have to release the address lock to indicate to
  173. // a client, we reference the current address file. If
  174. // we get an IRP we transfer the reference to that;
  175. // otherwise we store the address file in ReferencedAddressFile
  176. // and deref it the next time we release the lock.
  177. //
  178. ReferencedAddressFile = NULL;
  179. RequestCount = 0;
  180. // ++Device->TempDatagramsReceived;
  181. // Device->TempDatagramBytesReceived += (PacketSize - sizeof(IPX_HEADER));
  182. Device->Statistics.DatagramsReceived++;
  183. ADD_TO_LARGE_INTEGER(
  184. &Device->Statistics.DatagramBytesReceived,
  185. PacketSize - sizeof(IPX_HEADER));
  186. //
  187. // If LastAddressFile is TRUE, it means we did an indication
  188. // to the client on the last address file in the address'
  189. // list, and we did not reacquire the lock when we were
  190. // done.
  191. //
  192. LastAddressFile = FALSE;
  193. IPX_GET_LOCK (&Address->Lock, &LockHandle);
  194. //
  195. // If this is RtAdd, skip the entire body
  196. //
  197. if (!Address->RtAdd)
  198. {
  199. for (p = Address->AddressFileDatabase.Flink;
  200. p != &Address->AddressFileDatabase;
  201. p = p->Flink) {
  202. AddressFile = CONTAINING_RECORD (p, ADDRESS_FILE, Linkage);
  203. if (AddressFile->State != ADDRESSFILE_STATE_OPEN) {
  204. continue; // next address file
  205. }
  206. //
  207. // Set these to the common values, then change them.
  208. //
  209. SourceAddressLength = sizeof(TA_IPX_ADDRESS);
  210. IndicateOffset = sizeof(IPX_HEADER);
  211. if (AddressFile->SpecialReceiveProcessing) {
  212. //
  213. // On dial out lines, we don't indicate packets to
  214. // the SAP socket if DisableDialoutSap is set.
  215. //
  216. //
  217. // [FW] no need to check if the FWD is bound
  218. //
  219. if (!Device->ForwarderBound &&
  220. (AddressFile->IsSapSocket) &&
  221. (Binding->DialOutAsync) &&
  222. (Device->DisableDialoutSap || Device->SingleNetworkActive)) {
  223. //
  224. // Go to the next address file (although it will
  225. // likely fail this test too).
  226. //
  227. continue;
  228. }
  229. //
  230. // Set this, since generally we want it.
  231. //
  232. SourceAddress.PacketType = IpxHeader->PacketType;
  233. //
  234. // See if we fail a packet type filter.
  235. //
  236. if (AddressFile->FilterOnPacketType) {
  237. if (AddressFile->FilteredType != IpxHeader->PacketType) {
  238. continue;
  239. }
  240. }
  241. //
  242. // Calculate how long the addresses expected are.
  243. //
  244. if (AddressFile->ReceiveFlagsAddressing ||
  245. AddressFile->ExtendedAddressing) {
  246. SourceAddress.Flags = 0;
  247. if (Broadcast) {
  248. SourceAddress.Flags = IPX_EXTENDED_FLAG_BROADCAST;
  249. }
  250. if (IpxIsAddressLocal((TDI_ADDRESS_IPX UNALIGNED *)
  251. &SourceAddress.IpxAddress.Address[0].Address[0])) {
  252. SourceAddress.Flags |= IPX_EXTENDED_FLAG_LOCAL;
  253. }
  254. SourceAddressLength = sizeof(IPX_ADDRESS_EXTENDED_FLAGS);
  255. SourceAddress.IpxAddress.Address[0].AddressLength +=
  256. (sizeof(IPX_ADDRESS_EXTENDED_FLAGS) - sizeof(TA_IPX_ADDRESS));
  257. }
  258. //
  259. // Determine how much of the packet the client wants.
  260. //
  261. if (AddressFile->ReceiveIpxHeader) {
  262. IndicateOffset = 0;
  263. }
  264. }
  265. //
  266. // First scan the address' receive datagram queue
  267. // for datagrams that match. We do a quick check
  268. // to see if the list is empty.
  269. //
  270. q = AddressFile->ReceiveDatagramQueue.Flink;
  271. if (q != &AddressFile->ReceiveDatagramQueue) {
  272. do {
  273. Request = LIST_ENTRY_TO_REQUEST(q);
  274. DatagramInformation =
  275. ((PTDI_REQUEST_KERNEL_RECEIVEDG)(REQUEST_PARAMETERS(Request)))->
  276. ReceiveDatagramInformation;
  277. if ((DatagramInformation != NULL) &&
  278. (DatagramInformation->RemoteAddress != NULL) &&
  279. (DatagramAddress = IpxParseTdiAddress(DatagramInformation->RemoteAddress)) &&
  280. (DatagramAddress->Socket != SourceSocket)) {
  281. //
  282. // The address that this datagram is looking for is
  283. // not satisfied by this frame.
  284. //
  285. // Speed this up; worry about node and network?
  286. //
  287. q = q->Flink;
  288. continue; // next receive datagram on this address file
  289. } else {
  290. //
  291. // We found a datagram on the queue.
  292. //
  293. IPX_DEBUG (RECEIVE, ("Found RDG on %lx\n", AddressFile));
  294. RemoveEntryList (q);
  295. REQUEST_INFORMATION(Request) = 0;
  296. goto HandleDatagram;
  297. }
  298. } while (q != &AddressFile->ReceiveDatagramQueue);
  299. }
  300. //
  301. // If we found a datagram we would have jumped past here,
  302. // so looking for a datagram failed; see if the
  303. // client has a receive datagram handler registered.
  304. //
  305. //
  306. // Look for the chained receive handler if the MDL is not NULL
  307. //
  308. if (pMdl && AddressFile->RegisteredChainedReceiveDatagramHandler) {
  309. // Set to original value when this function was initially called.
  310. LookaheadBufferOffset = LookaheadBufferOffsetCopy;
  311. //
  312. // Chained receive both above and below => we indicate the entire MDL up.
  313. // Offset the LookaheadBuffer by the size of the MAC header.
  314. //
  315. LookaheadBufferOffset += HeaderBufferSize;
  316. IpxReferenceAddressFileLock (AddressFile, AFREF_INDICATION);
  317. //
  318. // Set this so we can exit without reacquiring
  319. // the lock.
  320. //
  321. if (p == &Address->AddressFileDatabase) {
  322. LastAddressFile = TRUE;
  323. }
  324. IndicateBytesCopied = 0;
  325. IPX_FREE_LOCK (&Address->Lock, LockHandle);
  326. if (ReferencedAddressFile) {
  327. IpxDereferenceAddressFileSync (ReferencedAddressFile, AFREF_INDICATION);
  328. ReferencedAddressFile = NULL;
  329. }
  330. IPX_DEBUG(RECEIVE, ("AddressFile (%p) ChainedIndicate RecvLen: %d, StartOffset: %d, Tsdu: %lx\n",
  331. AddressFile, PacketSize - IndicateOffset, IndicateOffset+LookaheadBufferOffset, pMdl));
  332. //
  333. // Will return SUCCESS if the client did not take ownership of the Tsdu
  334. // PENDING if the client took ownership and will free it later (using TdiFreeReceiveChain).
  335. // DATA_NOT_ACCEPTED if the client did not take ownership and did not copy the data.
  336. //
  337. //
  338. // Since NDIS needs an array of PNDIS_PACKETs when the TDI client returns this packet,
  339. // we pass the Packet as the ReceiveContext here. The TDI client will pass in the address
  340. // of this context on a ReturnPacket.
  341. // Also, NDIS needs the PacketArray (not to be confused with the array of packetptrs. mentioned
  342. // above) on an NdisTransferData call. These clients dont do this, but other clients like
  343. // NB, SPX, RIP or TDI clients that do not have this new interface, can call NdisTransferData
  344. // so we pass in the PacketArray as a parameter to them.
  345. //
  346. Status = (*AddressFile->ChainedReceiveDatagramHandler)(
  347. AddressFile->ChainedReceiveDatagramHandlerContext,
  348. SourceAddressLength,
  349. &SourceAddress,
  350. sizeof(IPX_DATAGRAM_OPTIONS),
  351. DatagramOptions,
  352. Adapter->MacInfo.CopyLookahead, // TdiRcvFlags|Adapter->MacInfo.CopyLookahead, Receive datagram flags
  353. PacketSize - IndicateOffset, // ReceiveLength
  354. IndicateOffset+LookaheadBufferOffset, // StartingOffset
  355. pMdl, // Tsdu - MDL chain
  356. (PNDIS_PACKET)MacReceiveContext); // TransportContext - pointer to the packet
  357. if (Status != STATUS_DATA_NOT_ACCEPTED) {
  358. if (Status == STATUS_PENDING) {
  359. //
  360. // We assume here that the client referenced the packet which will
  361. // be removed when the packet is freed.
  362. // Increment the Tdi client count
  363. //
  364. (*pTdiClientCount)++;
  365. }
  366. //
  367. // The handler accepted the data or did not
  368. // return an IRP; in either case there is
  369. // nothing else to do, so go to the next
  370. // address file.
  371. //
  372. ReferencedAddressFile = AddressFile;
  373. if (!LastAddressFile) {
  374. IPX_GET_LOCK (&Address->Lock, &LockHandle);
  375. continue;
  376. } else {
  377. //
  378. // In this case we have no cleanup, so just leave
  379. // if there are no datagrams pending.
  380. //
  381. // RequestCount should always be 0 here.
  382. //
  383. //if (RequestCount == 0) {
  384. // return;
  385. //}
  386. goto BreakWithoutLock;
  387. }
  388. } else {
  389. //
  390. // Since no IRP can be returned here, we continue to the next addressfile
  391. //
  392. ReferencedAddressFile = AddressFile;
  393. if (!LastAddressFile) {
  394. IPX_GET_LOCK (&Address->Lock, &LockHandle);
  395. continue;
  396. } else {
  397. //
  398. // In this case we have no cleanup, so just leave
  399. // if there are no datagrams pending.
  400. //
  401. //if (RequestCount == 0) {
  402. // return;
  403. //}
  404. goto BreakWithoutLock;
  405. }
  406. }
  407. } else if (AddressFile->RegisteredReceiveDatagramHandler) {
  408. IpxReferenceAddressFileLock (AddressFile, AFREF_INDICATION);
  409. //
  410. // Set this so we can exit without reacquiring
  411. // the lock.
  412. //
  413. if (p == &Address->AddressFileDatabase) {
  414. LastAddressFile = TRUE;
  415. }
  416. IPX_FREE_LOCK (&Address->Lock, LockHandle);
  417. if (ReferencedAddressFile) {
  418. IpxDereferenceAddressFileSync (ReferencedAddressFile, AFREF_INDICATION);
  419. ReferencedAddressFile = NULL;
  420. }
  421. IndicateBytesCopied = 0;
  422. if (PacketSize > LookaheadBufferSize) {
  423. IPX_DEBUG(RECEIVE, ("Indicate %d/%d to %lx on %lx\n",
  424. LookaheadBufferSize, PacketSize,
  425. AddressFile->ReceiveDatagramHandler, AddressFile));
  426. }
  427. Status = (*AddressFile->ReceiveDatagramHandler)(
  428. AddressFile->ReceiveDatagramHandlerContext,
  429. SourceAddressLength,
  430. &SourceAddress,
  431. sizeof(IPX_DATAGRAM_OPTIONS),
  432. DatagramOptions,
  433. Adapter->MacInfo.CopyLookahead,
  434. LookaheadBufferSize - IndicateOffset, // indicated
  435. PacketSize - IndicateOffset, // available
  436. &IndicateBytesCopied, // taken
  437. LookaheadBuffer + IndicateOffset, // data
  438. &Irp);
  439. if (Status != STATUS_MORE_PROCESSING_REQUIRED) {
  440. //
  441. // The handler accepted the data or did not
  442. // return an IRP; in either case there is
  443. // nothing else to do, so go to the next
  444. // address file.
  445. //
  446. ReferencedAddressFile = AddressFile;
  447. if (!LastAddressFile) {
  448. IPX_GET_LOCK (&Address->Lock, &LockHandle);
  449. continue;
  450. } else {
  451. //
  452. // In this case we have no cleanup, so just leave
  453. // if there are no datagrams pending.
  454. //
  455. if (RequestCount == 0) {
  456. return;
  457. }
  458. goto BreakWithoutLock;
  459. }
  460. } else {
  461. //
  462. // The client returned an IRP.
  463. //
  464. IPX_DEBUG (RECEIVE, ("Indicate IRP %lx, taken %d\n", Irp, IndicateBytesCopied));
  465. Request = IpxAllocateRequest (Device, Irp);
  466. IF_NOT_ALLOCATED(Request) {
  467. Irp->IoStatus.Information = 0;
  468. Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  469. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  470. ReferencedAddressFile = AddressFile;
  471. IPX_GET_LOCK (&Address->Lock, &LockHandle);
  472. continue;
  473. }
  474. if (!LastAddressFile) {
  475. IPX_GET_LOCK (&Address->Lock, &LockHandle);
  476. }
  477. #if DBG
  478. //
  479. // Make sure the IRP file object is right.
  480. //
  481. if (IoGetCurrentIrpStackLocation(Irp)->FileObject->FsContext != AddressFile) {
  482. DbgPrint ("IRP %lx does not match AF %lx, H %lx C %lx\n",
  483. Irp, AddressFile,
  484. AddressFile->ReceiveDatagramHandler,
  485. AddressFile->ReceiveDatagramHandlerContext);
  486. DbgBreakPoint();
  487. }
  488. #endif
  489. //
  490. // Set up the information field so we know
  491. // how much to skip in it.
  492. //
  493. IpxTransferReferenceAddressFile (AddressFile, AFREF_INDICATION, AFREF_RCV_DGRAM);
  494. REQUEST_INFORMATION(Request) = IndicateBytesCopied;
  495. //
  496. // Fall out of the if and continue via
  497. // HandleDatagram...
  498. //
  499. }
  500. } else {
  501. //
  502. // No posted datagram, no handler; go to the next
  503. // address file.
  504. //
  505. continue; // next address file
  506. }
  507. HandleDatagram:
  508. //
  509. // At this point, Request is set to the request
  510. // that will hold for this address file, and
  511. // REQUEST_INFORMATION() is the offset to start
  512. // the transfer at.
  513. //
  514. //
  515. // First copy over the source address while it is handy.
  516. //
  517. DatagramInformation =
  518. ((PTDI_REQUEST_KERNEL_RECEIVEDG)(REQUEST_PARAMETERS(Request)))->
  519. ReturnDatagramInformation;
  520. if (DatagramInformation != NULL) {
  521. RtlCopyMemory(
  522. DatagramInformation->RemoteAddress,
  523. &SourceAddress,
  524. (ULONG)DatagramInformation->RemoteAddressLength < SourceAddressLength ?
  525. DatagramInformation->RemoteAddressLength : SourceAddressLength);
  526. RtlCopyMemory(
  527. DatagramInformation->Options,
  528. &DatagramOptions,
  529. (ULONG)DatagramInformation->OptionsLength < sizeof(IPX_DATAGRAM_OPTIONS) ?
  530. DatagramInformation->OptionsLength : sizeof(IPX_DATAGRAM_OPTIONS));
  531. }
  532. //
  533. // Now check if this is the first request that will
  534. // take the data, otherwise queue it up.
  535. //
  536. if (RequestCount == 0) {
  537. //
  538. // First one; we need to allocate a packet for the transfer.
  539. //
  540. //if (Address->ReceivePacketInUse) {
  541. if (InterlockedExchangeAdd(&Address->ReceivePacketInUse, 0) != 0) {
  542. //
  543. // Need a packet, check the pool.
  544. //
  545. s = IpxPopReceivePacket (Device);
  546. if (s == NULL) {
  547. //
  548. // None in pool, fail the request.
  549. //
  550. REQUEST_INFORMATION(Request) = 0;
  551. REQUEST_STATUS(Request) = STATUS_INSUFFICIENT_RESOURCES;
  552. IPX_INSERT_TAIL_LIST(
  553. &Adapter->RequestCompletionQueue,
  554. REQUEST_LINKAGE(Request),
  555. Adapter->DeviceLock);
  556. if (!LastAddressFile) {
  557. continue;
  558. } else {
  559. goto BreakWithoutLock;
  560. }
  561. }
  562. Reserved = CONTAINING_RECORD (s, IPX_RECEIVE_RESERVED, PoolLinkage);
  563. ReceivePacket = CONTAINING_RECORD (Reserved, NDIS_PACKET, ProtocolReserved[0]);
  564. } else {
  565. // Address->ReceivePacketInUse = TRUE;
  566. InterlockedIncrement(&Address->ReceivePacketInUse);
  567. ReceivePacket = PACKET(&Address->ReceivePacket);
  568. Reserved = RECEIVE_RESERVED(&Address->ReceivePacket);
  569. }
  570. CTEAssert (IsListEmpty(&Reserved->Requests));
  571. Reserved->SingleRequest = Request;
  572. NdisBuffer = REQUEST_NDIS_BUFFER(Request);
  573. #ifdef SUNDOWN
  574. // NdisCopyFromPacketToPacket and NdisTransferData only takes UINT
  575. ByteOffset = (UINT) (REQUEST_INFORMATION(Request)) + LookaheadBufferOffset + IndicateOffset;
  576. #else
  577. ByteOffset = REQUEST_INFORMATION(Request) + LookaheadBufferOffset + IndicateOffset;
  578. #endif
  579. BytesToTransfer =
  580. ((PTDI_REQUEST_KERNEL_RECEIVEDG)(REQUEST_PARAMETERS(Request)))->ReceiveLength;
  581. if (BytesToTransfer == 0) {
  582. BytesToTransfer = IpxGetChainedMDLLength(NdisBuffer);
  583. IPX_DEBUG(RECEIVE, ("0 length in IRP, Use entire MDL buffer size %d\n", BytesToTransfer));
  584. }
  585. if (BytesToTransfer > (PacketSize - IndicateOffset)) {
  586. BytesToTransfer = PacketSize - IndicateOffset;
  587. }
  588. } else {
  589. if (RequestCount == 1) {
  590. //
  591. // There is already one request. We need to
  592. // allocate a buffer.
  593. //
  594. s = IpxPopReceiveBuffer (Adapter);
  595. if (s == NULL) {
  596. //
  597. // No buffers, fail the request.
  598. //
  599. // Should we fail the transfer for the first request too?
  600. //
  601. REQUEST_INFORMATION(Request) = 0;
  602. REQUEST_STATUS(Request) = STATUS_INSUFFICIENT_RESOURCES;
  603. IPX_INSERT_TAIL_LIST(
  604. &Adapter->RequestCompletionQueue,
  605. REQUEST_LINKAGE(Request),
  606. Adapter->DeviceLock);
  607. if (!LastAddressFile) {
  608. continue;
  609. } else {
  610. goto BreakWithoutLock;
  611. }
  612. }
  613. ReceiveBuffer = CONTAINING_RECORD(s, IPX_RECEIVE_BUFFER, PoolLinkage);
  614. NdisBuffer = ReceiveBuffer->NdisBuffer;
  615. //
  616. // Convert this to a queued multiple piece request.
  617. //
  618. InsertTailList(&Reserved->Requests, REQUEST_LINKAGE(Reserved->SingleRequest));
  619. Reserved->SingleRequest = NULL;
  620. Reserved->ReceiveBuffer = ReceiveBuffer;
  621. ByteOffset = LookaheadBufferOffset;
  622. BytesToTransfer = PacketSize;
  623. }
  624. InsertTailList(&Reserved->Requests, REQUEST_LINKAGE(Request));
  625. }
  626. //
  627. // We are done setting up this address file's transfer,
  628. // proceed to the next one.
  629. //
  630. ++RequestCount;
  631. if (LastAddressFile) {
  632. goto BreakWithoutLock;
  633. }
  634. }
  635. } else {
  636. //IpxPrint0("IpxProcessDatagram: Rt packet\n");
  637. if (Address->ReceivePacketInUse) {
  638. //
  639. // Need a packet, check the pool.
  640. //
  641. s = IpxPopReceivePacket (Device);
  642. if (s == NULL) {
  643. goto BreakWithLock;
  644. }
  645. Reserved = CONTAINING_RECORD (s, IPX_RECEIVE_RESERVED, PoolLinkage);
  646. ReceivePacket = CONTAINING_RECORD (Reserved, NDIS_PACKET, ProtocolReserved[0]);
  647. } else {
  648. Address->ReceivePacketInUse = TRUE;
  649. ReceivePacket = PACKET(&Address->ReceivePacket);
  650. Reserved = RECEIVE_RESERVED(&Address->ReceivePacket);
  651. }
  652. //IpxPrint0("IpxProcessDatagram: Rt packet reserved\n");
  653. s = IpxPopReceiveBuffer (Adapter);
  654. if (s == NULL) {
  655. //
  656. // No buffers, fail the request.
  657. //
  658. // Should we fail the transfer for the first request too?
  659. //
  660. goto BreakWithLock;
  661. }
  662. ReceiveBuffer = CONTAINING_RECORD(s, IPX_RECEIVE_BUFFER, PoolLinkage);
  663. NdisBuffer = ReceiveBuffer->NdisBuffer;
  664. Reserved->ReceiveBuffer = ReceiveBuffer;
  665. ByteOffset = LookaheadBufferOffset;
  666. BytesToTransfer = PacketSize;
  667. //IpxPrint0("IpxProcessDatagram: Rt packet buffer reserved\n");
  668. RtProc = TRUE;
  669. Reserved->Index = Address->Index;
  670. }
  671. BreakWithLock:
  672. IPX_FREE_LOCK (&Address->Lock, LockHandle);
  673. BreakWithoutLock:
  674. if (ReferencedAddressFile) {
  675. IpxDereferenceAddressFileSync (ReferencedAddressFile, AFREF_INDICATION);
  676. ReferencedAddressFile = NULL;
  677. }
  678. //
  679. // We can be transferring directly into a request's buffer,
  680. // transferring into an intermediate buffer, or not
  681. // receiving the packet at all.
  682. //
  683. if (RequestCount > 0 || RtProc) {
  684. if (RtProc) {
  685. Reserved->pContext = IpxAllocateMemory(sizeof(IPX_DATAGRAM_OPTIONS2), MEMORY_PACKET, "RT Options");
  686. if (!Reserved->pContext) {
  687. ASSERTMSG("Out of resources\n", 1);
  688. goto GetOut;
  689. } else {
  690. //IpxPrint1("IpxProcessDatagram: Nic Id is (%d)\n", DatagramOptions->LocalTarget.NicId);
  691. RtlCopyMemory(
  692. &((PIPX_DATAGRAM_OPTIONS2)(Reserved->pContext))->DgrmOptions,
  693. DatagramOptions,
  694. sizeof(IPX_DATAGRAM_OPTIONS));
  695. //IpxPrint1("IpxProcessDatagram: Nic Id is (%d)\n",
  696. // ((PIPX_DATAGRAM_OPTIONS2)(Reserved->pContext))->DgrmOptions.LocalTarget.NicId);
  697. }
  698. } else {
  699. Reserved->pContext = NULL;
  700. }
  701. //
  702. // If this is true, then ReceivePacket, Reserved,
  703. // and NdisBuffer are all set up correctly.
  704. //
  705. CTEAssert (ReceivePacket);
  706. CTEAssert (Reserved == (PIPX_RECEIVE_RESERVED)(ReceivePacket->ProtocolReserved));
  707. NdisChainBufferAtFront(ReceivePacket, NdisBuffer);
  708. IPX_DEBUG (RECEIVE, ("Transfer into %lx, offset %d bytes %d\n",
  709. NdisBuffer, ByteOffset, BytesToTransfer));
  710. if (BindingContext == (PVOID)IPX_LOOPBACK_COOKIE) {
  711. IPX_DEBUG (LOOPB, ("Loopback Copy from packet: %lx to packet: %lx\n", ReceivePacket, MacReceiveContext));
  712. NdisCopyFromPacketToPacketSafe(
  713. ReceivePacket, // Destination
  714. 0, // DestinationOffset
  715. BytesToTransfer, // BytesToCopy
  716. (PNDIS_PACKET)MacReceiveContext, // Source
  717. ByteOffset, // SourceOffset - loopback packet
  718. &BytesTransferred, // BytesCopied
  719. NormalPagePriority);
  720. NdisStatus = ((BytesTransferred == BytesToTransfer)? NDIS_STATUS_SUCCESS : NDIS_STATUS_RESOURCES);
  721. } else {
  722. NdisTransferData(
  723. &NdisStatus,
  724. Adapter->NdisBindingHandle,
  725. MacReceiveContext,
  726. ByteOffset,
  727. BytesToTransfer,
  728. ReceivePacket,
  729. &BytesTransferred);
  730. }
  731. if (NdisStatus != NDIS_STATUS_PENDING) {
  732. IpxTransferDataComplete(
  733. (NDIS_HANDLE)Adapter,
  734. ReceivePacket,
  735. NdisStatus,
  736. BytesTransferred);
  737. }
  738. }
  739. #ifdef SNMP
  740. else {
  741. ++IPX_MIB_ENTRY(Device, SysInUnknownSockets);
  742. }
  743. #endif SNMP
  744. GetOut:
  745. // IpxDereferenceAddressSync (Address, AREF_RECEIVE);
  746. IpxDereferenceAddress (Address, AREF_RECEIVE);
  747. } /* IpxProcessDatagram */
  748. NDIS_STATUS
  749. IpxReceiveIndication(
  750. IN NDIS_HANDLE BindingContext,
  751. IN NDIS_HANDLE ReceiveContext,
  752. IN PVOID HeaderBuffer,
  753. IN UINT HeaderBufferSize,
  754. IN PVOID LookaheadBuffer,
  755. IN UINT LookaheadBufferSize,
  756. IN UINT PacketSize
  757. )
  758. /*++
  759. Routine Description:
  760. This routine receives control from the physical provider as an
  761. indication that a frame has been received on the physical link.
  762. This routine is time critical, so we only allocate a
  763. buffer and copy the packet into it. We also perform minimal
  764. validation on this packet. It gets queued to the device context
  765. to allow for processing later.
  766. Arguments:
  767. BindingContext - The Adapter Binding specified at initialization time.
  768. ReceiveContext - A magic cookie for the MAC.
  769. HeaderBuffer - pointer to a buffer containing the packet header.
  770. HeaderBufferSize - the size of the header.
  771. LookaheadBuffer - pointer to a buffer containing the negotiated minimum
  772. amount of buffer I get to look at (not including header).
  773. LookaheadBufferSize - the size of the above. May be less than asked
  774. for, if that's all there is.
  775. PacketSize - Overall size of the packet (not including header).
  776. Return Value:
  777. NDIS_STATUS - status of operation, one of:
  778. NDIS_STATUS_SUCCESS if packet accepted,
  779. NDIS_STATUS_NOT_RECOGNIZED if not recognized by protocol,
  780. NDIS_any_other_thing if I understand, but can't handle.
  781. --*/
  782. {
  783. //
  784. // Call the actual receive indication handler and indicate that this is not a
  785. // chained receive
  786. //
  787. return IpxReceiveIndicationCommon (
  788. BindingContext,
  789. ReceiveContext, // ReceiveContext
  790. HeaderBuffer,
  791. HeaderBufferSize,
  792. LookaheadBuffer,
  793. LookaheadBufferSize,
  794. PacketSize, // PacketSize
  795. NULL, // pMdl - non-NULL => chained receive.
  796. NULL // pTdiClientCount - used in chained recv case to keep count of TDI clients
  797. );
  798. }
  799. NDIS_STATUS
  800. IpxReceiveIndicationCommon(
  801. IN NDIS_HANDLE BindingContext,
  802. IN NDIS_HANDLE ReceiveContext,
  803. IN PVOID HeaderBuffer,
  804. IN UINT HeaderBufferSize,
  805. IN PVOID LookaheadBuffer,
  806. IN UINT LookaheadBufferSize,
  807. IN UINT PacketSize,
  808. IN PMDL pMdl,
  809. IN PINT pTdiClientCount
  810. )
  811. /*++
  812. Routine Description:
  813. This routine receives control from the physical provider as an
  814. indication that a frame has been received on the physical link.
  815. This routine is time critical, so we only allocate a
  816. buffer and copy the packet into it. We also perform minimal
  817. validation on this packet. It gets queued to the device context
  818. to allow for processing later.
  819. Arguments:
  820. BindingContext - The Adapter Binding specified at initialization time.
  821. ReceiveContext - A magic cookie for the MAC.
  822. HeaderBuffer - pointer to a buffer containing the packet header.
  823. HeaderBufferSize - the size of the header.
  824. LookaheadBuffer - pointer to a buffer containing the negotiated minimum
  825. amount of buffer I get to look at (not including header).
  826. LookaheadBufferSize - the size of the above. May be less than asked
  827. for, if that's all there is.
  828. PacketSize - Overall size of the packet (not including header).
  829. pMdl - pointer to MDL chain if chained, NULL if this came from indication.
  830. Return Value:
  831. NDIS_STATUS - status of operation, one of:
  832. NDIS_STATUS_SUCCESS if packet accepted,
  833. NDIS_STATUS_NOT_RECOGNIZED if not recognized by protocol,
  834. NDIS_any_other_thing if I understand, but can't handle.
  835. --*/
  836. {
  837. IPX_DATAGRAM_OPTIONS DatagramOptions;
  838. PADAPTER Adapter = (PADAPTER)BindingContext;
  839. PBINDING Binding;
  840. PDEVICE Device = IpxDevice;
  841. PUCHAR Header = (PUCHAR)HeaderBuffer;
  842. PUCHAR Lookahead = (PUCHAR)LookaheadBuffer;
  843. ULONG PacketLength;
  844. UINT IpxPacketSize;
  845. ULONG Length802_3;
  846. USHORT Saps;
  847. ULONG DestinationNetwork;
  848. ULONG SourceNetwork;
  849. PUCHAR DestinationNode;
  850. USHORT DestinationSocket;
  851. ULONG IpxHeaderOffset;
  852. PIPX_HEADER IpxHeader;
  853. UINT i;
  854. BOOLEAN IsBroadcast;
  855. BOOLEAN IsLoopback = FALSE;
  856. #if DBG
  857. PUCHAR DestMacAddress;
  858. ULONG ReceiveFlag;
  859. #endif
  860. BOOLEAN fCallProcessDatagram = FALSE;
  861. IPX_DEFINE_LOCK_HANDLE(LockHandle1)
  862. //
  863. // Reject packets that are too short to hold even the
  864. // basic IPX header (this ignores any extra 802.2 etc.
  865. // headers but is good enough because a runt will fail
  866. // the IPX header packet length check).
  867. //
  868. if (PacketSize < sizeof(IPX_HEADER)) {
  869. #ifdef SNMP
  870. ++IPX_MIB_ENTRY(Device, SysInReceives);
  871. ++IPX_MIB_ENTRY(Device, SysInHdrErrors);
  872. #endif SNMP
  873. return STATUS_SUCCESS;
  874. }
  875. //
  876. // If this is a loopback packet, no need to do figure out the
  877. // MAC header.
  878. //
  879. if (BindingContext == (PVOID)IPX_LOOPBACK_COOKIE) {
  880. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  881. Binding = NIC_ID_TO_BINDING(IpxDevice, 1);
  882. if (!Binding) {
  883. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  884. goto NotValidLoopback;
  885. }
  886. Adapter = Binding->Adapter;
  887. //
  888. // Bump up the ref count so the adapter doesn't disappear from under
  889. // us.
  890. //
  891. IpxReferenceAdapter(Adapter);
  892. IpxReferenceBinding1(Binding, BREF_ADAPTER_ACCESS);
  893. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  894. FILL_LOCAL_TARGET(&DatagramOptions.LocalTarget, LOOPBACK_NIC_ID);
  895. //
  896. // Do this copy later, from the IpxHeader.
  897. //
  898. // RtlCopyMemory (DatagramOptions.LocalTarget.MacAddress, Binding->LocalAddress.NodeAddress, 6);
  899. if (Binding->Adapter->MacInfo.MediumType == NdisMedium802_5) {
  900. DatagramOptions.LocalTarget.MacAddress[0] &= 0x7f;
  901. }
  902. //
  903. // Ipx header starts at the top of the LookAheadBuffer
  904. //
  905. IpxHeaderOffset = 0;
  906. IPX_DEBUG (LOOPB, ("Loopback packet received: %lx\n", ReceiveContext));
  907. #if DBG
  908. DestMacAddress = DatagramOptions.LocalTarget.MacAddress;
  909. #endif
  910. IsLoopback = TRUE;
  911. goto Loopback;
  912. }
  913. //
  914. // Bump up the ref count so the adapter doesn't disappear from under
  915. // us.
  916. //
  917. IpxReferenceAdapter(Adapter);
  918. //
  919. // The first step is to construct the 8-byte local
  920. // target from the packet. We store it in the 9-byte
  921. // datagram options, leaving one byte at the front
  922. // for use by IpxProcessDatagram when indicating to
  923. // its TDI clients.
  924. //
  925. #if DBG
  926. Binding = NULL;
  927. #endif
  928. if (Adapter->MacInfo.MediumType == NdisMedium802_3) {
  929. //
  930. // Try to figure out what the packet type is.
  931. //
  932. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  933. if (Header[12] < 0x06) {
  934. //
  935. // An 802.3 header; check the next bytes. They may
  936. // be E0/E0 (802.2), FFFF (raw 802.3) or A0/A0 (SNAP).
  937. //
  938. Saps = *(UNALIGNED USHORT *)(Lookahead);
  939. if (Saps == 0xffff) {
  940. if ((Binding = Adapter->Bindings[ISN_FRAME_TYPE_802_3]) == NULL) {
  941. goto NotValid802_3;
  942. }
  943. IpxHeaderOffset = 0;
  944. Length802_3 = ((Header[12] << 8) | Header[13]);
  945. goto Valid802_3;
  946. } else if (Saps == 0xe0e0) {
  947. if (Lookahead[2] == 0x03) {
  948. if ((Binding = Adapter->Bindings[ISN_FRAME_TYPE_802_2]) == NULL) {
  949. goto NotValid802_3;
  950. }
  951. IpxHeaderOffset = 3;
  952. Length802_3 = ((Header[12] << 8) | Header[13]);
  953. goto Valid802_3;
  954. }
  955. } else if (Saps == 0xaaaa) {
  956. if ((Lookahead[2] == 0x03) &&
  957. (*(UNALIGNED USHORT *)(Lookahead+6) == Adapter->BindSapNetworkOrder)) {
  958. if ((Binding = Adapter->Bindings[ISN_FRAME_TYPE_SNAP]) == NULL) {
  959. goto NotValid802_3;
  960. }
  961. IpxHeaderOffset = 8;
  962. Length802_3 = ((Header[12] << 8) | Header[13]);
  963. goto Valid802_3;
  964. }
  965. }
  966. goto NotValid802_3;
  967. } else {
  968. //
  969. // It has an ethertype, see if it is ours.
  970. //
  971. if (*(UNALIGNED USHORT *)(Header+12) == Adapter->BindSapNetworkOrder) {
  972. if (Adapter->MacInfo.MediumAsync) {
  973. *((ULONG UNALIGNED *)(&Binding)) = *((ULONG UNALIGNED *)(&Header[2]));
  974. CTEAssert(Binding != NULL);
  975. if ((Binding != NULL) &&
  976. (Binding->LineUp)) {
  977. IpxHeaderOffset = 0;
  978. Length802_3 = PacketSize; // set this so the check succeeds
  979. //
  980. // Check if this is a type 20 packet and
  981. // we are disabling them on dialin lines -- we do
  982. // this check here to avoid impacting the main
  983. // indication path for LANs.
  984. //
  985. // The 0x02 bit of DisableDialinNetbios controls
  986. // WAN->LAN packets, which we handle here.
  987. //
  988. //
  989. // [FW] If FWD bound, no need to check since the FWD does the checks
  990. //
  991. if (!Device->ForwarderBound &&
  992. (!Binding->DialOutAsync) &&
  993. ((Device->DisableDialinNetbios & 0x02) != 0)) {
  994. IpxHeader = (PIPX_HEADER)Lookahead; // IpxHeaderOffset is 0
  995. if (IpxHeader->PacketType == 0x14) {
  996. IpxDereferenceAdapter(Adapter);
  997. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  998. return STATUS_SUCCESS;
  999. }
  1000. }
  1001. goto Valid802_3;
  1002. }
  1003. goto NotValid802_3;
  1004. } else if ((Binding = Adapter->Bindings[ISN_FRAME_TYPE_ETHERNET_II]) == NULL) {
  1005. goto NotValid802_3;
  1006. }
  1007. IpxHeaderOffset = 0;
  1008. Length802_3 = PacketSize; // set this so the check succeeds
  1009. goto Valid802_3;
  1010. }
  1011. }
  1012. goto NotValid802_3;
  1013. Valid802_3:
  1014. if (Length802_3 > PacketSize) {
  1015. goto NotValid802_3;
  1016. } else if (Length802_3 < PacketSize) {
  1017. PacketSize = Length802_3;
  1018. if (LookaheadBufferSize > Length802_3) {
  1019. LookaheadBufferSize = Length802_3;
  1020. }
  1021. }
  1022. IpxReferenceBinding1(Binding, BREF_ADAPTER_ACCESS);
  1023. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1024. RtlCopyMemory (DatagramOptions.LocalTarget.MacAddress, Header+6, 6);
  1025. #if DBG
  1026. DestMacAddress = Header;
  1027. #endif
  1028. } else if (Adapter->MacInfo.MediumType == NdisMedium802_5) {
  1029. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  1030. if ((HeaderBufferSize - 14) > 18) {
  1031. goto NotValid802_5;
  1032. }
  1033. Saps = *(USHORT UNALIGNED *)(Lookahead);
  1034. if (Saps == 0xe0e0) {
  1035. if (Lookahead[2] == 0x03) {
  1036. if ((Binding = Adapter->Bindings[ISN_FRAME_TYPE_802_2]) == NULL) {
  1037. goto NotValid802_5;
  1038. }
  1039. IpxHeaderOffset = 3;
  1040. goto Valid802_5;
  1041. }
  1042. } else if (Saps == 0xaaaa) {
  1043. if ((Lookahead[2] == 0x03) &&
  1044. (*(UNALIGNED USHORT *)(Lookahead+6) == Adapter->BindSapNetworkOrder)) {
  1045. if ((Binding = Adapter->Bindings[ISN_FRAME_TYPE_SNAP]) == NULL) {
  1046. goto NotValid802_5;
  1047. }
  1048. IpxHeaderOffset = 8;
  1049. goto Valid802_5;
  1050. }
  1051. }
  1052. goto NotValid802_5;
  1053. Valid802_5:
  1054. IpxReferenceBinding1(Binding, BREF_ADAPTER_ACCESS);
  1055. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1056. RtlCopyMemory (DatagramOptions.LocalTarget.MacAddress, Header+8, 6);
  1057. DatagramOptions.LocalTarget.MacAddress[0] &= 0x7f;
  1058. #if DBG
  1059. DestMacAddress = Header+2;
  1060. #endif
  1061. } else if (Adapter->MacInfo.MediumType == NdisMediumFddi) {
  1062. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  1063. Saps = *(USHORT UNALIGNED *)(Lookahead);
  1064. if (Saps == 0xe0e0) {
  1065. if (Lookahead[2] == 0x03) {
  1066. if ((Binding = Adapter->Bindings[ISN_FRAME_TYPE_802_2]) == NULL) {
  1067. goto NotValidFddi;
  1068. }
  1069. IpxHeaderOffset = 3;
  1070. goto ValidFddi;
  1071. }
  1072. } else if (Saps == 0xffff) {
  1073. if ((Binding = Adapter->Bindings[ISN_FRAME_TYPE_802_3]) == NULL) {
  1074. goto NotValidFddi;
  1075. }
  1076. IpxHeaderOffset = 0;
  1077. goto ValidFddi;
  1078. } else if (Saps == 0xaaaa) {
  1079. if ((Lookahead[2] == 0x03) &&
  1080. (*(UNALIGNED USHORT *)(Lookahead+6) == Adapter->BindSapNetworkOrder)) {
  1081. if ((Binding = Adapter->Bindings[ISN_FRAME_TYPE_SNAP]) == NULL) {
  1082. goto NotValidFddi;
  1083. }
  1084. IpxHeaderOffset = 8;
  1085. goto ValidFddi;
  1086. }
  1087. }
  1088. goto NotValidFddi;
  1089. ValidFddi:
  1090. IpxReferenceBinding1(Binding, BREF_ADAPTER_ACCESS);
  1091. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1092. RtlCopyMemory (DatagramOptions.LocalTarget.MacAddress, Header+7, 6);
  1093. #if DBG
  1094. DestMacAddress = Header+1;
  1095. #endif
  1096. } else {
  1097. //
  1098. // NdisMediumArcnet878_2
  1099. //
  1100. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  1101. if ((Header[2] == ARCNET_PROTOCOL_ID) &&
  1102. ((Binding = Adapter->Bindings[ISN_FRAME_TYPE_802_3]) != NULL)) {
  1103. IpxHeaderOffset = 0;
  1104. RtlZeroMemory (DatagramOptions.LocalTarget.MacAddress, 5);
  1105. DatagramOptions.LocalTarget.MacAddress[5] = Header[0];
  1106. } else {
  1107. IpxDereferenceAdapter(Adapter);
  1108. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1109. #ifdef IPX_PACKET_LOG
  1110. if (PACKET_LOG(IPX_PACKET_LOG_RCV_ALL)) {
  1111. IpxLogPacket(FALSE, Header+2, Header+1, (USHORT)PacketSize, LookaheadBuffer, (PUCHAR)LookaheadBuffer + sizeof(IPX_HEADER));
  1112. }
  1113. #endif
  1114. return NDIS_STATUS_SUCCESS;
  1115. }
  1116. #if DBG
  1117. DestMacAddress = Header+2; // Need to log less than six bytes
  1118. #endif
  1119. IpxReferenceBinding1(Binding, BREF_ADAPTER_ACCESS);
  1120. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1121. }
  1122. //
  1123. // Make sure this didn't slip through.
  1124. //
  1125. CTEAssert (Binding != NULL);
  1126. FILL_LOCAL_TARGET(&DatagramOptions.LocalTarget, MIN( Device->MaxBindings, Binding->NicId));
  1127. Loopback:
  1128. //
  1129. // Now that we have validated the header and constructed
  1130. // the local target, indicate the packet to the correct
  1131. // client.
  1132. //
  1133. IpxHeader = (PIPX_HEADER)(Lookahead + IpxHeaderOffset);
  1134. PacketLength = (IpxHeader->PacketLength[0] << 8) | IpxHeader->PacketLength[1];
  1135. IpxPacketSize = PacketSize - IpxHeaderOffset;
  1136. //
  1137. // Take care of bad NICs [109862]
  1138. //
  1139. if (PacketLength < sizeof(IPX_HEADER)) {
  1140. IpxDereferenceAdapter(Adapter);
  1141. IpxDereferenceBinding1(Binding, BREF_ADAPTER_ACCESS);
  1142. #ifdef IPX_PACKET_LOG
  1143. if (PACKET_LOG(IPX_PACKET_LOG_RCV_ALL)) {
  1144. IpxLogPacket(FALSE, DestMacAddress, DatagramOptions.LocalTarget.MacAddress, (USHORT)PacketSize, IpxHeader, IpxHeader+1);
  1145. }
  1146. #endif
  1147. IPX_DEBUG (BAD_PACKET, ("Packet len %d, IPX len %d\n",
  1148. PacketLength, IpxPacketSize));
  1149. return NDIS_STATUS_SUCCESS;
  1150. }
  1151. if (PacketLength > IpxPacketSize) {
  1152. IpxDereferenceAdapter(Adapter);
  1153. IpxDereferenceBinding1(Binding, BREF_ADAPTER_ACCESS);
  1154. #ifdef IPX_PACKET_LOG
  1155. if (PACKET_LOG(IPX_PACKET_LOG_RCV_ALL)) {
  1156. IpxLogPacket(FALSE, DestMacAddress, DatagramOptions.LocalTarget.MacAddress, (USHORT)PacketSize, IpxHeader, IpxHeader+1);
  1157. }
  1158. #endif
  1159. IPX_DEBUG (BAD_PACKET, ("Packet len %d, IPX len %d\n",
  1160. PacketLength, IpxPacketSize));
  1161. #ifdef SNMP
  1162. ++IPX_MIB_ENTRY(Device, SysInReceives);
  1163. #endif SNMP
  1164. return NDIS_STATUS_SUCCESS;
  1165. } else if (PacketLength < IpxPacketSize) {
  1166. IpxPacketSize = PacketLength;
  1167. if (LookaheadBufferSize > (PacketLength + IpxHeaderOffset)) {
  1168. LookaheadBufferSize = PacketLength + IpxHeaderOffset;
  1169. }
  1170. }
  1171. //
  1172. // Bug #33595 - (hotfixed in 3.51, checked into 4.0 beta2)
  1173. // Customer problem where NT allowed RIP/SAP to reply to an 802.5 functional address in the IPX source node. The source
  1174. // MAC address was proper in this case. We need to check for the case where if the packet's source network is the same
  1175. // as that of the binding it came on (=> did not come thru a router), then the SourceNodeAddress in the IPX header
  1176. // should be equal to the SourceAddress in the MAC header.
  1177. //
  1178. // This check is controlled through a registry value - VerifySourceAddress.
  1179. // In case of Arcnet, this check will not succeed.
  1180. // Also, for WAN, the node addresses will not match, so avoid check for those.
  1181. //
  1182. // If the source network is 0, we drop it. Auto-detect frames should have matching node (MAC) addresses.
  1183. // Loopback packets dont have a valid header, so skip this test for them.
  1184. //
  1185. // For loopback pkts, do all the processing above, so we can avoid all these checks for IsLoopback here.
  1186. // Also, to prevent the RtlCopyMemory into the localtarget above, try to use the MAC header to indicate the
  1187. // correct binding to us so we dont use the first one always.
  1188. //
  1189. // CAVEAT:: when using the MAC header as a binding pointer, ensure that we use the adapter corresp, to that binding
  1190. // to enque all the receive requests. currently we enqueue them onto the first bindings adapter.
  1191. //
  1192. if (((*(UNALIGNED ULONG *)IpxHeader->SourceNetwork == Binding->LocalAddress.NetworkAddress) ||
  1193. (*(UNALIGNED ULONG *)IpxHeader->SourceNetwork == 0)) &&
  1194. (!IPX_NODE_EQUAL (IpxHeader->SourceNode, DatagramOptions.LocalTarget.MacAddress)) &&
  1195. Device->VerifySourceAddress &&
  1196. !IsLoopback &&
  1197. !Adapter->MacInfo.MediumAsync &&
  1198. (Adapter->MacInfo.MediumType != NdisMediumArcnet878_2)) {
  1199. IPX_DEBUG(BAD_PACKET, ("Local packet: Src MAC %2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x ",
  1200. DatagramOptions.LocalTarget.MacAddress[0],
  1201. DatagramOptions.LocalTarget.MacAddress[1],
  1202. DatagramOptions.LocalTarget.MacAddress[2],
  1203. DatagramOptions.LocalTarget.MacAddress[3],
  1204. DatagramOptions.LocalTarget.MacAddress[4],
  1205. DatagramOptions.LocalTarget.MacAddress[5]));
  1206. IPX_DEBUG(BAD_PACKET, ("IPX Src Node %2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x\n",
  1207. IpxHeader->SourceNode[0],
  1208. IpxHeader->SourceNode[1],
  1209. IpxHeader->SourceNode[2],
  1210. IpxHeader->SourceNode[3],
  1211. IpxHeader->SourceNode[4],
  1212. IpxHeader->SourceNode[5]));
  1213. #ifdef IPX_PACKET_LOG
  1214. ReceiveFlag = IPX_PACKET_LOG_RCV_ALL;
  1215. if (PACKET_LOG(ReceiveFlag)) {
  1216. IpxLogPacket(
  1217. FALSE,
  1218. DestMacAddress,
  1219. DatagramOptions.LocalTarget.MacAddress,
  1220. (USHORT)IpxPacketSize,
  1221. IpxHeader,
  1222. IpxHeader+1);
  1223. }
  1224. #endif
  1225. IpxDereferenceAdapter(Adapter);
  1226. IpxDereferenceBinding1(Binding, BREF_ADAPTER_ACCESS);
  1227. #ifdef SNMP
  1228. ++IPX_MIB_ENTRY(Device, SysInReceives);
  1229. #endif SNMP
  1230. return NDIS_STATUS_SUCCESS;
  1231. }
  1232. // 235842 To avoid flooding when client blindly respond to source address. [tingcai]
  1233. if (((*(UNALIGNED ULONG *)IpxHeader->SourceNetwork == 0xffffffff) ||
  1234. (IPX_NODE_BROADCAST (IpxHeader->SourceNode)))) {
  1235. IPX_DEBUG(BAD_PACKET, ("!!! Droping packets with broadcast network or node address. !!!\n"));
  1236. IPX_DEBUG(BAD_PACKET, ("IPX Src Node %2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x\n",
  1237. IpxHeader->SourceNode[0],
  1238. IpxHeader->SourceNode[1],
  1239. IpxHeader->SourceNode[2],
  1240. IpxHeader->SourceNode[3],
  1241. IpxHeader->SourceNode[4],
  1242. IpxHeader->SourceNode[5]));
  1243. #ifdef IPX_PACKET_LOG
  1244. ReceiveFlag = IPX_PACKET_LOG_RCV_ALL;
  1245. if (PACKET_LOG(ReceiveFlag)) {
  1246. IpxLogPacket(
  1247. FALSE,
  1248. DestMacAddress,
  1249. DatagramOptions.LocalTarget.MacAddress,
  1250. (USHORT)IpxPacketSize,
  1251. IpxHeader,
  1252. IpxHeader+1);
  1253. }
  1254. #endif
  1255. IpxDereferenceAdapter(Adapter);
  1256. IpxDereferenceBinding1(Binding, BREF_ADAPTER_ACCESS);
  1257. #ifdef SNMP
  1258. ++IPX_MIB_ENTRY(Device, SysInReceives);
  1259. #endif SNMP
  1260. return NDIS_STATUS_SUCCESS;
  1261. }
  1262. // 260489 If we receive a packet with source network address equals to 0,
  1263. // we replace replace the source network address with the network address
  1264. // of the binding where the packet was received.
  1265. // In this way, clients, such as, forwarder can forward the packet to other
  1266. // networks, and clients in other networks will be able to reply to the
  1267. // packet with the source network address that we fill below.
  1268. if (*(UNALIGNED ULONG *)IpxHeader->SourceNetwork == 0) {
  1269. *(UNALIGNED ULONG *) IpxHeader->SourceNetwork = Binding->LocalAddress.NetworkAddress;
  1270. IPX_DEBUG(PACKET, ("!!! Replaced 0 source network address with local network address !!!\n"));
  1271. IPX_DEBUG (PACKET, ("Source %lx %2.2x-%2.2x-%2.2x-%2.2x %2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x\n",
  1272. *(USHORT UNALIGNED *)&IpxHeader->SourceSocket,
  1273. IpxHeader->SourceNetwork[0],
  1274. IpxHeader->SourceNetwork[1],
  1275. IpxHeader->SourceNetwork[2],
  1276. IpxHeader->SourceNetwork[3],
  1277. IpxHeader->SourceNode[0],
  1278. IpxHeader->SourceNode[1],
  1279. IpxHeader->SourceNode[2],
  1280. IpxHeader->SourceNode[3],
  1281. IpxHeader->SourceNode[4],
  1282. IpxHeader->SourceNode[5]));
  1283. #ifdef IPX_PACKET_LOG
  1284. ReceiveFlag = IPX_PACKET_LOG_RCV_ALL;
  1285. if (PACKET_LOG(ReceiveFlag)) {
  1286. IpxLogPacket(
  1287. FALSE,
  1288. DestMacAddress,
  1289. DatagramOptions.LocalTarget.MacAddress,
  1290. (USHORT)IpxPacketSize,
  1291. IpxHeader,
  1292. IpxHeader+1);
  1293. }
  1294. #endif
  1295. }
  1296. DestinationSocket = *(USHORT UNALIGNED *)&IpxHeader->DestinationSocket;
  1297. //
  1298. // In order to have consistent local targets, copy over the target from the IpxHeader.
  1299. //
  1300. if (IsLoopback) {
  1301. IPX_DEBUG (LOOPB, ("Loopback packet copied the localtarget: %lx\n", IpxHeader->DestinationNode));
  1302. // RtlCopyMemory (DatagramOptions.LocalTarget.MacAddress, IpxHeader->DestinationNode, 6);
  1303. *((UNALIGNED ULONG *)DatagramOptions.LocalTarget.MacAddress) =
  1304. *((UNALIGNED ULONG *)IpxHeader->DestinationNode);
  1305. *((UNALIGNED USHORT *)(DatagramOptions.LocalTarget.MacAddress+4)) =
  1306. *((UNALIGNED USHORT *)(IpxHeader->DestinationNode+4));
  1307. }
  1308. ++Device->Statistics.PacketsReceived;
  1309. DestinationNode = IpxHeader->DestinationNode;
  1310. if (DestinationSocket != RIP_SOCKET) {
  1311. DestinationNetwork = *(UNALIGNED ULONG *)IpxHeader->DestinationNetwork;
  1312. RecheckPacket:
  1313. if (Device->MultiCardZeroVirtual) {
  1314. if ((DestinationNetwork == Binding->LocalAddress.NetworkAddress) ||
  1315. (DestinationNetwork == 0)) {
  1316. if (IPX_NODE_EQUAL (DestinationNode, Binding->LocalAddress.NodeAddress)) {
  1317. IsBroadcast = FALSE;
  1318. goto DestinationOk;
  1319. } else {
  1320. if ((IsBroadcast = IPX_NODE_BROADCAST(DestinationNode)) &&
  1321. (Binding->ReceiveBroadcast)) {
  1322. goto DestinationOk;
  1323. }
  1324. }
  1325. //
  1326. // If this is a binding set slave, check for the master's
  1327. // address.
  1328. //
  1329. if ((Binding->BindingSetMember) &&
  1330. (IPX_NODE_EQUAL (DestinationNode, Binding->MasterBinding->LocalAddress.NodeAddress))) {
  1331. goto DestinationOk;
  1332. }
  1333. } else {
  1334. IsBroadcast = IPX_NODE_BROADCAST(DestinationNode);
  1335. }
  1336. } else {
  1337. if ((DestinationNetwork == Device->SourceAddress.NetworkAddress) ||
  1338. (DestinationNetwork == 0)) {
  1339. if (IPX_NODE_EQUAL (DestinationNode, Device->SourceAddress.NodeAddress)) {
  1340. IsBroadcast = FALSE;
  1341. goto DestinationOk;
  1342. } else {
  1343. if ((IsBroadcast = IPX_NODE_BROADCAST(DestinationNode)) &&
  1344. (Binding->ReceiveBroadcast)) {
  1345. goto DestinationOk;
  1346. }
  1347. }
  1348. } else {
  1349. IsBroadcast = IPX_NODE_BROADCAST(DestinationNode);
  1350. }
  1351. //
  1352. // We need to check for frames that are sent to the
  1353. // binding node and net, because if we have a virtual
  1354. // net we won't catch them in the check above. This
  1355. // will include any Netbios frames, since they don't
  1356. // use the virtual net. Doing the check like this will slow
  1357. // down netbios indications just a bit on a machine with
  1358. // a virtual network, but it saves a jump for other traffic
  1359. // vs. adding the check up there (the assumption is if we
  1360. // have a virtual net most traffic is NCP).
  1361. //
  1362. // Note that IsBroadcast is already set, so we don't have
  1363. // to do that.
  1364. //
  1365. if ((Device->VirtualNetwork) &&
  1366. ((DestinationNetwork == Binding->LocalAddress.NetworkAddress) ||
  1367. (DestinationNetwork == 0))) {
  1368. if (IPX_NODE_EQUAL (DestinationNode, Binding->LocalAddress.NodeAddress)) {
  1369. goto DestinationOk;
  1370. } else {
  1371. if (IsBroadcast && (Binding->ReceiveBroadcast)) {
  1372. goto DestinationOk;
  1373. }
  1374. }
  1375. //
  1376. // If this is a binding set slave, check for the master's
  1377. // address.
  1378. //
  1379. if ((Binding->BindingSetMember) &&
  1380. (IPX_NODE_EQUAL (DestinationNode, Binding->MasterBinding->LocalAddress.NodeAddress))) {
  1381. goto DestinationOk;
  1382. }
  1383. }
  1384. }
  1385. //
  1386. // If this was a loopback packet that was sent on the second binding (but showed back up on the first one),
  1387. // then the networknumbers will not match. Allow the receive on the first binding itself.
  1388. //
  1389. if (IsLoopback) {
  1390. IPX_DEBUG (LOOPB, ("Loopback packet forced on first binding: %lx\n", ReceiveContext));
  1391. goto DestinationOk;
  1392. }
  1393. //
  1394. // If we did not receive this packet, it might be because
  1395. // our network is still 0 and this packet was actually
  1396. // sent to the real network number. If so we try to
  1397. // update our local address, and if successful we
  1398. // re-check the packet. We don't insert if we are
  1399. // not done with auto detection, to avoid colliding
  1400. // with that.
  1401. //
  1402. // To avoid problems if we are a router, we only update
  1403. // on packets that are broadcast or sent to us.
  1404. //
  1405. if ((Binding->LocalAddress.NetworkAddress == 0) &&
  1406. (Device->AutoDetectState == AUTO_DETECT_STATE_DONE) &&
  1407. (DestinationNetwork != 0) &&
  1408. (IsBroadcast ||
  1409. IPX_NODE_EQUAL (DestinationNode, Binding->LocalAddress.NodeAddress))) {
  1410. CTEAssert (Binding->NicId != 0);
  1411. if (IpxUpdateBindingNetwork(
  1412. Device,
  1413. Binding,
  1414. DestinationNetwork) == STATUS_SUCCESS) {
  1415. IPX_DEBUG (RIP, ("Binding %d reconfigured to network %lx\n",
  1416. Binding->NicId,
  1417. REORDER_ULONG(Binding->LocalAddress.NetworkAddress)));
  1418. //
  1419. // Jump back and re-process the packet; we know
  1420. // we won't loop through here again because the
  1421. // binding's network is now non-zero.
  1422. //
  1423. goto RecheckPacket;
  1424. }
  1425. }
  1426. //
  1427. // The only frames that will not already have jumped to
  1428. // DestinationOk are those to or from the SAP socket,
  1429. // so we check for those.
  1430. //
  1431. if ((*(USHORT UNALIGNED *)&IpxHeader->SourceSocket == SAP_SOCKET) ||
  1432. (DestinationSocket == SAP_SOCKET)) {
  1433. DestinationOk:
  1434. //
  1435. // [FW] For internally destined packets, call the Forwarder's internal
  1436. // receive handler to filter the packets.
  1437. //
  1438. // STEFAN: 3/28/96:
  1439. // Dont filter IPXWAN config packets since the FWD does not have this adapter opened.
  1440. //
  1441. IPX_DEBUG(RECEIVE, ("DestSocket: %lx\n", DestinationSocket));
  1442. #ifdef SNMP
  1443. ++IPX_MIB_ENTRY(Device, SysInDelivers);
  1444. #endif SNMP
  1445. if (DestinationSocket != IPXWAN_SOCKET &&
  1446. Device->ForwarderBound) {
  1447. NDIS_STATUS NdisStatus;
  1448. IPX_DEBUG(RECEIVE, ("Internal packet, sending up to the Forwarder\n"));
  1449. //
  1450. // We should pass up the correct Fwd ctx for loopback ptks
  1451. //
  1452. //
  1453. // Indicate this up only if the adapter the packet came on was opened by the Forwarder
  1454. //
  1455. if (GET_LONG_VALUE(Binding->ReferenceCount) == 2) {
  1456. NdisStatus = (*Device->UpperDrivers[IDENTIFIER_RIP].InternalReceiveHandler) (
  1457. (IsLoopback) ?
  1458. VIRTUAL_NET_FORWARDER_CONTEXT :
  1459. Binding->FwdAdapterContext, // ForwarderAdapterContext
  1460. &DatagramOptions.LocalTarget, // Remote Address
  1461. (PUCHAR) IpxHeader, // Lookahead buffer
  1462. LookaheadBufferSize - IpxHeaderOffset // Lookahead buffer size
  1463. );
  1464. IPX_DEBUG(TEMP, ("Internal packet, Forwarder returned %lx\n", NdisStatus));
  1465. if (NdisStatus != STATUS_SUCCESS) {
  1466. //
  1467. // Log this packet
  1468. //
  1469. IPX_DEBUG(TEMP, ("Internal packet, failed the filter: ipxheader: %lx\n", IpxHeader));
  1470. //
  1471. // The router needs to see Netbios type 20 broadcasts.
  1472. //
  1473. if (IsBroadcast &&
  1474. (IpxHeader->PacketType == 0x14) &&
  1475. (Binding->ReceiveBroadcast) &&
  1476. (!fCallProcessDatagram)) {
  1477. goto RipIndication;
  1478. }
  1479. // else
  1480. IpxDereferenceAdapter(Adapter);
  1481. return NDIS_STATUS_SUCCESS;
  1482. }
  1483. } else {
  1484. IpxDereferenceAdapter(Adapter);
  1485. IPX_DEBUG(TEMP, ("Internal packet, Forwarder has not opened the adapter yet\n"));
  1486. return NDIS_STATUS_SUCCESS;
  1487. }
  1488. }
  1489. //
  1490. // An IPX packet sent to us, or a SAP packet (which
  1491. // are not sent to the virtual address but still need
  1492. // to be indicated and not forwarded to RIP).
  1493. //
  1494. if (DestinationSocket == NB_SOCKET) {
  1495. #if DBG
  1496. ReceiveFlag = IPX_PACKET_LOG_RCV_NB | IPX_PACKET_LOG_RCV_ALL;
  1497. #endif
  1498. if (((!IsBroadcast) || (Device->UpperDrivers[IDENTIFIER_NB].BroadcastEnable)) &&
  1499. (Device->UpperDriverBound[IDENTIFIER_NB]) && Binding->IsnInformed[IDENTIFIER_NB] == TRUE) {
  1500. if (!IsLoopback && Adapter->MacInfo.MediumType == NdisMedium802_5) {
  1501. MacUpdateSourceRouting (IDENTIFIER_NB, Adapter, Header, HeaderBufferSize);
  1502. }
  1503. //
  1504. // We add HeaderBufferSize to the IpxHeaderOffset field since we do an NdisCopyFromPacketToPacket
  1505. // in IpxTransferData, which needs offset from the beginning of the packet.
  1506. // NdisTransferData adds the offset passed in to the beginning of the IPX packet.
  1507. //
  1508. if ((*Device->UpperDrivers[IDENTIFIER_NB].ReceiveHandler)(
  1509. (IsLoopback) ? BindingContext : Adapter->NdisBindingHandle,
  1510. ReceiveContext,
  1511. Binding->FwdAdapterContext,
  1512. &DatagramOptions.LocalTarget,
  1513. Adapter->MacInfo.MacOptions,
  1514. (PUCHAR)IpxHeader,
  1515. LookaheadBufferSize - IpxHeaderOffset,
  1516. (IsLoopback) ? IpxHeaderOffset+HeaderBufferSize : IpxHeaderOffset,
  1517. IpxPacketSize,
  1518. pMdl)) {
  1519. CTEAssert(FALSE);
  1520. (*pTdiClientCount)++;
  1521. }
  1522. Device->ReceiveCompletePending[IDENTIFIER_NB] = TRUE;
  1523. }
  1524. //
  1525. // The router needs to see Netbios type 20 broadcasts.
  1526. //
  1527. if (IsBroadcast &&
  1528. (IpxHeader->PacketType == 0x14) &&
  1529. (Binding->ReceiveBroadcast) &&
  1530. (!fCallProcessDatagram)) {
  1531. goto RipIndication;
  1532. }
  1533. } else if (IpxHeader->PacketType == SPX_PACKET_TYPE) {
  1534. #if DBG
  1535. ReceiveFlag = IPX_PACKET_LOG_RCV_SPX | IPX_PACKET_LOG_RCV_ALL;
  1536. #endif
  1537. if (((!IsBroadcast) || (Device->UpperDrivers[IDENTIFIER_SPX].BroadcastEnable)) &&
  1538. (Device->UpperDriverBound[IDENTIFIER_SPX])) {
  1539. if (!IsLoopback && Adapter->MacInfo.MediumType == NdisMedium802_5) {
  1540. MacUpdateSourceRouting (IDENTIFIER_SPX, Adapter, Header, HeaderBufferSize);
  1541. }
  1542. if ((*Device->UpperDrivers[IDENTIFIER_SPX].ReceiveHandler)(
  1543. (IsLoopback) ? BindingContext : Adapter->NdisBindingHandle,
  1544. ReceiveContext,
  1545. Binding->FwdAdapterContext,
  1546. &DatagramOptions.LocalTarget,
  1547. Adapter->MacInfo.MacOptions,
  1548. (PUCHAR)IpxHeader,
  1549. LookaheadBufferSize - IpxHeaderOffset,
  1550. (IsLoopback) ? IpxHeaderOffset+HeaderBufferSize : IpxHeaderOffset,
  1551. IpxPacketSize,
  1552. pMdl)) {
  1553. CTEAssert(FALSE);
  1554. (*pTdiClientCount)++;
  1555. }
  1556. Device->ReceiveCompletePending[IDENTIFIER_SPX] = TRUE;
  1557. }
  1558. } else {
  1559. IPX_DEBUG (RECEIVE, ("Received packet type %d, length %d\n",
  1560. Binding->FrameType,
  1561. IpxPacketSize));
  1562. IPX_DEBUG (RECEIVE, ("Source %lx %2.2x-%2.2x-%2.2x-%2.2x %2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x\n",
  1563. *(USHORT UNALIGNED *)&IpxHeader->SourceSocket,
  1564. IpxHeader->SourceNetwork[0],
  1565. IpxHeader->SourceNetwork[1],
  1566. IpxHeader->SourceNetwork[2],
  1567. IpxHeader->SourceNetwork[3],
  1568. IpxHeader->SourceNode[0],
  1569. IpxHeader->SourceNode[1],
  1570. IpxHeader->SourceNode[2],
  1571. IpxHeader->SourceNode[3],
  1572. IpxHeader->SourceNode[4],
  1573. IpxHeader->SourceNode[5]));
  1574. IPX_DEBUG (RECEIVE, ("Destination %d %2.2x-%2.2x-%2.2x-%2.2x %2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x\n",
  1575. DestinationSocket,
  1576. IpxHeader->DestinationNetwork[0],
  1577. IpxHeader->DestinationNetwork[1],
  1578. IpxHeader->DestinationNetwork[2],
  1579. IpxHeader->DestinationNetwork[3],
  1580. IpxHeader->DestinationNode[0],
  1581. IpxHeader->DestinationNode[1],
  1582. IpxHeader->DestinationNode[2],
  1583. IpxHeader->DestinationNode[3],
  1584. IpxHeader->DestinationNode[4],
  1585. IpxHeader->DestinationNode[5]));
  1586. #if DBG
  1587. if (IpxHeader->DestinationSocket == IpxPacketLogSocket) {
  1588. ReceiveFlag = IPX_PACKET_LOG_RCV_SOCKET | IPX_PACKET_LOG_RCV_OTHER | IPX_PACKET_LOG_RCV_ALL;
  1589. } else {
  1590. ReceiveFlag = IPX_PACKET_LOG_RCV_OTHER | IPX_PACKET_LOG_RCV_ALL;
  1591. }
  1592. #endif
  1593. //
  1594. // Fiddle with this if so in the general case
  1595. // the jump is not made (the compiler
  1596. // still rearranges it).
  1597. //
  1598. if (Adapter->MacInfo.MediumType != NdisMedium802_5) {
  1599. CallProcessDatagram:
  1600. //
  1601. // [SA] Returns a status now which needs to be returned to NDIS
  1602. // Also, MDL is passed in.
  1603. // We need to pass in the HeaderBufferSize too....
  1604. //
  1605. IpxProcessDatagram(
  1606. Device,
  1607. Adapter,
  1608. Binding,
  1609. ReceiveContext,
  1610. &DatagramOptions,
  1611. (PUCHAR)IpxHeader,
  1612. LookaheadBufferSize - IpxHeaderOffset,
  1613. (IsLoopback) ? IpxHeaderOffset+HeaderBufferSize : IpxHeaderOffset, // lookaheadbufferoffset
  1614. IpxPacketSize,
  1615. IsBroadcast,
  1616. pTdiClientCount,
  1617. HeaderBufferSize,
  1618. pMdl,
  1619. BindingContext);
  1620. } else {
  1621. if (!IsLoopback) {
  1622. MacUpdateSourceRouting (IDENTIFIER_IPX, Adapter, Header, HeaderBufferSize);
  1623. }
  1624. goto CallProcessDatagram;
  1625. }
  1626. //
  1627. // The router needs to see type 20 broadcasts.
  1628. //
  1629. if (IsBroadcast &&
  1630. (IpxHeader->PacketType == 0x14) &&
  1631. (Binding->ReceiveBroadcast) &&
  1632. (!fCallProcessDatagram)) {
  1633. goto RipIndication;
  1634. }
  1635. }
  1636. } else {
  1637. #if DBG
  1638. ReceiveFlag = IPX_PACKET_LOG_RCV_ALL;
  1639. #endif
  1640. //
  1641. // We need to let non-type 20 broadcast frames go to RIP to allow for lan-specific
  1642. // broadcasts. For logon over IPX, this allows the logon request to get thru the WAN
  1643. // line.
  1644. //
  1645. // if ( !IsBroadcast ) {
  1646. RipIndication:;
  1647. if (Device->ForwarderBound) {
  1648. //
  1649. // FWD ....
  1650. //
  1651. if (DestinationSocket == RIP_SOCKET) {
  1652. //
  1653. // [FW] Since RIP is now a user app with the same socket #, we inform thru'
  1654. // the ProcessDatagram path. And only if the Forwarder is installed.
  1655. //
  1656. IsBroadcast = IPX_NODE_BROADCAST(DestinationNode);
  1657. fCallProcessDatagram = TRUE;
  1658. goto CallProcessDatagram;
  1659. } else {
  1660. if (!IsLoopback && Adapter->MacInfo.MediumType == NdisMedium802_5) {
  1661. MacUpdateSourceRouting (IDENTIFIER_RIP, Adapter, Header, HeaderBufferSize);
  1662. }
  1663. //
  1664. // We hide binding sets from the router, to avoid
  1665. // misordering packets which it routes.
  1666. //
  1667. if (!IsLoopback && Binding->BindingSetMember) {
  1668. FILL_LOCAL_TARGET(&DatagramOptions.LocalTarget, MIN (Device->MaxBindings, Binding->MasterBinding->NicId));
  1669. }
  1670. if (GET_LONG_VALUE(Binding->ReferenceCount) == 2) {
  1671. if (IsLoopback) {
  1672. if ((*Device->UpperDrivers[IDENTIFIER_RIP].InternalReceiveHandler)(
  1673. VIRTUAL_NET_FORWARDER_CONTEXT,
  1674. &DatagramOptions.LocalTarget,
  1675. (PUCHAR)IpxHeader,
  1676. LookaheadBufferSize - IpxHeaderOffset
  1677. )) {
  1678. (*pTdiClientCount)++;
  1679. }
  1680. } else {
  1681. if ((*Device->UpperDrivers[IDENTIFIER_RIP].ReceiveHandler)(
  1682. (IsLoopback) ? BindingContext : Adapter->NdisBindingHandle,
  1683. ReceiveContext,
  1684. Binding->FwdAdapterContext,
  1685. &DatagramOptions.LocalTarget,
  1686. Adapter->MacInfo.MacOptions,
  1687. (PUCHAR)IpxHeader,
  1688. LookaheadBufferSize - IpxHeaderOffset,
  1689. (IsLoopback) ? IpxHeaderOffset+HeaderBufferSize : IpxHeaderOffset,
  1690. IpxPacketSize,
  1691. pMdl)) {
  1692. (*pTdiClientCount)++;
  1693. }
  1694. }
  1695. Device->ReceiveCompletePending[IDENTIFIER_RIP] = TRUE;
  1696. } else {
  1697. IPX_DEBUG(RECEIVE, ("External packet, Forwarder has not opened the adapter yet\n"));
  1698. }
  1699. }
  1700. } else if (Device->UpperDriverBound[IDENTIFIER_RIP]) {
  1701. //
  1702. // Old RIP...
  1703. //
  1704. if (!IsLoopback && Adapter->MacInfo.MediumType == NdisMedium802_5) {
  1705. MacUpdateSourceRouting (IDENTIFIER_RIP, Adapter, Header, HeaderBufferSize);
  1706. }
  1707. //
  1708. // We hide binding sets from the router, to avoid
  1709. // misordering packets which it routes.
  1710. //
  1711. if (!IsLoopback && Binding->BindingSetMember) {
  1712. FILL_LOCAL_TARGET(&DatagramOptions.LocalTarget, MIN (Device->MaxBindings, Binding->MasterBinding->NicId));
  1713. }
  1714. if (GET_LONG_VALUE(Binding->ReferenceCount) == 2) {
  1715. if (IsLoopback) {
  1716. if ((*Device->UpperDrivers[IDENTIFIER_RIP].InternalReceiveHandler)(
  1717. VIRTUAL_NET_FORWARDER_CONTEXT,
  1718. &DatagramOptions.LocalTarget,
  1719. (PUCHAR)IpxHeader,
  1720. LookaheadBufferSize - IpxHeaderOffset
  1721. )) {
  1722. CTEAssert(FALSE);
  1723. (*pTdiClientCount)++;
  1724. }
  1725. } else {
  1726. if ((*Device->UpperDrivers[IDENTIFIER_RIP].ReceiveHandler)(
  1727. (IsLoopback) ? BindingContext : Adapter->NdisBindingHandle,
  1728. ReceiveContext,
  1729. Binding->FwdAdapterContext,
  1730. &DatagramOptions.LocalTarget,
  1731. Adapter->MacInfo.MacOptions,
  1732. (PUCHAR)IpxHeader,
  1733. LookaheadBufferSize - IpxHeaderOffset,
  1734. (IsLoopback) ? IpxHeaderOffset+HeaderBufferSize : IpxHeaderOffset,
  1735. IpxPacketSize,
  1736. pMdl)) {
  1737. CTEAssert(FALSE);
  1738. (*pTdiClientCount)++;
  1739. }
  1740. }
  1741. } else {
  1742. IPX_DEBUG(RECEIVE, ("Old Rip: External packet, Forwarder has not opened the adapter yet\n"));
  1743. }
  1744. Device->ReceiveCompletePending[IDENTIFIER_RIP] = TRUE;
  1745. }
  1746. // }
  1747. }
  1748. } else {
  1749. if ((Binding->ReceiveBroadcast) ||
  1750. (!IPX_NODE_BROADCAST(IpxHeader->DestinationNode))) {
  1751. SourceNetwork = *(UNALIGNED LONG *)IpxHeader->SourceNetwork;
  1752. //
  1753. // Sent to the RIP socket; check if this binding needs a
  1754. // network number.
  1755. //
  1756. if ((Binding->LocalAddress.NetworkAddress == 0) &&
  1757. ((SourceNetwork = *(UNALIGNED LONG *)IpxHeader->SourceNetwork) != 0)) {
  1758. switch (Device->AutoDetectState) {
  1759. case AUTO_DETECT_STATE_DONE:
  1760. //
  1761. // We are done with auto-detect and running.
  1762. // Make sure this packet is useful. If the source
  1763. // MAC address and source IPX node are the same then
  1764. // it was not routed, and we also check that it is not
  1765. // an IPX broadcast (otherwise a misconfigured client
  1766. // might confuse us).
  1767. //
  1768. if ((RtlEqualMemory(
  1769. IpxHeader->SourceNode,
  1770. DatagramOptions.LocalTarget.MacAddress,
  1771. 6)) &&
  1772. (*(UNALIGNED ULONG *)(IpxHeader->DestinationNode) != 0xffffffff) &&
  1773. (*(UNALIGNED USHORT *)(IpxHeader->DestinationNode+4) != 0xffff)) {
  1774. CTEAssert (Binding->NicId != 0);
  1775. if (IpxUpdateBindingNetwork(
  1776. Device,
  1777. Binding,
  1778. *(UNALIGNED LONG *)IpxHeader->SourceNetwork) == STATUS_SUCCESS) {
  1779. IPX_DEBUG (RIP, ("Binding %d is network %lx\n",
  1780. Binding->NicId,
  1781. REORDER_ULONG(Binding->LocalAddress.NetworkAddress)));
  1782. }
  1783. }
  1784. break;
  1785. case AUTO_DETECT_STATE_RUNNING:
  1786. //
  1787. // We are waiting for rip responses to figure out our
  1788. // network number. We count the responses that match
  1789. // and do not match our current value; when the non-
  1790. // matching number exceeds it we switch (to whatever
  1791. // this frame happens to have). Note that on the first
  1792. // non-zero response this will be the case and we will
  1793. // switch to that network.
  1794. //
  1795. // After auto-detect is done we call RipInsertLocalNetwork
  1796. // for whatever the current network is on each binding.
  1797. //
  1798. if (SourceNetwork == Binding->TentativeNetworkAddress) {
  1799. ++Binding->MatchingResponses;
  1800. } else {
  1801. ++Binding->NonMatchingResponses;
  1802. if (Binding->NonMatchingResponses > Binding->MatchingResponses) {
  1803. IPX_DEBUG (AUTO_DETECT, ("Switching to net %lx on %lx (%d - %d)\n",
  1804. REORDER_ULONG(SourceNetwork),
  1805. Binding,
  1806. Binding->NonMatchingResponses,
  1807. Binding->MatchingResponses));
  1808. Binding->TentativeNetworkAddress = SourceNetwork;
  1809. Binding->MatchingResponses = 1;
  1810. Binding->NonMatchingResponses = 0;
  1811. }
  1812. }
  1813. //
  1814. // If we are auto-detecting and we have just found
  1815. // a default, set this so that RIP stops trying
  1816. // to auto-detect on other nets. Unless we
  1817. // are on a server doing multiple detects.
  1818. //
  1819. if (Binding->DefaultAutoDetect) {
  1820. Adapter->DefaultAutoDetected = TRUE;
  1821. }
  1822. Adapter->AutoDetectResponse = TRUE;
  1823. break;
  1824. default:
  1825. //
  1826. // We are still initializing, or are processing auto-detect
  1827. // responses, not the right time to start updating stuff.
  1828. //
  1829. break;
  1830. }
  1831. }
  1832. //
  1833. // See if any packets are waiting for a RIP response.
  1834. //
  1835. if (Device->RipPacketCount > 0) {
  1836. RIP_PACKET UNALIGNED * RipPacket = (RIP_PACKET UNALIGNED *)(IpxHeader+1);
  1837. PBINDING Binding;
  1838. Binding = NIC_ID_TO_BINDING(Device, NIC_FROM_LOCAL_TARGET(&DatagramOptions.LocalTarget));
  1839. #ifdef DBG
  1840. // This could be we in the middle of IpxUnbindAdapter and IpxClosNdis.
  1841. if (Binding == NULL) {
  1842. DbgPrint("The binding %d has disappeared. Skip RipProcessResponse.\n", NIC_FROM_LOCAL_TARGET(&DatagramOptions.LocalTarget));
  1843. DbgPrint("The packet was received on adapter %p.\n",BindingContext);
  1844. }
  1845. #endif
  1846. if ((IpxPacketSize >= sizeof(IPX_HEADER) + sizeof(RIP_PACKET)) &&
  1847. (RipPacket->Operation == RIP_RESPONSE) &&
  1848. (RipPacket->NetworkEntry.NetworkNumber != 0xffffffff) &&
  1849. (Binding != NULL)) {
  1850. RipProcessResponse(
  1851. Device,
  1852. &DatagramOptions.LocalTarget,
  1853. RipPacket);
  1854. }
  1855. }
  1856. //
  1857. // See if this is a RIP response for our virtual network
  1858. // and we are the only person who could respond to it.
  1859. // We also respond to general queries on WAN lines since
  1860. // we are the only machine on it.
  1861. //
  1862. if (Device->RipResponder) {
  1863. PRIP_PACKET RipPacket =
  1864. (PRIP_PACKET)(IpxHeader+1);
  1865. if ((IpxPacketSize >= sizeof(IPX_HEADER) + sizeof(RIP_PACKET)) &&
  1866. (RipPacket->Operation == RIP_REQUEST) &&
  1867. ((RipPacket->NetworkEntry.NetworkNumber == Device->VirtualNetworkNumber) ||
  1868. (Adapter->MacInfo.MediumAsync && (RipPacket->NetworkEntry.NetworkNumber == 0xffffffff)))) {
  1869. //
  1870. // Update this so our response goes out correctly.
  1871. //
  1872. if (!IsLoopback && Adapter->MacInfo.MediumType == NdisMedium802_5) {
  1873. MacUpdateSourceRouting (IDENTIFIER_IPX, Adapter, Header, HeaderBufferSize);
  1874. }
  1875. RipSendResponse(
  1876. Binding,
  1877. (TDI_ADDRESS_IPX UNALIGNED *)(IpxHeader->SourceNetwork),
  1878. &DatagramOptions.LocalTarget);
  1879. }
  1880. }
  1881. #if DBG
  1882. ReceiveFlag = IPX_PACKET_LOG_RCV_RIP | IPX_PACKET_LOG_RCV_ALL;
  1883. #endif
  1884. //
  1885. // See if the RIP upper driver wants it too.
  1886. //
  1887. goto RipIndication;
  1888. }
  1889. }
  1890. IpxDereferenceAdapter(Adapter);
  1891. IpxDereferenceBinding1(Binding, BREF_ADAPTER_ACCESS);
  1892. #ifdef IPX_PACKET_LOG
  1893. if (PACKET_LOG(ReceiveFlag)) {
  1894. IpxLogPacket(
  1895. FALSE,
  1896. DestMacAddress,
  1897. DatagramOptions.LocalTarget.MacAddress,
  1898. (USHORT)IpxPacketSize,
  1899. IpxHeader,
  1900. IpxHeader+1);
  1901. }
  1902. #endif
  1903. return NDIS_STATUS_SUCCESS;
  1904. //
  1905. // These are the failure routines for the various media types.
  1906. // They only differ in the debug logging.
  1907. //
  1908. NotValid802_3:
  1909. #ifdef SNMP
  1910. ++IPX_MIB_ENTRY(Device, SysInReceives);
  1911. ++IPX_MIB_ENTRY(Device, SysInHdrErrors);
  1912. #endif SNMP
  1913. IpxDereferenceAdapter(Adapter);
  1914. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1915. #ifdef IPX_PACKET_LOG
  1916. if (PACKET_LOG(IPX_PACKET_LOG_RCV_ALL)) {
  1917. IpxLogPacket(FALSE, Header, Header+6, (USHORT)PacketSize, LookaheadBuffer, (PUCHAR)LookaheadBuffer + sizeof(IPX_HEADER));
  1918. }
  1919. #endif
  1920. return NDIS_STATUS_SUCCESS;
  1921. NotValid802_5:
  1922. #ifdef SNMP
  1923. ++IPX_MIB_ENTRY(Device, SysInReceives);
  1924. ++IPX_MIB_ENTRY(Device, SysInHdrErrors);
  1925. #endif SNMP
  1926. IpxDereferenceAdapter(Adapter);
  1927. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1928. #ifdef IPX_PACKET_LOG
  1929. if (PACKET_LOG(IPX_PACKET_LOG_RCV_ALL)) {
  1930. IpxLogPacket(FALSE, Header+2, Header+8, (USHORT)PacketSize, LookaheadBuffer, (PUCHAR)LookaheadBuffer + sizeof(IPX_HEADER));
  1931. }
  1932. #endif
  1933. return NDIS_STATUS_SUCCESS;
  1934. NotValidFddi:
  1935. #ifdef SNMP
  1936. ++IPX_MIB_ENTRY(Device, SysInReceives);
  1937. ++IPX_MIB_ENTRY(Device, SysInHdrErrors);
  1938. #endif SNMP
  1939. IpxDereferenceAdapter(Adapter);
  1940. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1941. NotValidLoopback:
  1942. #ifdef SNMP
  1943. ++IPX_MIB_ENTRY(Device, SysInReceives);
  1944. ++IPX_MIB_ENTRY(Device, SysInHdrErrors);
  1945. #endif SNMP
  1946. #ifdef IPX_PACKET_LOG
  1947. if (PACKET_LOG(IPX_PACKET_LOG_RCV_ALL)) {
  1948. IpxLogPacket(FALSE, Header+1, Header+7, (USHORT)PacketSize, LookaheadBuffer, (PUCHAR)LookaheadBuffer + sizeof(IPX_HEADER));
  1949. }
  1950. #endif
  1951. return NDIS_STATUS_SUCCESS;
  1952. } /* IpxReceiveIndication */
  1953. VOID
  1954. IpxReceiveComplete(
  1955. IN NDIS_HANDLE BindingContext
  1956. )
  1957. /*++
  1958. Routine Description:
  1959. This routine receives control from the physical provider as an
  1960. indication that a connection(less) frame has been received on the
  1961. physical link. We dispatch to the correct packet handler here.
  1962. Arguments:
  1963. BindingContext - The Adapter Binding specified at initialization time.
  1964. Return Value:
  1965. None
  1966. --*/
  1967. {
  1968. PADAPTER Adapter = (PADAPTER)BindingContext;
  1969. PREQUEST Request;
  1970. PADDRESS_FILE AddressFile;
  1971. PLIST_ENTRY linkage;
  1972. CTELockHandle OldIrq;
  1973. PDEVICE Device = IpxDevice;
  1974. PIRP pIrp;
  1975. PLIST_ENTRY pLE;
  1976. //
  1977. // Complete all pending receives. Do a quick check
  1978. // without the lock.
  1979. //
  1980. while (!IsListEmpty (&Adapter->RequestCompletionQueue)) {
  1981. linkage = IPX_REMOVE_HEAD_LIST(
  1982. &Adapter->RequestCompletionQueue,
  1983. Adapter->DeviceLock);
  1984. if (!IPX_LIST_WAS_EMPTY (&Adapter->RequestCompletionQueue, linkage)) {
  1985. Request = LIST_ENTRY_TO_REQUEST(linkage);
  1986. AddressFile = REQUEST_OPEN_CONTEXT(Request);
  1987. IPX_DEBUG (RECEIVE, ("Completing RDG on %lx\n", AddressFile));
  1988. IoSetCancelRoutine (Request, (PDRIVER_CANCEL)NULL);
  1989. IpxCompleteRequest(Request);
  1990. IpxFreeRequest(Adapter->Device, Request);
  1991. IpxDereferenceAddressFileSync (AddressFile, AFREF_RCV_DGRAM);
  1992. } else {
  1993. //
  1994. // IPX_REMOVE_HEAD_LIST returned nothing, so don't
  1995. // bother looping back.
  1996. //
  1997. break;
  1998. }
  1999. }
  2000. //
  2001. // Unwind this loop for speed.
  2002. //
  2003. if (IpxDevice->AnyUpperDriverBound) {
  2004. // PDEVICE Device = IpxDevice;
  2005. if ((Device->UpperDriverBound[0]) &&
  2006. (Device->ReceiveCompletePending[0])) {
  2007. (*Device->UpperDrivers[0].ReceiveCompleteHandler)(
  2008. (USHORT)1); // Fix NIC ID or remove.
  2009. Device->ReceiveCompletePending[0] = FALSE;
  2010. }
  2011. if ((Device->UpperDriverBound[1]) &&
  2012. (Device->ReceiveCompletePending[1])) {
  2013. (*Device->UpperDrivers[1].ReceiveCompleteHandler)(
  2014. (USHORT)1); // Fix NIC ID or remove.
  2015. Device->ReceiveCompletePending[1] = FALSE;
  2016. }
  2017. if ((Device->UpperDriverBound[2]) &&
  2018. (Device->ReceiveCompletePending[2])) {
  2019. (*Device->UpperDrivers[2].ReceiveCompleteHandler)(
  2020. (USHORT)1); // Fix NIC ID or remove.
  2021. Device->ReceiveCompletePending[2] = FALSE;
  2022. }
  2023. }
  2024. CTEGetLock(&Device->Lock, &OldIrq);
  2025. if (pRtInfo)
  2026. {
  2027. CTEFreeLock(&Device->Lock, OldIrq);
  2028. IpxReferenceRt(pRtInfo, RT_EXTRACT);
  2029. while((pLE = ExInterlockedRemoveHeadList(&pRtInfo->CompletedIrps,
  2030. &pRtInfo->Lock)) != NULL)
  2031. {
  2032. pIrp = LIST_ENTRY_TO_REQUEST(pLE);
  2033. CTEAssert(pIrp);
  2034. IpxPrint0("IpxReceiveComplete: Completing extracted irp\n");
  2035. NTIoComplete(pIrp, (NTSTATUS)-1,(ULONG)-1);
  2036. }
  2037. IpxDereferenceRt(pRtInfo, RT_EXTRACT);
  2038. } else {
  2039. CTEFreeLock(&Device->Lock, OldIrq);
  2040. }
  2041. //
  2042. // If there are any Ntf completions, do them. These ntf completions
  2043. // are only if we discovered the address of one of our adapters.
  2044. //
  2045. while((pLE = ExInterlockedRemoveHeadList(&Device->NicNtfComplQueue, &Device ->Lock)) != NULL)
  2046. {
  2047. pIrp = LIST_ENTRY_TO_REQUEST(pLE);
  2048. CTEAssert(pIrp);
  2049. IpxPrint0("IpxReceiveComplete: Completing Nic Ntf irp\n");
  2050. NTIoComplete(pIrp, (NTSTATUS)-1, (ULONG)-1);
  2051. IpxDereferenceDevice (Device, DREF_NIC_NOTIFY);
  2052. }
  2053. } /* IpxReceiveComplete */
  2054. NTSTATUS
  2055. IpxUpdateBindingNetwork(
  2056. IN PDEVICE Device,
  2057. IN PBINDING Binding,
  2058. IN ULONG Network
  2059. )
  2060. /*++
  2061. Routine Description:
  2062. This routine is called when we have decided that we now know
  2063. the network number for a binding which we previously thought
  2064. was zero.
  2065. Arguments:
  2066. Device - The IPX device.
  2067. Binding - The binding being updated.
  2068. Network - The new network number.
  2069. Return Value:
  2070. The status of the operation.
  2071. --*/
  2072. {
  2073. NTSTATUS Status;
  2074. PADDRESS Address;
  2075. ULONG CurrentHash;
  2076. PLIST_ENTRY p;
  2077. IPX_DEFINE_LOCK_HANDLE (LockHandle)
  2078. PBINDING Loopback = NULL;
  2079. NDIS_REQUEST IpxRequest;
  2080. PNETWORK_ADDRESS_LIST AddrList;
  2081. PNETWORK_ADDRESS Addr;
  2082. NETWORK_ADDRESS_IPX *TdiAddress;
  2083. PIPX_DELAYED_NDISREQUEST_ITEM DelayedNdisItem;
  2084. //
  2085. // Only binding set members should have these different,
  2086. // and they will not have a network of 0.
  2087. //
  2088. Status = RipInsertLocalNetwork(
  2089. Network,
  2090. Binding->NicId,
  2091. Binding->Adapter->NdisBindingHandle,
  2092. (USHORT)((839 + Binding->MediumSpeed) / Binding->MediumSpeed));
  2093. if (Status == STATUS_SUCCESS) {
  2094. Binding->LocalAddress.NetworkAddress = Network;
  2095. //
  2096. // Loopback Adapter might need to be primed too [shreem]
  2097. //
  2098. if (!Device->VirtualNetwork) {
  2099. Loopback = NIC_ID_TO_BINDING(Device, LOOPBACK_NIC_ID);
  2100. if (( 0 == Loopback->LocalAddress.NetworkAddress) ||
  2101. (REORDER_ULONG(INITIAL_LOOPBACK_NET_ADDRESS) == Loopback->LocalAddress.NetworkAddress)) {
  2102. Loopback->LocalAddress.NetworkAddress = Network;
  2103. RtlCopyMemory (Loopback->LocalAddress.NodeAddress, Binding->LocalAddress.NodeAddress, 6);
  2104. RtlCopyMemory (Loopback->LocalMacAddress.Address, Binding->LocalAddress.NodeAddress, 6);
  2105. }
  2106. }
  2107. //
  2108. // Update the device address if we have no virtual net
  2109. // and there is one binding (!Device->MultiCardZeroVirtual)
  2110. // or this is the first binding, which is the one we
  2111. // appear to be if a) we have no virtual net defined and
  2112. // b) we are bound to multiple cards.
  2113. //
  2114. if ((!Device->MultiCardZeroVirtual) || (Binding->NicId == FIRST_REAL_BINDING)) {
  2115. if (!Device->VirtualNetwork) {
  2116. Device->SourceAddress.NetworkAddress = Network;
  2117. //
  2118. // Scan through all the addresses that exist and modify
  2119. // their pre-constructed local IPX address to reflect
  2120. // the new local net and node.
  2121. //
  2122. IPX_GET_LOCK (&Device->Lock, &LockHandle);
  2123. for (CurrentHash = 0; CurrentHash < IPX_ADDRESS_HASH_COUNT; CurrentHash++) {
  2124. for (p = Device->AddressDatabases[CurrentHash].Flink;
  2125. p != &Device->AddressDatabases[CurrentHash];
  2126. p = p->Flink) {
  2127. Address = CONTAINING_RECORD (p, ADDRESS, Linkage);
  2128. Address->LocalAddress.NetworkAddress = Network;
  2129. }
  2130. }
  2131. IPX_FREE_LOCK (&Device->Lock, LockHandle);
  2132. //
  2133. // Let SPX know because it fills in its own headers.
  2134. //
  2135. if (Device->UpperDriverBound[IDENTIFIER_SPX]) {
  2136. IPX_DEFINE_LOCK_HANDLE(LockHandle1)
  2137. IPX_PNP_INFO IpxPnPInfo;
  2138. IpxPnPInfo.NewReservedAddress = TRUE;
  2139. IpxPnPInfo.NetworkAddress = Network;
  2140. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  2141. RtlCopyMemory(IpxPnPInfo.NodeAddress, Binding->LocalAddress.NodeAddress, 6);
  2142. NIC_HANDLE_FROM_NIC(IpxPnPInfo.NicHandle, Binding->NicId);
  2143. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  2144. //
  2145. // give the PnP indication
  2146. //
  2147. (*Device->UpperDrivers[IDENTIFIER_SPX].PnPHandler) (
  2148. IPX_PNP_ADDRESS_CHANGE,
  2149. &IpxPnPInfo);
  2150. IPX_DEBUG(AUTO_DETECT, ("IPX_PNP_ADDRESS_CHANGED to SPX: net addr: %lx\n", Network));
  2151. }
  2152. }
  2153. }
  2154. } else if (Status == STATUS_DUPLICATE_NAME) {
  2155. //
  2156. // If it was a duplicate we still set the binding's local
  2157. // address to the value so we can detect binding sets.
  2158. //
  2159. Binding->LocalAddress.NetworkAddress = Network;
  2160. }
  2161. #if 0
  2162. //
  2163. // Set an Ndis OID. This should overwrite any previous setting (they claim).
  2164. //
  2165. if (!Binding->Adapter->MacInfo.MediumAsync) {
  2166. int count, i;
  2167. int size;
  2168. NTSTATUS NdisStatus = STATUS_SUCCESS;
  2169. PADAPTER Adapter;
  2170. Adapter = Binding->Adapter;
  2171. for (count=0, i=0; i < ISN_FRAME_TYPE_MAX; i++) {
  2172. if (Adapter->Bindings[i]) {
  2173. count++;
  2174. }
  2175. }
  2176. IPX_DEBUG(PNP, ("This adapter has %d valid bindings\n", count));
  2177. size = FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address) + count * (FIELD_OFFSET(NETWORK_ADDRESS, Address) + sizeof(NETWORK_ADDRESS_IPX));
  2178. AddrList = IpxAllocateMemory(
  2179. size,
  2180. MEMORY_ADAPTER,
  2181. "QoS specific stuff");
  2182. if (AddrList != NULL) {
  2183. AddrList->AddressCount = count;
  2184. AddrList->AddressType = NDIS_PROTOCOL_ID_IPX;
  2185. count = 0;
  2186. Addr = &AddrList->Address[0];
  2187. for (i=0; i < ISN_FRAME_TYPE_MAX; i++) {
  2188. if (Adapter->Bindings[i]) {
  2189. Addr->AddressLength = sizeof(NETWORK_ADDRESS_IPX);
  2190. Addr->AddressType = NDIS_PROTOCOL_ID_IPX;
  2191. TdiAddress = (NETWORK_ADDRESS_IPX *) &Addr->Address[0];
  2192. TdiAddress->NetworkAddress = Adapter->Bindings[i]->LocalAddress.NetworkAddress;
  2193. RtlCopyMemory (TdiAddress->NodeAddress, Adapter->Bindings[i]->LocalAddress.NodeAddress, 6);
  2194. TdiAddress->Socket = 0;
  2195. IPX_DEBUG(PNP, ("Node is %2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x, ",
  2196. TdiAddress->NodeAddress[0], TdiAddress->NodeAddress[1],
  2197. TdiAddress->NodeAddress[2], TdiAddress->NodeAddress[3],
  2198. TdiAddress->NodeAddress[4], TdiAddress->NodeAddress[5]));
  2199. IPX_DEBUG(PNP, ("Network is %lx\n", REORDER_ULONG (TdiAddress->NetworkAddress)));
  2200. count++;
  2201. Addr = (PNETWORK_ADDRESS) (((PUCHAR)(&AddrList->Address[0])) + count * (FIELD_OFFSET(NETWORK_ADDRESS, Address) + sizeof(NETWORK_ADDRESS_IPX)));
  2202. }
  2203. }
  2204. IPX_DEBUG(PNP, ("Getting ready to call NDIS\n"));
  2205. IpxRequest.RequestType = NdisRequestSetInformation;
  2206. IpxRequest.DATA.SET_INFORMATION.Oid = OID_GEN_NETWORK_LAYER_ADDRESSES;
  2207. IpxRequest.DATA.SET_INFORMATION.InformationBuffer = AddrList;
  2208. IpxRequest.DATA.SET_INFORMATION.InformationBufferLength = size;
  2209. DelayedNdisItem = (PIPX_DELAYED_NDISREQUEST_ITEM)IpxAllocateMemory (
  2210. sizeof(IPX_DELAYED_NDISREQUEST_ITEM),
  2211. MEMORY_WORK_ITEM,
  2212. "Work Item");
  2213. if ( DelayedNdisItem ) {
  2214. IPX_DEFINE_LOCK_HANDLE(LockHandle)
  2215. IPX_GET_LOCK (&Adapter->Lock, &LockHandle);
  2216. if (Adapter->State != ADAPTER_STATE_STOPPING) {
  2217. IpxReferenceDevice (Device, DREF_ADAPTER);
  2218. IpxReferenceAdapter1(Adapter,ADAP_REF_NDISREQ);
  2219. DelayedNdisItem->Adapter = (PVOID)Adapter;
  2220. DelayedNdisItem->IpxRequest = IpxRequest;
  2221. DelayedNdisItem->AddrListSize = size;
  2222. ExInitializeWorkItem(
  2223. &DelayedNdisItem->WorkItem,
  2224. IpxDelayedSubmitNdisRequest,
  2225. (PVOID)DelayedNdisItem);
  2226. ExQueueWorkItem(
  2227. &DelayedNdisItem->WorkItem,
  2228. DelayedWorkQueue);
  2229. IPX_DEBUG(PNP,("Queued the worker thread for IpxDelayedSubmitNdisRequest\n"));
  2230. }
  2231. #ifdef DBG
  2232. else {
  2233. IPX_DEBUG(PNP,("The adapter %p is stopping, skip IpxDelyedSbmitNdisRequest\n",Adapter));
  2234. IpxFreeMemory (
  2235. DelayedNdisItem,
  2236. sizeof (IPX_DELAYED_NDISREQUEST_ITEM),
  2237. MEMORY_WORK_ITEM,
  2238. "Work Item");
  2239. }
  2240. #endif
  2241. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  2242. } else {
  2243. IPX_DEBUG(PNP, ("Failed to allocate work-item for NdisRequest."));
  2244. }
  2245. } else {
  2246. DbgPrint("IPX:IpxAllocateMemory failed, skipped QoS Registration..\n");
  2247. }
  2248. } else {
  2249. IPX_DEBUG(PNP, ("Async Medium - skipping QoS OID\n"));
  2250. }
  2251. #endif
  2252. Binding->fInfoIndicated = FALSE;
  2253. if ((p = ExInterlockedRemoveHeadList(
  2254. &Device->NicNtfQueue,
  2255. &Device->Lock)) != NULL)
  2256. {
  2257. PREQUEST Request;
  2258. Request = LIST_ENTRY_TO_REQUEST(p);
  2259. IPX_DEBUG(BIND, ("IpxStatus: Got address of binding\n"));
  2260. Status = GetNewNics(Device, Request, FALSE, NULL, 0, TRUE);
  2261. //
  2262. // If not success, we don't queue back the irp. It has
  2263. // already been queued or completed
  2264. //
  2265. if (Status == STATUS_PENDING)
  2266. {
  2267. IPX_DEBUG(BIND, ("New address Irp request not responding properly. Status = (%lx)\n", Status));
  2268. }
  2269. else
  2270. {
  2271. KIRQL OldIrq;
  2272. //
  2273. // Status is SUCCESS
  2274. //
  2275. IoAcquireCancelSpinLock(&OldIrq);
  2276. IoSetCancelRoutine (Request, (PDRIVER_CANCEL)NULL);
  2277. IoReleaseCancelSpinLock(OldIrq);
  2278. REQUEST_STATUS(Request) = Status;
  2279. ExInterlockedInsertTailList(&Device->NicNtfComplQueue,REQUEST_LINKAGE(Request), &Device->Lock);
  2280. }
  2281. } else {
  2282. IPX_DEBUG(BIND, ("No IRPs available\n"));
  2283. }
  2284. return Status;
  2285. } /* IpxUpdateBindingNetwork */
  2286. INT
  2287. IpxReceivePacket (
  2288. IN NDIS_HANDLE ProtocolBindingContext,
  2289. IN PNDIS_PACKET Packet
  2290. )
  2291. /*++
  2292. Routine Description:
  2293. This routine receives control from the physical provider as an
  2294. indication that a frame has been received on the physical link.
  2295. The packet passed up from NDIS can be held on to by the TDI clients
  2296. that request TDI_EVENT_RECEIVE_EX_DATAGRAM events with us.
  2297. Arguments:
  2298. ProtocolBindingContext - The Adapter Binding specified at initialization time.
  2299. Packet - contains the packet received as well as some mediaspecific info.
  2300. Return Value:
  2301. return of IpxReceiveIndicationCommon(),
  2302. --*/
  2303. {
  2304. UINT HeaderBufferSize = NDIS_GET_PACKET_HEADER_SIZE(Packet);
  2305. UINT firstbufferLength, bufferLength;
  2306. PNDIS_BUFFER pFirstBuffer;
  2307. PUCHAR headerBuffer;
  2308. NTSTATUS ntStatus;
  2309. INT tdiClientCount = 0;
  2310. //
  2311. // Query the number of buffers, the first MDL's descriptor and the packet length
  2312. //
  2313. NdisGetFirstBufferFromPacket(Packet, // packet
  2314. &pFirstBuffer, // first buffer descriptor
  2315. &headerBuffer, // ptr to the start of packet
  2316. &firstbufferLength,// length of the header+lookahead
  2317. &bufferLength); // length of the bytes in the buffers
  2318. //
  2319. // ReceiveContext is the packet itself
  2320. //
  2321. ntStatus = IpxReceiveIndicationCommon (
  2322. ProtocolBindingContext,
  2323. Packet, // ReceiveContext
  2324. headerBuffer,
  2325. HeaderBufferSize,
  2326. headerBuffer + HeaderBufferSize, // LookaheadBuffer
  2327. firstbufferLength - HeaderBufferSize, // LookaheadBufferSize
  2328. bufferLength - HeaderBufferSize, // PacketSize - since the whole packet is indicated
  2329. pFirstBuffer, // pMdl
  2330. &tdiClientCount // tdi client count
  2331. );
  2332. IPX_DEBUG(RECEIVE, ("IpxReceivePacket: Tdi Client Count is: %lx\n", tdiClientCount));
  2333. return tdiClientCount;
  2334. } /* IpxReceivePacket */
  2335. BOOLEAN
  2336. IpxNewVirtualNetwork(
  2337. IN PDEVICE Device,
  2338. IN BOOLEAN NewVirtualNetwork
  2339. )
  2340. /*++
  2341. Routine Description:
  2342. If the virtualnetwork number changed, this function records this fact
  2343. in the device.
  2344. Called with the BINDACCESSLOCK held.
  2345. Arguments:
  2346. Device - Pointer to the Device.
  2347. NewVirtualNetwork - boolean to indicate if the virtual net# changed.
  2348. Return Value:
  2349. BOOLEAN - to indicate whether SPX's reserved address was changed.
  2350. --*/
  2351. {
  2352. NTSTATUS ntStatus;
  2353. UCHAR VirtualNode[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
  2354. UCHAR InitialLoopbackNodeAddress[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x02};
  2355. BOOLEAN ReservedAddrChanged = FALSE;
  2356. PBINDING Loopback = NULL, Binding = NULL;
  2357. if (Device->VirtualNetworkNumber) {
  2358. //
  2359. // Added the check for valid bindings so that we dont deref null bindings.
  2360. // Also the net number is useless without adapters. [Shreem]
  2361. // we could probably use a permanent loopback binding in future.
  2362. //
  2363. if (NewVirtualNetwork && Device->ValidBindings) {
  2364. //
  2365. // If a new one appeared.
  2366. //
  2367. ntStatus = RipInsertLocalNetwork(
  2368. Device->VirtualNetworkNumber,
  2369. 0, // NIC ID
  2370. NIC_ID_TO_BINDING(Device, 1)->Adapter->NdisBindingHandle,
  2371. 1);
  2372. if (ntStatus != STATUS_SUCCESS) {
  2373. //
  2374. // Log the appropriate error, then ignore the
  2375. // virtual network. If the error was
  2376. // INSUFFICIENT_RESOURCES, the RIP module
  2377. // will have already logged an error.
  2378. //
  2379. if (ntStatus == STATUS_DUPLICATE_NAME) {
  2380. IPX_DEBUG (AUTO_DETECT, ("Ignoring virtual network %lx, conflict\n", REORDER_ULONG (Device->VirtualNetworkNumber)));
  2381. IpxWriteResourceErrorLog(
  2382. Device->DeviceObject,
  2383. EVENT_IPX_INTERNAL_NET_INVALID,
  2384. 0,
  2385. REORDER_ULONG (Device->VirtualNetworkNumber));
  2386. }
  2387. Device->VirtualNetworkNumber = 0;
  2388. goto NoVirtualNetwork;
  2389. }
  2390. //
  2391. // If the number is non-zero now, a new one appeared
  2392. //
  2393. Device->VirtualNetwork = TRUE;
  2394. Device->MultiCardZeroVirtual = FALSE;
  2395. RtlCopyMemory(Device->SourceAddress.NodeAddress, VirtualNode, 6);
  2396. Device->SourceAddress.NetworkAddress = Device->VirtualNetworkNumber;
  2397. ReservedAddrChanged = TRUE;
  2398. //
  2399. // Loopback Adapter might need to be primed too [shreem]
  2400. //
  2401. if (Device->VirtualNetwork) {
  2402. Loopback = NIC_ID_TO_BINDING(Device, LOOPBACK_NIC_ID);
  2403. Loopback->LocalAddress.NetworkAddress = Device->VirtualNetworkNumber;
  2404. RtlCopyMemory (Loopback->LocalAddress.NodeAddress, InitialLoopbackNodeAddress, 6);
  2405. RtlCopyMemory (Loopback->LocalMacAddress.Address, InitialLoopbackNodeAddress, 6);
  2406. }
  2407. //
  2408. // If RIP is not bound, then this node is a RipResponder
  2409. //
  2410. if (!Device->UpperDriverBound[IDENTIFIER_RIP]) {
  2411. Device->RipResponder = TRUE;
  2412. }
  2413. }
  2414. } else {
  2415. NoVirtualNetwork:
  2416. Device->VirtualNetwork = FALSE;
  2417. //
  2418. // See if we need to be set up for the fake
  2419. // virtual network.
  2420. //
  2421. if (Device->ValidBindings > 1) {
  2422. CTEAssert (Device->VirtualNetworkOptional);
  2423. //
  2424. // In this case we return as our local node the
  2425. // address of the first card. We will also only
  2426. // direct SAP sends to that card.
  2427. //
  2428. Device->MultiCardZeroVirtual = TRUE;
  2429. } else {
  2430. Device->MultiCardZeroVirtual = FALSE;
  2431. }
  2432. if (NewVirtualNetwork) {
  2433. //
  2434. // The virtual network number disappeared this time
  2435. //
  2436. //
  2437. // Remove the prev. net # from the RIP tables here
  2438. //
  2439. RipAdjustForBindingChange (0, 0, IpxBindingDeleted);
  2440. //
  2441. // If we were a RipResponder, we are not anymore
  2442. //
  2443. if (Device->RipResponder) {
  2444. Device->RipResponder = FALSE;
  2445. }
  2446. }
  2447. //
  2448. // Since there is not virtual network number, SPX's reserved address is
  2449. // the address of the first binding. This could have changed because of
  2450. // several reasons: if there was a WAN binding only earlier and this time
  2451. // a LAN binding appeared, or if the first LAN binding disappeared. Instead
  2452. // of checking for all these conditions, check if the Device's sourceaddress
  2453. // and that of the first mis-match.
  2454. // NB uses the address of the first device always and hence does not need
  2455. // this mechanism to determine if this is a reserved address change.
  2456. //
  2457. if (NULL == (Binding = NIC_ID_TO_BINDING(Device, FIRST_REAL_BINDING))) {
  2458. Binding = NIC_ID_TO_BINDING(Device, LOOPBACK_NIC_ID);
  2459. }
  2460. if (!RtlEqualMemory( &Device->SourceAddress,
  2461. &Binding->LocalAddress,
  2462. FIELD_OFFSET(TDI_ADDRESS_IPX,Socket))) {
  2463. RtlCopyMemory( &Device->SourceAddress,
  2464. &Binding->LocalAddress,
  2465. FIELD_OFFSET(TDI_ADDRESS_IPX,Socket));
  2466. ReservedAddrChanged = TRUE;
  2467. }
  2468. }
  2469. #ifdef SNMP
  2470. *(UNALIGNED ULONG *)(IPX_MIB_ENTRY(Device, SysNetNumber)) = Device->SourceAddress.NetworkAddress;
  2471. *(UNALIGNED ULONG *)(IPX_MIB_ENTRY(Device, SysNode)) =
  2472. *(UNALIGNED ULONG *)(Device->SourceAddress.NodeAddress);
  2473. *(UNALIGNED USHORT *)(IPX_MIB_ENTRY(Device, SysNode)+4) =
  2474. *(UNALIGNED USHORT *)(Device->SourceAddress.NodeAddress+4);
  2475. #endif
  2476. return ReservedAddrChanged;
  2477. }
  2478. VOID
  2479. IpxBindAdapter(
  2480. OUT PNDIS_STATUS Status,
  2481. IN NDIS_HANDLE BindContext,
  2482. IN PNDIS_STRING DeviceName,
  2483. IN PVOID SystemSpecific1,
  2484. IN PVOID SystemSpecific2
  2485. )
  2486. /*++
  2487. Routine Description:
  2488. This routine receives a Plug and Play notification about a new
  2489. adapter in the machine. We are called here only if this adapter
  2490. is to be bound to us, so we don't make any checks for this.
  2491. Arguments:
  2492. Status - NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING
  2493. BindContext - context to represent this bind indication
  2494. DeviceName - Name of the adapter that appeared (e.g. \Device\Lance1)
  2495. SystemSpecific1/2 - Not used here
  2496. Return Value:
  2497. Status - NDIS_STATUS_SUCCESS
  2498. --*/
  2499. {
  2500. NTSTATUS ntStatus;
  2501. PDEVICE Device = IpxDevice;
  2502. PADAPTER Adapter = NULL;
  2503. CONFIG Config;
  2504. UINT i;
  2505. ULONG Temp, SuccessfulOpens=0;
  2506. PBINDING Binding;
  2507. BINDING_CONFIG ConfigBinding;
  2508. ULONG ValidBindings;
  2509. USHORT AutoDetectReject;
  2510. BOOLEAN NewVirtualNetwork = FALSE;
  2511. BOOLEAN FirstDevice = FALSE;
  2512. BOOLEAN ReservedAddrChanged = FALSE;
  2513. IPX_PNP_INFO IpxPnPInfo;
  2514. PLIST_ENTRY p = NULL;
  2515. PREQUEST Request = NULL;
  2516. NDIS_REQUEST IpxRequest;
  2517. PNETWORK_ADDRESS_LIST AddrList;
  2518. PNETWORK_ADDRESS Address;
  2519. NETWORK_ADDRESS_IPX UNALIGNED *TdiAddress;
  2520. IPX_DEFINE_LOCK_HANDLE(LockHandle1)
  2521. IPX_DEFINE_LOCK_HANDLE(LockHandle)
  2522. IPX_DEFINE_LOCK_HANDLE (OldIrq)
  2523. CTEAssert(KeGetCurrentIrql() < DISPATCH_LEVEL);
  2524. *Status = NDIS_STATUS_SUCCESS;
  2525. //
  2526. // This keeps track of the init time adapters
  2527. //
  2528. IPX_GET_LOCK(&Device->Lock, &LockHandle);
  2529. if (FALSE == Device->NoMoreInitAdapters) {
  2530. ++Device->InitTimeAdapters;
  2531. IPX_DEBUG(PNP,("BindAdapter: Count %d\n", Device->InitTimeAdapters));
  2532. }
  2533. IPX_FREE_LOCK(&Device->Lock, LockHandle);
  2534. //
  2535. // Used for error logging
  2536. //
  2537. Config.DriverObject = (PDRIVER_OBJECT)Device->DeviceObject;
  2538. Config.RegistryPathBuffer = Device->RegistryPathBuffer;
  2539. ConfigBinding.AdapterName = *DeviceName;
  2540. ConfigBinding.DriverObject = (PDRIVER_OBJECT)Device->DeviceObject;
  2541. //
  2542. // Read the registry to see if a virtual network number appeared/disappeared
  2543. //
  2544. ntStatus = IpxPnPGetVirtualNetworkNumber(&Config);
  2545. if (ntStatus != STATUS_SUCCESS) {
  2546. DbgPrint("IPX BindAdapter -> PnPGetVirtualNetworkNumber returned: %lx\n", ntStatus);
  2547. IPX_DEBUG(PNP, ("Could not read the vnet#: registrypathbuffer: %lx\n", Device->RegistryPathBuffer));
  2548. *Status = ntStatus;
  2549. goto InitFailed;
  2550. //return;
  2551. }
  2552. Temp = REORDER_ULONG (Config.Parameters[CONFIG_VIRTUAL_NETWORK]);
  2553. //
  2554. // If the virtual network number changed, record this fact.
  2555. //
  2556. if (Device->VirtualNetworkNumber != Temp) {
  2557. NewVirtualNetwork = TRUE;
  2558. Device->VirtualNetworkNumber = Temp;
  2559. }
  2560. Device->VirtualNetworkOptional = (BOOLEAN)(Config.Parameters[CONFIG_VIRTUAL_OPTIONAL] != 0);
  2561. IPX_DEBUG(PNP, ("Virtual net # is: %lx\n", Temp));
  2562. //
  2563. // For each FrameType and Network Number configured, initialize the
  2564. // FrameType array in the CONFIG_BINDING
  2565. //
  2566. IPX_DEBUG(PNP, ("IRQL is %x\n", KeGetCurrentIrql()));
  2567. ntStatus = IpxPnPGetAdapterParameters(
  2568. &Config,
  2569. DeviceName,
  2570. &ConfigBinding);
  2571. if (ntStatus != STATUS_SUCCESS) {
  2572. DbgPrint("IPX BindAdapter -> PnPGetAdapterParameters returned: %lx\n", ntStatus);
  2573. IPX_DEBUG(PNP, ("Could not read the adapter params: DeviceName: %lx\n", DeviceName->Buffer));
  2574. *Status = ntStatus;
  2575. goto InitFailed;
  2576. //return;
  2577. }
  2578. IPX_DEBUG(PNP, ("ConfigBinding.FrameTypeCount: %lx\n", ConfigBinding.FrameTypeCount));
  2579. //
  2580. // Reset the auto-detect state to init so that if a receive occurs on this binding
  2581. // before we can place this binding in the device's binding array, we know of it.
  2582. //
  2583. Device->AutoDetectState = AUTO_DETECT_STATE_INIT;
  2584. //
  2585. // Register adapter with NDIS; query the various parameters; get the WAN line count
  2586. // if this is a WAN adapter.
  2587. // Allocate the bindings corresponding to this adapter
  2588. //
  2589. for (i = 0; i < ConfigBinding.FrameTypeCount; i++) {
  2590. //
  2591. // If successful, this queues them on Device->InitialBindingList. not right now
  2592. // Adapter is NULL first time and is allocated then. In subsequent calls,
  2593. // it is not NULL and the bindings are hooked to this adapter.
  2594. ntStatus = IpxBindToAdapter (Device, &ConfigBinding, &Adapter, i);
  2595. //
  2596. // If this failed because the adapter could not be bound
  2597. // to, then don't try any more frame types on this adapter.
  2598. // For other failures we do try the other frame types.
  2599. //
  2600. if (ntStatus == STATUS_DEVICE_DOES_NOT_EXIST) {
  2601. break;
  2602. }
  2603. //
  2604. // If the status is STATUS_NOT_SUPPORTED, then this frametype mapped to a previously
  2605. // initialized one. In this case, remove this index fron the FrameType array so that
  2606. // when we try to update the binding array, we dont have duplicates.
  2607. //
  2608. if (ntStatus == STATUS_NOT_SUPPORTED) {
  2609. ULONG j;
  2610. //
  2611. // Remove this frametype from the FrameType array.
  2612. //
  2613. for (j = i+1; j < ConfigBinding.FrameTypeCount; j++) {
  2614. ConfigBinding.FrameType[j-1] = ConfigBinding.FrameType[j];
  2615. }
  2616. --ConfigBinding.FrameTypeCount;
  2617. //
  2618. // Decrement so we see the one just moved up.
  2619. //
  2620. --i;
  2621. #if DBG
  2622. for (j = 0; j < ISN_FRAME_TYPE_MAX; j++) {
  2623. IPX_DEBUG (AUTO_DETECT, ("%d: type %d, net %d, auto %d\n",
  2624. j, ConfigBinding.FrameType[j], ConfigBinding.NetworkNumber[j], ConfigBinding.AutoDetect[j]));
  2625. }
  2626. #endif
  2627. continue;
  2628. }
  2629. if (ntStatus != STATUS_SUCCESS) {
  2630. continue;
  2631. }
  2632. if (ConfigBinding.AutoDetect[i]) {
  2633. Device->AutoDetect = TRUE;
  2634. }
  2635. CTEAssert(Adapter);
  2636. ++SuccessfulOpens;
  2637. //
  2638. // Even for WAN adapters, the FrameTypeCount is set to 4. We only need to
  2639. // allocate one binding for WAN; the others come later.
  2640. //
  2641. if (Adapter->MacInfo.MediumAsync) {
  2642. break;
  2643. }
  2644. }
  2645. if (SuccessfulOpens == 0) {
  2646. *Status = NDIS_STATUS_FAILURE;
  2647. goto InitFailed;
  2648. }
  2649. ASSERT(SystemSpecific2 != NULL);
  2650. Adapter->PNPContext = SystemSpecific2;
  2651. //
  2652. // Place all the bindings corresponding to this adapter in the binding array
  2653. // Also resolve binding sets for non-autodetect bindings.
  2654. //
  2655. //
  2656. // Obtain lock to the Binding related stuff.
  2657. //
  2658. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  2659. IpxPnPUpdateBindingArray (Device, Adapter, &ConfigBinding);
  2660. //
  2661. // Release access to the Binding related stuff.
  2662. //
  2663. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  2664. //
  2665. // If at least one card appeared here, set our state
  2666. // to open
  2667. //
  2668. // what if all these bindings are eliminated - then
  2669. // the state is not open...
  2670. //
  2671. if (Device->ValidBindings > 0) {
  2672. if (Device->State == DEVICE_STATE_LOADED) {
  2673. FirstDevice = TRUE;
  2674. Device->State = DEVICE_STATE_OPEN;
  2675. }
  2676. }
  2677. //
  2678. // We don't do auto-detect/bindingsets for WAN lines: skip over.
  2679. //
  2680. if (Adapter->MacInfo.MediumAsync) {
  2681. goto jump_wan;
  2682. }
  2683. //
  2684. // If this adapter already has a configured network number, and
  2685. // the network number is already plumbed in the binding, we dont need
  2686. // to Autodetect [MS]. NtBug 101876
  2687. //
  2688. for (i = 0; i < ISN_FRAME_TYPE_MAX; i++) {
  2689. Binding = Adapter->Bindings[i];
  2690. //
  2691. // Skip empty binding slots
  2692. if (!Binding) {
  2693. continue;
  2694. }
  2695. // Bindings that were configured
  2696. // for a certain network number, we inserted those above.
  2697. if (Binding->ConfiguredNetworkNumber != 0) {
  2698. goto AlreadyConfigured;
  2699. }
  2700. }
  2701. //
  2702. // Auto-detect the network number. Update the results for only the
  2703. // bindings corresponding to this adapter
  2704. //
  2705. //
  2706. // Queue a request to discover our locally attached
  2707. // adapter addresses. This must succeed because we
  2708. // just allocated our send packet pool. We need
  2709. // to wait for this, either because we are
  2710. // auto-detecting or because we need to determine
  2711. // if there are multiple cards on the same network.
  2712. //
  2713. KeInitializeEvent(
  2714. &Device->AutoDetectEvent,
  2715. NotificationEvent,
  2716. FALSE
  2717. );
  2718. Device->AutoDetectState = AUTO_DETECT_STATE_RUNNING;
  2719. //
  2720. // Make this 0; after we are done waiting, which means
  2721. // the packet has been completed, we set it to the
  2722. // correct value.
  2723. //
  2724. // Device->IncludedHeaderOffset = 0;
  2725. IPX_BEGIN_SYNC (&SyncContext);
  2726. ntStatus = RipQueueRequest (0xffffffff, RIP_REQUEST);
  2727. IPX_END_SYNC (&SyncContext);
  2728. if (ntStatus != STATUS_PENDING) {
  2729. DbgPrint("IPX: RipQueueRequest returned status %x, skip auto-detect\n", ntStatus);
  2730. } else {
  2731. //
  2732. // This is set when this rip send completes.
  2733. //
  2734. NTSTATUS status = STATUS_SUCCESS;
  2735. IPX_DEBUG (AUTO_DETECT, ("Waiting for AutoDetectEvent\n"));
  2736. status = KeWaitForSingleObject(
  2737. &Device->AutoDetectEvent,
  2738. Executive,
  2739. KernelMode,
  2740. TRUE,
  2741. (PLARGE_INTEGER)NULL
  2742. );
  2743. }
  2744. AlreadyConfigured:
  2745. Device->AutoDetectState = AUTO_DETECT_STATE_PROCESSING;
  2746. //
  2747. // Now that we are done receiving responses, insert the
  2748. // current network number for every auto-detect binding
  2749. // to the rip database.
  2750. //
  2751. //
  2752. // Obtain exclusive access to the Binding related stuff.
  2753. //
  2754. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  2755. //
  2756. // Note, here we go thru' only the bindings corresponding to this adapter
  2757. //
  2758. for (i = 0; i < ISN_FRAME_TYPE_MAX; i++) {
  2759. Binding = Adapter->Bindings[i];
  2760. //
  2761. // Skip empty binding slots or bindings that were configured
  2762. // for a certain network number, we inserted those above.
  2763. // If no network number was detected, also skip it.
  2764. //
  2765. if ((!Binding) ||
  2766. (Binding->ConfiguredNetworkNumber != 0) ||
  2767. (Binding->TentativeNetworkAddress == 0)) {
  2768. continue;
  2769. }
  2770. IPX_DEBUG (AUTO_DETECT, ("Final score for %lx on %lx is %d - %d\n",
  2771. REORDER_ULONG(Binding->TentativeNetworkAddress),
  2772. Binding,
  2773. Binding->MatchingResponses,
  2774. Binding->NonMatchingResponses));
  2775. //
  2776. // We don't care about the status.
  2777. //
  2778. ntStatus = RipInsertLocalNetwork(
  2779. Binding->TentativeNetworkAddress,
  2780. Binding->NicId,
  2781. Binding->Adapter->NdisBindingHandle,
  2782. (USHORT)((839 + Binding->MediumSpeed) / Binding->MediumSpeed));
  2783. if ((ntStatus != STATUS_SUCCESS) &&
  2784. (ntStatus != STATUS_DUPLICATE_NAME)) {
  2785. //
  2786. // We failed to insert, keep it at zero, hopefully
  2787. // we will be able to update later.
  2788. //
  2789. #if DBG
  2790. DbgPrint ("IPX: Could not insert net %lx for binding %lx\n",
  2791. REORDER_ULONG(Binding->LocalAddress.NetworkAddress),
  2792. Binding);
  2793. #endif
  2794. CTEAssert (Binding->LocalAddress.NetworkAddress == 0);
  2795. } else {
  2796. Binding->LocalAddress.NetworkAddress = Binding->TentativeNetworkAddress;
  2797. }
  2798. Binding->LocalAddress.NetworkAddress = Binding->TentativeNetworkAddress;
  2799. }
  2800. // ValidBindings = Device->BindingCount;
  2801. ValidBindings = Device->ValidBindings;
  2802. // if (Device->AutoDetect) {
  2803. ValidBindings = IpxResolveAutoDetect (Device, ValidBindings, &LockHandle1, &Device->RegistryPath, Adapter);
  2804. //}
  2805. //
  2806. // Adjust all the indices by the number of AutoDetect bindings thrown away
  2807. //
  2808. // AutoDetectReject = (USHORT)(Device->BindingCount - ValidBindings);
  2809. AutoDetectReject = (USHORT)(Device->ValidBindings - ValidBindings);
  2810. Device->HighestLanNicId -= AutoDetectReject;
  2811. Device->HighestExternalNicId -= AutoDetectReject;
  2812. Device->HighestType20NicId -= AutoDetectReject;
  2813. Device->SapNicCount -= AutoDetectReject;
  2814. Device->ValidBindings = (USHORT)ValidBindings;
  2815. //
  2816. // Now see if any bindings are actually on the same
  2817. // network. This updates the Device->HighestExternalNicId
  2818. // and Device->HighestType20NicId, SapNicCount, HighestLanNicId
  2819. //
  2820. //
  2821. // Do this only for the auto-detect bindings
  2822. // check this
  2823. //
  2824. //if (Device->AutoDetect) {
  2825. IpxResolveBindingSets (Device, Device->HighestExternalNicId);
  2826. //}
  2827. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  2828. jump_wan:
  2829. IPX_DEBUG(PNP, ("BindingCount: %lu\n", Device->BindingCount));
  2830. IPX_DEBUG(PNP, ("ValidBindings: %lu\n", Device->ValidBindings));
  2831. IPX_DEBUG(PNP, ("HighestLanNicId: %lu\n", Device->HighestLanNicId));
  2832. IPX_DEBUG(PNP, ("HighestExternalNicId: %lu\n", Device->HighestExternalNicId));
  2833. IPX_DEBUG(PNP, ("HighestType20NicId: %lu\n", Device->HighestType20NicId));
  2834. IPX_DEBUG(PNP, ("SapNicCount: %lu\n", Device->SapNicCount));
  2835. IPX_DEBUG(PNP, ("BindingArray: %lx\n", Device->Bindings));
  2836. //
  2837. // Enable this regardless of whether any of our clients enabled b'cast.
  2838. // NB always enables it, so we are fine.
  2839. //
  2840. // Since we dont increment the Broadcast count in the device, we will disable b'casts
  2841. // correctly if the count drops to 0.
  2842. //
  2843. // If the ISN clients appear before the adapters, they increment the BCount, but
  2844. // since the ValidBindings is 0, all works. Then, when the adapters appear, we enable
  2845. // the broadcasts here.
  2846. //
  2847. // If the adapters appear before the ISN clients, then the broadcast is enabled on
  2848. // the adapters here and the adapter's flag is set to indicate this, which will prevent
  2849. // any further calls to NDIS when the ISN clients force an IpxAddBroadcast.
  2850. //
  2851. if (!Device->EnableBroadcastPending) {
  2852. Device->EnableBroadcastPending = TRUE;
  2853. IpxBroadcastOperation((PVOID)TRUE);
  2854. }
  2855. //
  2856. // For multiple adapters, use the offset of the first...why not.
  2857. //
  2858. #if 0
  2859. Device->IncludedHeaderOffset = Device->Bindings[1]->DefHeaderSize;
  2860. #endif
  2861. Device->IncludedHeaderOffset = MAC_HEADER_SIZE;
  2862. //
  2863. // If we already registered a virtual network with the loopback adapter, remove it.
  2864. //
  2865. if (NewVirtualNetwork) {
  2866. if (!Device->UpperDriverBound[IDENTIFIER_RIP]) {
  2867. PIPX_ROUTE_ENTRY RouteEntry = NULL;
  2868. ULONG Segment;
  2869. Segment = RipGetSegment ((PUCHAR)&Temp);
  2870. IPX_GET_LOCK (&Device->SegmentLocks[Segment], &LockHandle);
  2871. RouteEntry = RipGetRoute (Segment, (PUCHAR)&Temp);
  2872. if (RouteEntry != (PIPX_ROUTE_ENTRY)NULL) {
  2873. RipDeleteRoute (Segment, RouteEntry);
  2874. IPX_FREE_LOCK (&Device->SegmentLocks[Segment], LockHandle);
  2875. IpxFreeMemory (RouteEntry, sizeof(IPX_ROUTE_ENTRY), MEMORY_RIP, "RouteEntry");
  2876. IPX_DEBUG(BIND, ("Removed %lx from routing table\n", Temp));
  2877. } else {
  2878. IPX_DEBUG(BIND, ("Couldnt find %lx in routing table\n", Temp));
  2879. IPX_FREE_LOCK (&Device->SegmentLocks[Segment], LockHandle);
  2880. }
  2881. IPX_DEBUG(PNP, ("Removed the route to LOOPBACK number\n"));
  2882. } else {
  2883. //
  2884. // Talk to PMay and figure this out.
  2885. //
  2886. IPX_DEBUG(BIND, ("******** PMAY needs to know about this? \n"));
  2887. //DbgBreakPoint();
  2888. }
  2889. }
  2890. //
  2891. // This function updates flags like RipResponder, MultiCardZeroVirtual, etc.
  2892. // If the VirtualNetwork number changed (NewVirtualNetwork is TRUE), it updates
  2893. // the Device structure and the RIP tables accordingly.
  2894. // It returns a boolean to indicate if SPX's reserved address changed.
  2895. //
  2896. ReservedAddrChanged = IpxNewVirtualNetwork(Device, NewVirtualNetwork);
  2897. //
  2898. // Update the values once the auto-detect bindings have been thrown away...
  2899. //
  2900. IpxPnPUpdateDevice(Device);
  2901. Device->AutoDetectState = AUTO_DETECT_STATE_DONE;
  2902. IPX_DEBUG (DEVICE, ("Node is %2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x, ",
  2903. Device->SourceAddress.NodeAddress[0], Device->SourceAddress.NodeAddress[1],
  2904. Device->SourceAddress.NodeAddress[2], Device->SourceAddress.NodeAddress[3],
  2905. Device->SourceAddress.NodeAddress[4], Device->SourceAddress.NodeAddress[5]));
  2906. IPX_DEBUG (DEVICE, ("Network is %lx\n",
  2907. REORDER_ULONG (Device->SourceAddress.NetworkAddress)));
  2908. //
  2909. // Change the address in the AddressFiles list to the address of this Adapter now.
  2910. //
  2911. IPX_DEBUG(BIND, ("REAL ADAPTERS? : %x\n", Device->RealAdapters));
  2912. if (FALSE == Device->RealAdapters ||
  2913. (REORDER_ULONG(INITIAL_LOOPBACK_NET_ADDRESS) == (NIC_ID_TO_BINDING(IpxDevice, LOOPBACK_NIC_ID))->LocalAddress.NetworkAddress)) {
  2914. PADDRESS_FILE AddrFile = NULL;
  2915. PLIST_ENTRY Current = NULL;
  2916. PBINDING Loopback = NULL, FirstNonZero = NULL, TempB = NULL;
  2917. PADDRESS AddrObj = NULL;
  2918. UINT k = 0;
  2919. //
  2920. // First change the Loopback Binding's network number to what we discovered.
  2921. //
  2922. Loopback = NIC_ID_TO_BINDING(Device, LOOPBACK_NIC_ID);
  2923. if (Loopback->LocalAddress.NetworkAddress == REORDER_ULONG(INITIAL_LOOPBACK_NET_ADDRESS)) {
  2924. //
  2925. // ideally we need to find the first non-zero network number
  2926. //
  2927. for (k = FIRST_REAL_BINDING; k <= IpxDevice->ValidBindings; k++) {
  2928. TempB = NIC_ID_TO_BINDING(IpxDevice, k);
  2929. if (!TempB) {
  2930. continue;
  2931. }
  2932. if (0 != TempB->LocalAddress.NetworkAddress) {
  2933. FirstNonZero = TempB;
  2934. IPX_DEBUG(BIND, ("#%lx Binding had a non zero netnum: %lx\n", k, TempB->LocalAddress.NetworkAddress));
  2935. Loopback->LocalAddress.NetworkAddress = TempB->LocalAddress.NetworkAddress;
  2936. Device->SourceAddress.NetworkAddress = TempB->LocalAddress.NetworkAddress;
  2937. IPX_DEBUG(BIND, ("Changed Loopback address to %lx\n", TempB->LocalAddress.NetworkAddress));
  2938. RtlCopyMemory (Loopback->LocalAddress.NodeAddress, TempB->LocalAddress.NodeAddress, 6);
  2939. RtlCopyMemory (Loopback->LocalMacAddress.Address, TempB->LocalAddress.NodeAddress, 6);
  2940. RtlCopyMemory (Device->SourceAddress.NodeAddress, TempB->LocalAddress.NodeAddress, 6);
  2941. IPX_DEBUG(BIND, ("Changed Loopback NODE address too\n"));
  2942. if (NULL != Loopback->TdiRegistrationHandle) {
  2943. if ((ntStatus = TdiDeregisterNetAddress(
  2944. Loopback->TdiRegistrationHandle
  2945. )) != STATUS_SUCCESS) {
  2946. IPX_DEBUG(PNP, ("TdiDeregisterNetAddress failed: %lx", ntStatus));
  2947. } else {
  2948. Loopback->TdiRegistrationHandle = NULL;
  2949. }
  2950. }
  2951. break;
  2952. }
  2953. }
  2954. if (NULL != FirstNonZero) {
  2955. //
  2956. // Then munge the addresses.
  2957. //
  2958. CTEGetLock(&Device->Lock, &LockHandle);
  2959. for (i = 0; i < IPX_ADDRESS_HASH_COUNT; i++) {
  2960. Current = Device->AddressDatabases[i].Flink;
  2961. while (Current != &Device->AddressDatabases[i]) {
  2962. //CTEGetLock (&AddrFile->Address->Lock, &LockHandle);
  2963. // do we need the addrfile lock here?
  2964. AddrObj = CONTAINING_RECORD(Current,
  2965. ADDRESS,
  2966. Linkage);
  2967. //if (AddrFile->State == ADDRESSFILE_STATE_OPEN) {
  2968. if (AddrObj->LocalAddress.NetworkAddress == REORDER_ULONG(INITIAL_LOOPBACK_NET_ADDRESS) ||
  2969. AddrObj->LocalAddress.NetworkAddress == 0) {
  2970. IPX_DEBUG(BIND, ("Found an Address using the Loopback netnumber: %lx!!\n", AddrObj));
  2971. //
  2972. // Change the address now.
  2973. //
  2974. RtlCopyMemory(&AddrObj->LocalAddress,
  2975. &FirstNonZero->LocalAddress,
  2976. sizeof(TDI_ADDRESS_IPX));
  2977. // }
  2978. IPX_DEBUG(BIND, ("Set Address #%d to the %lx\n", i, AddrObj->LocalAddress.NetworkAddress));
  2979. } else {
  2980. IPX_DEBUG(BIND, ("AddressObj(%lx): Network Address->%lx\n", AddrObj, AddrObj->LocalAddress.NetworkAddress));
  2981. //DbgBreakPoint();
  2982. }
  2983. // CTEFreeLock (&AddrFile->Address->Lock, LockHandle);
  2984. Current = Current->Flink;
  2985. }
  2986. IPX_DEBUG(BIND, ("No more entries in this Hash\n"));
  2987. }
  2988. CTEFreeLock(&Device->Lock, LockHandle);
  2989. //
  2990. // Remove the loopback network number if it was registered.
  2991. //
  2992. if (!Device->UpperDriverBound[IDENTIFIER_RIP]) {
  2993. PIPX_ROUTE_ENTRY RouteEntry = NULL;
  2994. ULONG Segment;
  2995. ULONG LoopbackNet = REORDER_ULONG(INITIAL_LOOPBACK_NET_ADDRESS);
  2996. Segment = RipGetSegment ((PUCHAR)&LoopbackNet);
  2997. IPX_GET_LOCK (&Device->SegmentLocks[Segment], &LockHandle);
  2998. RouteEntry = RipGetRoute (Segment, (PUCHAR)&LoopbackNet);
  2999. if (RouteEntry != (PIPX_ROUTE_ENTRY)NULL) {
  3000. RipDeleteRoute (Segment, RouteEntry);
  3001. IPX_FREE_LOCK (&Device->SegmentLocks[Segment], LockHandle);
  3002. IpxFreeMemory (RouteEntry, sizeof(IPX_ROUTE_ENTRY), MEMORY_RIP, "RouteEntry");
  3003. IPX_DEBUG(BIND, ("Removed %lx from routing table\n", LoopbackNet));
  3004. } else {
  3005. IPX_DEBUG(BIND, ("Couldnt find %lx in routing table\n", LoopbackNet));
  3006. IPX_FREE_LOCK (&Device->SegmentLocks[Segment], LockHandle);
  3007. }
  3008. IPX_DEBUG(PNP, ("Removed the route to LOOPBACK number\n"));
  3009. } else {
  3010. //
  3011. // Talk to PMay and figure this out.
  3012. //
  3013. IPX_DEBUG(PNP,("******** PMAY needs to know about this? \n"));
  3014. //DbgBreakPoint();
  3015. }
  3016. }
  3017. } else {
  3018. IPX_DEBUG(BIND, ("Loopback address to %lx\n", Loopback->LocalAddress.NetworkAddress));
  3019. }
  3020. //
  3021. // dont we need to update all the other device sourceaddresses etc. too?
  3022. //
  3023. } else {
  3024. IPX_DEBUG(BIND, ("---------------> Already have REAL adapters\n"));
  3025. }
  3026. IPX_DEBUG (DEVICE, ("Node is %2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x, ",
  3027. Device->SourceAddress.NodeAddress[0], Device->SourceAddress.NodeAddress[1],
  3028. Device->SourceAddress.NodeAddress[2], Device->SourceAddress.NodeAddress[3],
  3029. Device->SourceAddress.NodeAddress[4], Device->SourceAddress.NodeAddress[5]));
  3030. IPX_DEBUG (DEVICE, ("Network is %lx\n",
  3031. REORDER_ULONG (Device->SourceAddress.NetworkAddress)));
  3032. //
  3033. // Start the timer which updates the RIP database
  3034. // periodically. For the first one we do a ten
  3035. // second timeout (hopefully this is enough time
  3036. // for RIP to start if it is going to).
  3037. //
  3038. if (FALSE == Device->RealAdapters) {
  3039. IpxReferenceDevice (Device, DREF_LONG_TIMER);
  3040. CTEStartTimer(
  3041. &Device->RipLongTimer,
  3042. 10000,
  3043. RipLongTimeout,
  3044. (PVOID)Device);
  3045. }
  3046. //
  3047. // We have a real adapter now.
  3048. //
  3049. Device->RealAdapters = TRUE;
  3050. //
  3051. // Set up the LineInfo struct.
  3052. //
  3053. IpxPnPInfo.LineInfo.LinkSpeed = Device->LinkSpeed;
  3054. IpxPnPInfo.LineInfo.MaximumPacketSize =
  3055. Device->Information.MaximumLookaheadData + sizeof(IPX_HEADER);
  3056. IpxPnPInfo.LineInfo.MaximumSendSize =
  3057. Device->Information.MaxDatagramSize + sizeof(IPX_HEADER);
  3058. IpxPnPInfo.LineInfo.MacOptions = Device->MacOptions;
  3059. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  3060. //
  3061. // Inform NB and TDI of all the bindings corresponding to this adapter
  3062. //
  3063. for (i = 0; i < ISN_FRAME_TYPE_MAX; i++) {
  3064. Binding = Adapter->Bindings[i];
  3065. //
  3066. // If a NULL binding or a binding set slave, dont inform NB about it.
  3067. //
  3068. if (!Binding || (Binding->NicId > Device->HighestExternalNicId)) {
  3069. #if DBG
  3070. if (Binding) {
  3071. IPX_DEBUG(PNP, ("Binding: %lx, Binding set slave\n", Binding));
  3072. }
  3073. #endif
  3074. continue;
  3075. }
  3076. //
  3077. // We dont want to inform AFD of bogus wan addresses, we notify
  3078. // on lineup anyways. [ShreeM]
  3079. //
  3080. if (Adapter->MacInfo.MediumAsync) {
  3081. Binding->TdiRegistrationHandle = NULL;
  3082. IPX_DEBUG(PNP, ("Down WAN Binding - Dont TdiRegisterNetAddress\n"));
  3083. continue;
  3084. }
  3085. Binding->PastAutoDetection = TRUE; // tell only on line up
  3086. //
  3087. // Register this address with the TDI clients.
  3088. //
  3089. RtlCopyMemory (Device->TdiRegistrationAddress->Address, &Binding->LocalAddress, sizeof(TDI_ADDRESS_IPX));
  3090. if ((ntStatus = TdiRegisterNetAddress(
  3091. Device->TdiRegistrationAddress,
  3092. #if defined(_PNP_POWER_)
  3093. &IpxDeviceName,
  3094. NULL,
  3095. #endif _PNP_POWER_
  3096. &Binding->TdiRegistrationHandle)) != STATUS_SUCCESS) {
  3097. IPX_DEBUG(PNP, ("TdiRegisterNetAddress failed: %lx", ntStatus));
  3098. }
  3099. //
  3100. // Lock taken to check the UpperDriverBound flag.
  3101. // We already have the BindAccessLock at this point.
  3102. //
  3103. IPX_GET_LOCK(&Device->Lock, &LockHandle);
  3104. if (Device->UpperDriverBound[IDENTIFIER_NB]) {
  3105. IPX_FREE_LOCK(&Device->Lock, LockHandle);
  3106. //
  3107. // We could have informed the upper driver from IpxPnPIsnIndicate
  3108. // Ensure that we dont do it twice.
  3109. //
  3110. if (!Binding->IsnInformed[IDENTIFIER_NB]) {
  3111. //
  3112. // Maybe we didnt indicate the Loopback Binding.
  3113. // NtBug: 132433
  3114. //
  3115. // Make sure we have informed loopback binding before any other bindings.
  3116. // Moved the fix for 132433 to IpxInformNbLoopback.
  3117. KeWaitForSingleObject(
  3118. &IpxDevice->NbEvent,
  3119. Executive,
  3120. KernelMode,
  3121. TRUE,
  3122. (PLARGE_INTEGER)NULL
  3123. );
  3124. // IpxInformNbLoopback();
  3125. //
  3126. // Also, to ensure that the indications are done in the right order,
  3127. // check if the first card has been indicated yet.
  3128. //
  3129. if ((Binding->NicId != FIRST_REAL_BINDING) &&
  3130. !NIC_ID_TO_BINDING_NO_ILOCK(Device, FIRST_REAL_BINDING)->IsnInformed[IDENTIFIER_NB]) {
  3131. //break;
  3132. continue;
  3133. }
  3134. Binding->IsnInformed[IDENTIFIER_NB] = TRUE;
  3135. IpxPnPInfo.FirstORLastDevice = FALSE;
  3136. if (Binding->NicId == FIRST_REAL_BINDING) {
  3137. IpxPnPInfo.NewReservedAddress = TRUE;
  3138. } else {
  3139. IpxPnPInfo.NewReservedAddress = FALSE;
  3140. }
  3141. IpxPnPInfo.NetworkAddress = Binding->LocalAddress.NetworkAddress;
  3142. RtlCopyMemory(IpxPnPInfo.NodeAddress, Binding->LocalAddress.NodeAddress, 6);
  3143. NIC_HANDLE_FROM_NIC(IpxPnPInfo.NicHandle, Binding->NicId);
  3144. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  3145. //
  3146. // give the PnP indication
  3147. //
  3148. ASSERT(Binding->NicId != LOOPBACK_NIC_ID);
  3149. ASSERT(IpxHasInformedNbLoopback());
  3150. (*Device->UpperDrivers[IDENTIFIER_NB].PnPHandler) (
  3151. IPX_PNP_ADD_DEVICE,
  3152. &IpxPnPInfo);
  3153. IPX_DEBUG(PNP, ("PnP to NB add: %lx\n", Binding));
  3154. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  3155. }
  3156. } else {
  3157. IPX_FREE_LOCK(&Device->Lock, LockHandle);
  3158. }
  3159. }
  3160. IPX_GET_LOCK(&Device->Lock, &LockHandle);
  3161. if (Device->UpperDriverBound[IDENTIFIER_SPX]) {
  3162. IPX_FREE_LOCK(&Device->Lock, LockHandle);
  3163. //
  3164. // Always true for SPX
  3165. //
  3166. IpxPnPInfo.NewReservedAddress = TRUE;
  3167. if (FirstDevice) {
  3168. IpxPnPInfo.FirstORLastDevice = TRUE;
  3169. //
  3170. // We could have informed the upper driver from IpxPnPIsnIndicate
  3171. //
  3172. if (!NIC_ID_TO_BINDING_NO_ILOCK(Device, 1)->IsnInformed[IDENTIFIER_SPX]) {
  3173. NIC_ID_TO_BINDING_NO_ILOCK(Device, 1)->IsnInformed[IDENTIFIER_SPX] = TRUE;
  3174. //
  3175. // Inform SPX - the network/node address is the Virtual one if it exists
  3176. // else the address of the first binding
  3177. //
  3178. IpxPnPInfo.NetworkAddress = Device->SourceAddress.NetworkAddress;
  3179. RtlCopyMemory(IpxPnPInfo.NodeAddress, Device->SourceAddress.NodeAddress, 6);
  3180. if (Device->VirtualNetwork) {
  3181. NIC_HANDLE_FROM_NIC(IpxPnPInfo.NicHandle, 0);
  3182. } else {
  3183. NIC_HANDLE_FROM_NIC(IpxPnPInfo.NicHandle, 1);
  3184. }
  3185. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  3186. (*Device->UpperDrivers[IDENTIFIER_SPX].PnPHandler) (
  3187. IPX_PNP_ADD_DEVICE,
  3188. &IpxPnPInfo);
  3189. IPX_DEBUG(PNP, ("PnP to SPX add: %lx\n", Binding));
  3190. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  3191. }
  3192. } else {
  3193. //
  3194. // Not the first device - inform if the reserved address changed.
  3195. //
  3196. if (ReservedAddrChanged) {
  3197. if (!NIC_ID_TO_BINDING_NO_ILOCK(Device, 1)->IsnInformed[IDENTIFIER_SPX]) {
  3198. NIC_ID_TO_BINDING_NO_ILOCK(Device, 1)->IsnInformed[IDENTIFIER_SPX] = TRUE;
  3199. IPX_DEBUG(PNP, ("Reserved addr changed; SPX not told of first one yet\n"));
  3200. }
  3201. IpxPnPInfo.NetworkAddress = Device->SourceAddress.NetworkAddress;
  3202. RtlCopyMemory(IpxPnPInfo.NodeAddress, Device->SourceAddress.NodeAddress, 6);
  3203. if (Device->VirtualNetwork) {
  3204. //
  3205. // new one appeared
  3206. //
  3207. NIC_HANDLE_FROM_NIC(IpxPnPInfo.NicHandle, 0);
  3208. } else {
  3209. //
  3210. // Old one disappeared
  3211. //
  3212. NIC_HANDLE_FROM_NIC(IpxPnPInfo.NicHandle, 1);
  3213. }
  3214. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  3215. IpxPnPInfo.FirstORLastDevice = FALSE;
  3216. IPX_DEBUG(PNP, ("PnP to SPX add (res. addr change): %lx\n", Binding));
  3217. (*Device->UpperDrivers[IDENTIFIER_SPX].PnPHandler) (
  3218. IPX_PNP_ADDRESS_CHANGE,
  3219. &IpxPnPInfo);
  3220. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  3221. }
  3222. }
  3223. } else {
  3224. IPX_FREE_LOCK(&Device->Lock, LockHandle);
  3225. }
  3226. //
  3227. //
  3228. //
  3229. IPX_DEBUG(BIND, ("Telling RTR Manager that some bindings have been created\n"));
  3230. if ((p = ExInterlockedRemoveHeadList(
  3231. &Device->NicNtfQueue,
  3232. &Device->Lock)) != NULL)
  3233. {
  3234. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  3235. Request = LIST_ENTRY_TO_REQUEST(p);
  3236. IPX_DEBUG(BIND, ("IpxBindAdapter: NICs coming in\n"));
  3237. Status = GetNewNics(Device, Request, FALSE, NULL, 0, TRUE);
  3238. if (Status == STATUS_PENDING)
  3239. {
  3240. IPX_DEBUG(BIND, ("GetNewNics returned %lx\n", Status));
  3241. }
  3242. else
  3243. {
  3244. IoAcquireCancelSpinLock(&OldIrq);
  3245. IoSetCancelRoutine (Request, (PDRIVER_CANCEL)NULL);
  3246. IoReleaseCancelSpinLock(OldIrq);
  3247. REQUEST_STATUS(Request) = Status;
  3248. IpxCompleteRequest (Request);
  3249. IpxFreeRequest (Device, Request);
  3250. IpxDereferenceDevice (Device, DREF_NIC_NOTIFY);
  3251. IPX_DEBUG(BIND, ("GetNewNics returned SUCCESS (RTR Manager has been informed)\n"));
  3252. }
  3253. } else {
  3254. IPX_DEBUG(BIND,("No IRPs available\n"));
  3255. }
  3256. //
  3257. // Release access to the Binding related stuff.
  3258. //
  3259. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  3260. #if 0
  3261. //
  3262. // QoS needs IPX to set the network address as an OID now.
  3263. //
  3264. if (!Adapter->MacInfo.MediumAsync) {
  3265. int count, i;
  3266. int size;
  3267. NTSTATUS NdisStatus = STATUS_SUCCESS;
  3268. UNICODE_STRING AdapterName;
  3269. for (count=0, i=0; i < ISN_FRAME_TYPE_MAX; i++) {
  3270. if (Adapter->Bindings[i]) {
  3271. count++;
  3272. }
  3273. }
  3274. IPX_DEBUG(PNP,("This adapter has %d valid bindings\n", count));
  3275. size = FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address) + count * (FIELD_OFFSET(NETWORK_ADDRESS, Address) + sizeof(NETWORK_ADDRESS_IPX));
  3276. AddrList = IpxAllocateMemory(
  3277. size,
  3278. MEMORY_ADAPTER,
  3279. "QoS specific stuff");
  3280. if (AddrList != NULL) {
  3281. RtlZeroMemory(AddrList, size);
  3282. AddrList->AddressCount = count;
  3283. AddrList->AddressType = NDIS_PROTOCOL_ID_IPX;
  3284. count = 0;
  3285. Address = &AddrList->Address[0];
  3286. for (i=0; i < ISN_FRAME_TYPE_MAX; i++) {
  3287. if (Adapter->Bindings[i]) {
  3288. Address->AddressLength = sizeof(NETWORK_ADDRESS_IPX);
  3289. Address->AddressType = NDIS_PROTOCOL_ID_IPX;
  3290. TdiAddress = (NETWORK_ADDRESS_IPX UNALIGNED *) &Address->Address[0];
  3291. TdiAddress->NetworkAddress = Adapter->Bindings[i]->LocalAddress.NetworkAddress;
  3292. RtlCopyMemory (TdiAddress->NodeAddress, Adapter->Bindings[i]->LocalAddress.NodeAddress, 6);
  3293. TdiAddress->Socket = 0;
  3294. IPX_DEBUG(PNP,("Node is %2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x, ",
  3295. TdiAddress->NodeAddress[0], TdiAddress->NodeAddress[1],
  3296. TdiAddress->NodeAddress[2], TdiAddress->NodeAddress[3],
  3297. TdiAddress->NodeAddress[4], TdiAddress->NodeAddress[5]));
  3298. IPX_DEBUG(PNP,("Network is %lx\n", REORDER_ULONG (TdiAddress->NetworkAddress)));
  3299. count++;
  3300. Address = (PNETWORK_ADDRESS) (((PUCHAR)(&AddrList->Address[0])) + count * (FIELD_OFFSET(NETWORK_ADDRESS, Address) + sizeof(NETWORK_ADDRESS_IPX)));
  3301. }
  3302. }
  3303. IpxRequest.RequestType = NdisRequestSetInformation;
  3304. IpxRequest.DATA.SET_INFORMATION.Oid = OID_GEN_NETWORK_LAYER_ADDRESSES;
  3305. IpxRequest.DATA.SET_INFORMATION.InformationBuffer = AddrList;
  3306. IpxRequest.DATA.SET_INFORMATION.InformationBufferLength = size;
  3307. RtlInitUnicodeString(&AdapterName, Adapter->AdapterName);
  3308. NdisStatus = IpxSubmitNdisRequest (Adapter, &IpxRequest, &AdapterName);
  3309. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  3310. IPX_DEBUG(PNP,("Setting the OID Failed!! - Error %lx \n", NdisStatus));
  3311. //*Status = NdisStatus;
  3312. } else {
  3313. IPX_DEBUG(PNP,("Setting the OID was successful\n"));
  3314. }
  3315. IpxFreeMemory(AddrList,
  3316. sizeof(NETWORK_ADDRESS_LIST) + sizeof (NETWORK_ADDRESS) + sizeof(TDI_ADDRESS_IPX),
  3317. MEMORY_ADAPTER,
  3318. "QoS specific stuff");
  3319. } else {
  3320. DbgPrint("IPX:Failed to allocate memory. Skipped QoS registration.\n");
  3321. }
  3322. } else {
  3323. IPX_DEBUG(PNP,("Async Medium - skipping\n"));
  3324. }
  3325. #endif
  3326. InitFailed:
  3327. //
  3328. // If there are no more init-time adapters, then indicate to TDI now.
  3329. //
  3330. IPX_GET_LOCK(&Device->Lock, &LockHandle);
  3331. if (0 == --Device->InitTimeAdapters) {
  3332. IPX_DEBUG(PNP,("BindAdapter EXIT time: Count %d - CALLING TDI!\n", Device->InitTimeAdapters));
  3333. IPX_FREE_LOCK(&Device->Lock, LockHandle);
  3334. CTEAssert(Device->NetPnPEvent);
  3335. NdisCompletePnPEvent(
  3336. STATUS_SUCCESS,
  3337. NULL,
  3338. Device->NetPnPEvent
  3339. );
  3340. Device->NetPnPEvent = NULL;
  3341. TdiProviderReady(Device->TdiProviderReadyHandle);
  3342. } else {
  3343. IPX_DEBUG(PNP,("BindAdapter EXIT time: Count %d - not calling TDI\n", Device->InitTimeAdapters));
  3344. IPX_FREE_LOCK(&Device->Lock, LockHandle);
  3345. }
  3346. IPX_DEBUG(PNP, ("IpxBindAdapter returns status %x\n", *Status));
  3347. return;
  3348. } /* IpxBindAdapter */
  3349. VOID
  3350. IpxUnbindAdapter(
  3351. OUT PNDIS_STATUS Status,
  3352. IN NDIS_HANDLE ProtocolBindingContext,
  3353. IN NDIS_HANDLE UnbindContext
  3354. )
  3355. /*++
  3356. Routine Description:
  3357. This routine receives a Plug and Play notification about the removal
  3358. of an existing adapter from the machine. We are called here only if
  3359. this adapter is to be bound to us, so we don't make any checks for this.
  3360. Arguments:
  3361. Status - NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING.
  3362. ProtocolBindingContext - the adapter that got removed.
  3363. UnbindContext - context to represent this bind indication.
  3364. Return Value:
  3365. Void - return thru' Status above.
  3366. --*/
  3367. {
  3368. UCHAR InitialLoopbackNodeAddress[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x02};
  3369. NTSTATUS ntStatus;
  3370. PADAPTER Adapter=(PADAPTER)ProtocolBindingContext;
  3371. CONFIG Config;
  3372. PBINDING Binding;
  3373. PDEVICE Device=IpxDevice;
  3374. ULONG i, Temp;
  3375. BOOLEAN NewVirtualNetwork = FALSE;
  3376. BOOLEAN NBReservedAddrChanged = FALSE;
  3377. BOOLEAN SPXInformed = FALSE;
  3378. IPX_PNP_INFO IpxPnPInfo;
  3379. PBINDING newMasterBinding, tBinding = NULL;
  3380. PLIST_ENTRY p = NULL;
  3381. PREQUEST Request = NULL;
  3382. USHORT NicId = 0;
  3383. // QoS
  3384. NDIS_REQUEST IpxRequest;
  3385. PNETWORK_ADDRESS_LIST AddrList;
  3386. UNICODE_STRING AdapterName;
  3387. NTSTATUS NdisStatus = STATUS_SUCCESS;
  3388. IPX_DEFINE_LOCK_HANDLE(LockHandle1)
  3389. IPX_DEFINE_LOCK_HANDLE(LockHandle)
  3390. IPX_DEFINE_LOCK_HANDLE (OldIrq)
  3391. IPX_DEFINE_LOCK_HANDLE (LockHandle2)
  3392. PAGED_CODE();
  3393. IPX_GET_LOCK (&Adapter->Lock, &LockHandle2);
  3394. Adapter->State = ADAPTER_STATE_STOPPING;
  3395. IpxDereferenceAdapter1(Adapter,ADAP_REF_CREATE);
  3396. IPX_FREE_LOCK (&Adapter->Lock, LockHandle2);
  3397. IPX_DEBUG(PNP,("IpxUnbindAdapter: Waiting for ndis requests to be submitted \n"));
  3398. KeWaitForSingleObject(
  3399. &Adapter->NdisEvent,
  3400. Executive,
  3401. KernelMode,
  3402. TRUE,
  3403. (PLARGE_INTEGER)NULL
  3404. );
  3405. IPX_DEBUG(PNP,("IpxUnbindAdapter: Past NdisEvent\n"));
  3406. #if 0
  3407. AddrList = IpxAllocateMemory(sizeof(NETWORK_ADDRESS_LIST),
  3408. MEMORY_ADAPTER,
  3409. "QoS specific stuff");
  3410. if (AddrList != NULL) {
  3411. RtlZeroMemory(AddrList, sizeof(NETWORK_ADDRESS_LIST));
  3412. AddrList->AddressCount = 0;
  3413. AddrList->AddressType = NDIS_PROTOCOL_ID_IPX;
  3414. IpxRequest.RequestType = NdisRequestSetInformation;
  3415. IpxRequest.DATA.SET_INFORMATION.Oid = OID_GEN_NETWORK_LAYER_ADDRESSES;
  3416. IpxRequest.DATA.SET_INFORMATION.InformationBuffer = AddrList;
  3417. IpxRequest.DATA.SET_INFORMATION.InformationBufferLength = sizeof(NETWORK_ADDRESS_LIST);
  3418. RtlInitUnicodeString(&AdapterName, Adapter->AdapterName);
  3419. NdisStatus = IpxSubmitNdisRequest (Adapter, &IpxRequest, &AdapterName);
  3420. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  3421. IPX_DEBUG(PNP,("IpxUnbindAdapter: Setting the OID Failed!! - Error %lx \n", NdisStatus));
  3422. } else {
  3423. IPX_DEBUG(PNP,("Setting the OID was successful\n"));
  3424. }
  3425. IpxFreeMemory(AddrList,
  3426. sizeof(NETWORK_ADDRESS_LIST),
  3427. MEMORY_ADAPTER,
  3428. "QoS specific stuff");
  3429. } else {
  3430. DbgPrint("IPX:IpxUnbindAdapter:Memory allocation failed! Skipped QoS registration.\n");
  3431. }
  3432. #endif
  3433. //
  3434. // Free the packet pools, etc. and close the
  3435. // adapter.
  3436. //
  3437. IpxCloseNdis (Adapter);
  3438. //
  3439. // Used for error logging
  3440. //
  3441. Config.DriverObject = (PDRIVER_OBJECT)Device->DeviceObject;
  3442. Config.RegistryPathBuffer = Device->RegistryPathBuffer;
  3443. //
  3444. // Read the registry to see if a virtual network number appeared/disappeared
  3445. //
  3446. ntStatus = IpxPnPGetVirtualNetworkNumber(&Config);
  3447. if (ntStatus != STATUS_SUCCESS) {
  3448. IPX_DEBUG(PNP, ("Could not read the vnet#: registrypathbuffer: %lx\n", Device->RegistryPathBuffer));
  3449. *Status = NDIS_STATUS_SUCCESS;
  3450. return;
  3451. }
  3452. Temp = REORDER_ULONG (Config.Parameters[CONFIG_VIRTUAL_NETWORK]);
  3453. //
  3454. // If the VirtualNetwork number changed, record it.
  3455. //
  3456. if (Device->VirtualNetworkNumber != Temp) {
  3457. NewVirtualNetwork = TRUE;
  3458. }
  3459. PAGED_CODE();
  3460. Device->VirtualNetworkOptional = (BOOLEAN)(Config.Parameters[CONFIG_VIRTUAL_OPTIONAL] != 0);
  3461. IPX_DEBUG(PNP, ("Virtual net # is: %lx\n", Temp));
  3462. //
  3463. // If the WAN adapter disappeared, we can simply remove all the WAN bindings since
  3464. // all of them correspond to this single WAN adapter. Since we tell NB only about
  3465. // the first one of these, we need to indicate removal of only one binding to NB.
  3466. //
  3467. if (Adapter->MacInfo.MediumAsync) {
  3468. USHORT wanLineCount = (USHORT)Adapter->WanNicIdCount;
  3469. PBINDING bindingDemand = NULL;
  3470. CTEAssert(wanLineCount == (Device->HighestExternalNicId - Device->HighestLanNicId));
  3471. //
  3472. // If no more bindings remain, tell upper driver of the same.
  3473. // We go back to the loaded state.
  3474. //
  3475. if ((Device->ValidBindings - wanLineCount) == 1) {
  3476. PBINDING LoopbackBinding = NULL;
  3477. //
  3478. // If we are left with one NIC, then we are on loopback only (and no real adapters).
  3479. // [Shreem]
  3480. //
  3481. Device->RealAdapters = FALSE;
  3482. // Dont do these anymore [Shreem]
  3483. //IpxPnPInfo.FirstORLastDevice = TRUE;
  3484. // Device->State = DEVICE_STATE_LOADED;
  3485. //
  3486. // Shut down RIP timers, complete address notify requests, etc.
  3487. //
  3488. IpxPnPToLoad();
  3489. //
  3490. // Put the old Loopback address into the Loopback binding.
  3491. //
  3492. LoopbackBinding = NIC_ID_TO_BINDING(Device, LOOPBACK_NIC_ID);
  3493. if (!Device->VirtualNetwork) {
  3494. LoopbackBinding->LocalAddress.NetworkAddress = REORDER_ULONG(INITIAL_LOOPBACK_NET_ADDRESS);
  3495. Device->SourceAddress.NetworkAddress = REORDER_ULONG(INITIAL_LOOPBACK_NET_ADDRESS);
  3496. ntStatus = RipInsertLocalNetwork(
  3497. LoopbackBinding->LocalAddress.NetworkAddress,
  3498. LoopbackBinding->NicId,
  3499. LoopbackBinding->Adapter->NdisBindingHandle,
  3500. (USHORT)((839 + LoopbackBinding->MediumSpeed) / LoopbackBinding->MediumSpeed));
  3501. if ((ntStatus != STATUS_SUCCESS) &&
  3502. (ntStatus != STATUS_DUPLICATE_NAME)) {
  3503. //
  3504. // We failed to insert, keep it at zero, hopefully
  3505. // we will be able to update later.
  3506. //
  3507. IPX_DEBUG(LOOPB, ("IPX: Could not insert net %lx for binding %lx\n",
  3508. REORDER_ULONG(LoopbackBinding->LocalAddress.NetworkAddress),
  3509. LoopbackBinding));
  3510. } else {
  3511. IPX_DEBUG(LOOPB, ("Inserted the loopback address in the RIP table\n"));
  3512. }
  3513. }
  3514. RtlCopyMemory (LoopbackBinding->LocalAddress.NodeAddress, InitialLoopbackNodeAddress, 6);
  3515. RtlCopyMemory (LoopbackBinding->LocalMacAddress.Address, InitialLoopbackNodeAddress, 6);
  3516. RtlCopyMemory (Device->SourceAddress.NodeAddress, LoopbackBinding->LocalAddress.NodeAddress, 6);
  3517. RtlCopyMemory ( Device->TdiRegistrationAddress->Address,
  3518. &LoopbackBinding->LocalAddress,
  3519. sizeof(TDI_ADDRESS_IPX));
  3520. if (STATUS_SUCCESS != (ntStatus = TdiRegisterNetAddress(Device->TdiRegistrationAddress,
  3521. &IpxDeviceName,
  3522. NULL,
  3523. &LoopbackBinding->TdiRegistrationHandle))) {
  3524. IPX_DEBUG(PNP, ("Error registering Loopback IPX address\n"));
  3525. }
  3526. IpxPnPInfo.FirstORLastDevice = FALSE;
  3527. } else {
  3528. CTEAssert(Device->State == DEVICE_STATE_OPEN);
  3529. IpxPnPInfo.FirstORLastDevice = FALSE;
  3530. }
  3531. //
  3532. // DeRegister this address with the TDI clients.
  3533. //
  3534. //
  3535. // Get to the first WAN binding - this is always the one after the last LAN binding.
  3536. //
  3537. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  3538. Binding = NIC_ID_TO_BINDING_NO_ILOCK(Device, Device->HighestLanNicId+1);
  3539. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  3540. // CTEAssert(Binding->TdiRegistrationHandle); // We dont register until lineup these days
  3541. PAGED_CODE();
  3542. if (Binding->TdiRegistrationHandle) {
  3543. if ((ntStatus = TdiDeregisterNetAddress(Binding->TdiRegistrationHandle)) != STATUS_SUCCESS) {
  3544. IPX_DEBUG(PNP, ("TdiDeRegisterNetAddress failed: %lx", ntStatus));
  3545. } else {
  3546. Binding->TdiRegistrationHandle = NULL;
  3547. }
  3548. }
  3549. //
  3550. // Set up the LineInfo struct.
  3551. //
  3552. IpxPnPInfo.LineInfo.LinkSpeed = Device->LinkSpeed;
  3553. IpxPnPInfo.LineInfo.MaximumPacketSize =
  3554. Device->Information.MaximumLookaheadData + sizeof(IPX_HEADER);
  3555. IpxPnPInfo.LineInfo.MaximumSendSize =
  3556. Device->Information.MaxDatagramSize + sizeof(IPX_HEADER);
  3557. IpxPnPInfo.LineInfo.MacOptions = Device->MacOptions;
  3558. IPX_GET_LOCK(&Device->Lock, &LockHandle);
  3559. if (Device->UpperDriverBound[IDENTIFIER_NB]) {
  3560. PBINDING Loopback = NULL;
  3561. IPX_FREE_LOCK(&Device->Lock, LockHandle);
  3562. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  3563. Loopback = NIC_ID_TO_BINDING(Device, LOOPBACK_NIC_ID);
  3564. //
  3565. // Give the PnP indication to indicate the deletion only if it was
  3566. // added before.
  3567. //
  3568. if (Binding->IsnInformed[IDENTIFIER_NB]) {
  3569. IpxPnPInfo.NetworkAddress = Binding->LocalAddress.NetworkAddress;
  3570. RtlCopyMemory(IpxPnPInfo.NodeAddress, Binding->LocalAddress.NodeAddress, 6);
  3571. NIC_HANDLE_FROM_NIC(IpxPnPInfo.NicHandle, Binding->NicId);
  3572. IpxPnPInfo.FirstORLastDevice = FALSE;
  3573. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  3574. IPX_DEBUG(PNP, ("Inform NB: delete WAN device\n"));
  3575. CTEAssert(Binding->NicId != LOOPBACK_NIC_ID);
  3576. (*Device->UpperDrivers[IDENTIFIER_NB].PnPHandler) (
  3577. IPX_PNP_DELETE_DEVICE,
  3578. &IpxPnPInfo);
  3579. Binding->IsnInformed[IDENTIFIER_NB] = FALSE;
  3580. IPX_DEBUG(PNP, ("PnP to NB delete: %lx\n", Binding));
  3581. IPX_DEBUG(PNP,("Indicate to NB IPX_PNP_DELETE_DEVICE with FirstORLastDevice = (%d)",IpxPnPInfo.FirstORLastDevice));
  3582. }
  3583. #if DBG
  3584. else {
  3585. DbgPrint("WAN adapter id: %lx not indicated to NB\n", Binding->NicId);
  3586. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  3587. }
  3588. #endif
  3589. } else {
  3590. IPX_FREE_LOCK(&Device->Lock, LockHandle);
  3591. }
  3592. //
  3593. // Inform SPX only if this is the last device.
  3594. //
  3595. IPX_GET_LOCK(&Device->Lock, &LockHandle);
  3596. if (Device->UpperDriverBound[IDENTIFIER_SPX]) {
  3597. IPX_FREE_LOCK(&Device->Lock, LockHandle);
  3598. if (IpxPnPInfo.FirstORLastDevice && Binding->IsnInformed[IDENTIFIER_SPX]) {
  3599. PBINDING Loopback = NULL;
  3600. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  3601. CTEAssert(Device->HighestLanNicId == 0);
  3602. //
  3603. // Get to the first WAN binding - this is always the one after the last LAN binding.
  3604. //
  3605. Binding = NIC_ID_TO_BINDING_NO_ILOCK(Device, Device->HighestLanNicId+1);
  3606. IpxPnPInfo.NetworkAddress = Binding->LocalAddress.NetworkAddress;
  3607. RtlCopyMemory(IpxPnPInfo.NodeAddress, Binding->LocalAddress.NodeAddress, 6);
  3608. NIC_HANDLE_FROM_NIC(IpxPnPInfo.NicHandle, Binding->NicId);
  3609. IpxPnPInfo.FirstORLastDevice = FALSE;
  3610. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  3611. IPX_DEBUG(PNP, ("Inform SPX: delete WAN device\n"));
  3612. (*Device->UpperDrivers[IDENTIFIER_SPX].PnPHandler) (
  3613. IPX_PNP_DELETE_DEVICE,
  3614. &IpxPnPInfo);
  3615. Binding->IsnInformed[IDENTIFIER_SPX] = FALSE;
  3616. //
  3617. // Now add loopback back! [Shreem]
  3618. //
  3619. if (!Device->RealAdapters) {
  3620. Loopback = NIC_ID_TO_BINDING(Device, LOOPBACK_NIC_ID);
  3621. IpxPnPInfo.NetworkAddress = Loopback->LocalAddress.NetworkAddress;
  3622. RtlCopyMemory(IpxPnPInfo.NodeAddress, Loopback->LocalAddress.NodeAddress, 6);
  3623. NIC_HANDLE_FROM_NIC(IpxPnPInfo.NicHandle, Loopback->NicId);
  3624. IpxPnPInfo.NewReservedAddress = TRUE;
  3625. IpxPnPInfo.FirstORLastDevice = FALSE;
  3626. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  3627. IPX_DEBUG(PNP, ("Inform SPX: ADD Loopback device\n"));
  3628. (*Device->UpperDrivers[IDENTIFIER_SPX].PnPHandler) (
  3629. IPX_PNP_ADD_DEVICE,
  3630. &IpxPnPInfo);
  3631. Loopback->IsnInformed[IDENTIFIER_SPX] = TRUE;
  3632. }
  3633. }
  3634. } else {
  3635. IPX_FREE_LOCK(&Device->Lock, LockHandle);
  3636. }
  3637. //
  3638. // IPX needs to tell the forwarder about NIC IDs going away. [109160]
  3639. //
  3640. for (i = Device->HighestLanNicId+1; i <= Device->HighestExternalNicId; i++) {
  3641. PBINDING UnBinding;
  3642. UnBinding = NIC_ID_TO_BINDING_NO_ILOCK(Device, i);
  3643. if (UnBinding) {
  3644. if (UnBinding->LineUp) {
  3645. UnBinding->LineUp = FALSE;
  3646. UnBinding->fInfoIndicated = FALSE;
  3647. } else {
  3648. IPX_DEBUG(BIND, ("Line is not up for Binding[%lx]\n", i));
  3649. }
  3650. }
  3651. }
  3652. IPX_DEBUG(BIND, ("Telling RTR Manager that some bindings are going away.\n"));
  3653. if ((p = ExInterlockedRemoveHeadList(
  3654. &Device->NicNtfQueue,
  3655. &Device->Lock)) != NULL)
  3656. {
  3657. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  3658. Request = LIST_ENTRY_TO_REQUEST(p);
  3659. IPX_DEBUG(BIND, ("IpxUNbindadapter: NICs gone away\n"));
  3660. Status = GetNewNics(Device, Request, FALSE, NULL, 0, TRUE);
  3661. if (Status == STATUS_PENDING)
  3662. {
  3663. IPX_DEBUG(BIND, ("GetNewNics returned %lx\n", Status));
  3664. }
  3665. else
  3666. {
  3667. IoAcquireCancelSpinLock(&OldIrq);
  3668. IoSetCancelRoutine (Request, (PDRIVER_CANCEL)NULL);
  3669. IoReleaseCancelSpinLock(OldIrq);
  3670. REQUEST_STATUS(Request) = Status;
  3671. IpxCompleteRequest (Request);
  3672. IpxFreeRequest (Device, Request);
  3673. IpxDereferenceDevice (Device, DREF_NIC_NOTIFY);
  3674. IPX_DEBUG(BIND, ("GetNewNics returned SUCCESS (RTR Manager has been informed\n"));
  3675. }
  3676. } else {
  3677. IPX_DEBUG(PNP,("No IRPs available\n"));
  3678. }
  3679. //
  3680. // Now remove these WAN bindings from the array. Move all the Slave bindings
  3681. // up to where the WAN bindings were.
  3682. //
  3683. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  3684. for (i = Device->HighestLanNicId+1; i <= Device->HighestExternalNicId; i++) {
  3685. PBINDING UnBinding;
  3686. //
  3687. // Unbind from the adapter - if it is not referenced by any other thread, it will
  3688. // be deleted at this point.
  3689. //
  3690. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  3691. UnBinding = NIC_ID_TO_BINDING_NO_ILOCK(Device, i);
  3692. if (UnBinding) {
  3693. IpxUnBindFromAdapter(UnBinding);
  3694. INSERT_BINDING(Device, UnBinding->NicId, NULL);
  3695. }
  3696. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  3697. //
  3698. // Move the slave binding here.
  3699. // ONLY if they exist! [ShreeM] 98679
  3700. //
  3701. if ((Device->ValidBindings > Device->HighestExternalNicId) && (i+wanLineCount <= Device->ValidBindings)) {
  3702. PBINDING tmpBinding;
  3703. tmpBinding = NIC_ID_TO_BINDING_NO_ILOCK(Device, i+wanLineCount);
  3704. INSERT_BINDING(Device, i, tmpBinding);
  3705. tmpBinding->NicId = (unsigned short) i;
  3706. }
  3707. }
  3708. //
  3709. // Free the demand dial binding place holder.
  3710. //
  3711. bindingDemand = NIC_ID_TO_BINDING(IpxDevice, DEMAND_DIAL_ADAPTER_CONTEXT);
  3712. if (bindingDemand != NULL) {
  3713. IpxUnBindFromAdapter(bindingDemand);
  3714. INSERT_BINDING(Device, (SHORT) DEMAND_DIAL_ADAPTER_CONTEXT, NULL);
  3715. }
  3716. //
  3717. // Update the indices
  3718. //
  3719. Device->HighestExternalNicId -= wanLineCount;
  3720. Device->ValidBindings -= wanLineCount;
  3721. Device->BindingCount -= wanLineCount;
  3722. Device->SapNicCount = Device->HighestType20NicId = Device->HighestLanNicId;
  3723. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  3724. CTEAssert(Device->HighestLanNicId == Device->HighestExternalNicId);
  3725. } else {
  3726. //
  3727. // LAN adapter disappeared.
  3728. //
  3729. //
  3730. // Set up the LineInfo struct.
  3731. //
  3732. IpxPnPInfo.LineInfo.LinkSpeed = Device->LinkSpeed;
  3733. IpxPnPInfo.LineInfo.MaximumPacketSize =
  3734. Device->Information.MaximumLookaheadData + sizeof(IPX_HEADER);
  3735. IpxPnPInfo.LineInfo.MaximumSendSize =
  3736. Device->Information.MaxDatagramSize + sizeof(IPX_HEADER);
  3737. IpxPnPInfo.LineInfo.MacOptions = Device->MacOptions;
  3738. //
  3739. // IPX needs to tell the forwarder about NIC IDs going away. [109160]
  3740. //
  3741. for (i = 0; i < ISN_FRAME_TYPE_MAX; i++) {
  3742. PBINDING UnBinding;
  3743. UnBinding = Adapter->Bindings[i];
  3744. if (UnBinding) {
  3745. if (UnBinding->LineUp) {
  3746. UnBinding->LineUp = FALSE;
  3747. UnBinding->fInfoIndicated = FALSE;
  3748. IPX_DEBUG(BIND, ("Line is UP for Binding[%lx]\n", i));
  3749. } else {
  3750. IPX_DEBUG(BIND, ("Line is not up for Binding[%lx]\n", i));
  3751. }
  3752. }
  3753. }
  3754. IPX_DEBUG(BIND, ("Telling RTR Manager that some bindings are going away.\n"));
  3755. if ((p = ExInterlockedRemoveHeadList(
  3756. &Device->NicNtfQueue,
  3757. &Device->Lock)) != NULL)
  3758. {
  3759. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  3760. Request = LIST_ENTRY_TO_REQUEST(p);
  3761. IPX_DEBUG(BIND, ("IpxUNbindadapter: NICs gone away\n"));
  3762. Status = GetNewNics(Device, Request, FALSE, NULL, 0, TRUE);
  3763. if (Status == STATUS_PENDING)
  3764. {
  3765. IPX_DEBUG(BIND, ("GetNewNics returned %lx\n", Status));
  3766. }
  3767. else
  3768. {
  3769. IoAcquireCancelSpinLock(&OldIrq);
  3770. IoSetCancelRoutine (Request, (PDRIVER_CANCEL)NULL);
  3771. IoReleaseCancelSpinLock(OldIrq);
  3772. REQUEST_STATUS(Request) = Status;
  3773. IpxCompleteRequest (Request);
  3774. IpxFreeRequest (Device, Request);
  3775. IpxDereferenceDevice (Device, DREF_NIC_NOTIFY);
  3776. IPX_DEBUG(BIND, ("GetNewNics returned SUCCESS (RTR Manager has been informed\n"));
  3777. }
  3778. } else {
  3779. IPX_DEBUG(PNP,("No IRPs available\n"));
  3780. }
  3781. //
  3782. // For each binding corresponding to this adapter, inform NB only
  3783. // if the binding addition was indicated.
  3784. //
  3785. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  3786. for (i = 0; i < ISN_FRAME_TYPE_MAX; i++) {
  3787. Binding = Adapter->Bindings[i];
  3788. if (!Binding) {
  3789. continue;
  3790. }
  3791. //
  3792. // We cannot receive on this binding anymore
  3793. //
  3794. Adapter->Bindings[i] = NULL;
  3795. //
  3796. // If this was a slave binding, dont inform of the deletion.
  3797. // Just remove the binding from the binding array and the bindingset list.
  3798. //
  3799. if (Binding->NicId > Device->HighestExternalNicId) {
  3800. PBINDING MasterBinding, tempBinding;
  3801. ULONG j;
  3802. CTEAssert(Binding->BindingSetMember);
  3803. CTEAssert(Binding->CurrentSendBinding == NULL);
  3804. //
  3805. // Traverse the bindingset list and remove this binding from there.
  3806. //
  3807. tempBinding = MasterBinding = Binding->MasterBinding;
  3808. while (tempBinding->NextBinding != MasterBinding) {
  3809. if (tempBinding->NextBinding == Binding) {
  3810. tempBinding->NextBinding = tempBinding->NextBinding->NextBinding;
  3811. break;
  3812. }
  3813. tempBinding = tempBinding->NextBinding;
  3814. }
  3815. //
  3816. // If no more slaves, this is no longer a bindingset.
  3817. //
  3818. if (MasterBinding->NextBinding == MasterBinding) {
  3819. MasterBinding->BindingSetMember = FALSE;
  3820. MasterBinding->CurrentSendBinding = NULL;
  3821. MasterBinding->ReceiveBroadcast = TRUE;
  3822. IPX_DEBUG(PNP, ("Slave binding: %lx removed, no master: %lx\n", Binding, MasterBinding));
  3823. } else {
  3824. //
  3825. // [MS] if this slave had ReceiveBroadcast on, we need to change that...
  3826. //
  3827. MasterBinding->CurrentSendBinding = MasterBinding;
  3828. MasterBinding->ReceiveBroadcast = TRUE;
  3829. //
  3830. // Make sure other bindings are in sync with this change in command
  3831. //
  3832. tempBinding = MasterBinding;
  3833. while (MasterBinding != (tempBinding = tempBinding->NextBinding) ) {
  3834. tempBinding->ReceiveBroadcast = FALSE;
  3835. CTEAssert(tempBinding->MasterBinding == MasterBinding);
  3836. }
  3837. }
  3838. //
  3839. // Change the slave binding entries to have the master's NicId
  3840. //
  3841. RipAdjustForBindingChange (Binding->NicId, MasterBinding->NicId, IpxBindingMoved);
  3842. IPX_DEBUG(PNP, ("RipAdjustForBindingChange (%d, %d, IpxBindingMoved)\n", Binding->NicId, MasterBinding->NicId));
  3843. //
  3844. // Null out the Slave binding.
  3845. //
  3846. INSERT_BINDING(Device, Binding->NicId, NULL);
  3847. // 306476
  3848. for (j = Binding->NicId+1; j <= Device->ValidBindings; j++) {
  3849. PBINDING tmp;
  3850. tmp = NIC_ID_TO_BINDING_NO_ILOCK(Device, j);
  3851. INSERT_BINDING(Device, j-1, tmp);
  3852. if (tmp) {
  3853. USHORT oldId = tmp->NicId;
  3854. --tmp->NicId;
  3855. RipAdjustForBindingChange (oldId, tmp->NicId, IpxBindingMoved);
  3856. }
  3857. }
  3858. INSERT_BINDING(Device, Device->ValidBindings, NULL);
  3859. --Device->ValidBindings;
  3860. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  3861. if (Adapter->BindingCount == 1) {
  3862. // The adapter will be destroyed if this is the last binding.
  3863. IpxUnBindFromAdapter(Binding);
  3864. break;
  3865. } else {
  3866. IpxUnBindFromAdapter(Binding);
  3867. }
  3868. continue;
  3869. }
  3870. //
  3871. // If this was the last binding, go back to loaded state and shut down the RIP timers.
  3872. //
  3873. if (Device->ValidBindings == LAST_REAL_BINDING) {
  3874. PBINDING LoopbackBinding = NULL;
  3875. CTEAssert(Device->HighestExternalNicId == LAST_REAL_BINDING);
  3876. CTEAssert(Device->HighestLanNicId == LAST_REAL_BINDING);
  3877. CTEAssert(Device->SapNicCount == LAST_REAL_BINDING);
  3878. CTEAssert(Device->HighestType20NicId == LAST_REAL_BINDING);
  3879. //
  3880. // If we are left with one NIC, then we are on loopback only (and no real adapters).
  3881. // [Shreem]
  3882. //
  3883. Device->RealAdapters = FALSE;
  3884. //
  3885. // Put the old Loopback address into the Loopback binding.
  3886. //
  3887. LoopbackBinding = NIC_ID_TO_BINDING(Device, LOOPBACK_NIC_ID);
  3888. if (!Device->VirtualNetwork) {
  3889. LoopbackBinding->LocalAddress.NetworkAddress = REORDER_ULONG(INITIAL_LOOPBACK_NET_ADDRESS);
  3890. Device->SourceAddress.NetworkAddress = REORDER_ULONG(INITIAL_LOOPBACK_NET_ADDRESS);
  3891. ntStatus = RipInsertLocalNetwork(
  3892. LoopbackBinding->LocalAddress.NetworkAddress,
  3893. LoopbackBinding->NicId,
  3894. LoopbackBinding->Adapter->NdisBindingHandle,
  3895. (USHORT)((839 + LoopbackBinding->MediumSpeed) / LoopbackBinding->MediumSpeed));
  3896. if ((ntStatus != STATUS_SUCCESS) &&
  3897. (ntStatus != STATUS_DUPLICATE_NAME)) {
  3898. //
  3899. // We failed to insert, keep it at zero, hopefully
  3900. // we will be able to update later.
  3901. //
  3902. IPX_DEBUG(LOOPB, ("IPX: Could not insert net %lx for binding %lx\n",
  3903. REORDER_ULONG(LoopbackBinding->LocalAddress.NetworkAddress),
  3904. LoopbackBinding));
  3905. } else {
  3906. IPX_DEBUG(LOOPB, ("Inserted the loopback address in the RIP table\n"));
  3907. }
  3908. }
  3909. RtlCopyMemory (LoopbackBinding->LocalAddress.NodeAddress, InitialLoopbackNodeAddress, 6);
  3910. RtlCopyMemory (LoopbackBinding->LocalMacAddress.Address, InitialLoopbackNodeAddress, 6);
  3911. RtlCopyMemory (Device->SourceAddress.NodeAddress, LoopbackBinding->LocalAddress.NodeAddress, 6);
  3912. RtlCopyMemory ( Device->TdiRegistrationAddress->Address,
  3913. &LoopbackBinding->LocalAddress,
  3914. sizeof(TDI_ADDRESS_IPX));
  3915. if (STATUS_SUCCESS != (ntStatus = TdiRegisterNetAddress(Device->TdiRegistrationAddress,
  3916. &IpxDeviceName,
  3917. NULL,
  3918. &LoopbackBinding->TdiRegistrationHandle))) {
  3919. IPX_DEBUG(PNP, ("Error registering Loopback IPX address\n"));
  3920. }
  3921. IpxPnPInfo.FirstORLastDevice = FALSE;
  3922. //
  3923. //
  3924. // Shut down RIP timers, complete address notify requests, etc.
  3925. //
  3926. IpxPnPToLoad();
  3927. } else if (IPX_NODE_EQUAL(
  3928. NIC_ID_TO_BINDING(Device, LOOPBACK_NIC_ID)->LocalAddress.NodeAddress,
  3929. Binding->LocalAddress.NodeAddress)) {
  3930. PBINDING LoopbackBinding = NIC_ID_TO_BINDING(Device, LOOPBACK_NIC_ID);
  3931. //
  3932. // 195358
  3933. // It is likely that the adapter going away was the one that the loopback
  3934. // adapter was using. Fix it by finding the next LAN Adapter.
  3935. //
  3936. for (NicId = FIRST_REAL_BINDING; NicId < Device->HighestExternalNicId; NicId++) {
  3937. //
  3938. // Find the next one that is NOT going away.
  3939. //
  3940. if (NicId != Binding->NicId) {
  3941. if ((tBinding = NIC_ID_TO_BINDING(Device, NicId)) == NULL) {
  3942. CTEAssert(FALSE);
  3943. }
  3944. IPX_DEBUG(LOOPB, ("******** Using %d Nicid\n", NicId));
  3945. LoopbackBinding->LocalAddress.NetworkAddress = tBinding->LocalAddress.NetworkAddress;
  3946. RtlCopyMemory (LoopbackBinding->LocalAddress.NodeAddress, tBinding->LocalAddress.NodeAddress, 6);
  3947. RtlCopyMemory (LoopbackBinding->LocalMacAddress.Address, tBinding->LocalMacAddress.Address, 6);
  3948. RtlCopyMemory (Device->SourceAddress.NodeAddress, LoopbackBinding->LocalAddress.NodeAddress, 6);
  3949. Device->SourceAddress.NetworkAddress = tBinding->LocalAddress.NetworkAddress;
  3950. //
  3951. // We are done for now.
  3952. //
  3953. break;
  3954. }
  3955. }
  3956. IpxPnPInfo.FirstORLastDevice = FALSE;
  3957. } else {
  3958. CTEAssert(Device->State == DEVICE_STATE_OPEN);
  3959. IpxPnPInfo.FirstORLastDevice = FALSE;
  3960. }
  3961. //
  3962. // If this was a master binding, promote a slave binding to master.
  3963. //
  3964. // If binding is a slave binding, this code is skipped by the continue.
  3965. if (Binding->BindingSetMember) {
  3966. PBINDING tmpBinding;
  3967. int j;
  3968. CTEAssert(Binding->CurrentSendBinding);
  3969. CTEAssert(Binding->MasterBinding == Binding);
  3970. //
  3971. // Promote the next slave to Master.
  3972. //
  3973. newMasterBinding = Binding->NextBinding;
  3974. INSERT_BINDING(Device, Binding->NicId, newMasterBinding);
  3975. newMasterBinding->CurrentSendBinding = newMasterBinding;
  3976. newMasterBinding->MasterBinding = newMasterBinding;
  3977. //
  3978. // If this is the only binding remaining out of its set,
  3979. // it is no longer part of a set.
  3980. //
  3981. if (newMasterBinding->NextBinding == Binding) {
  3982. newMasterBinding->NextBinding = newMasterBinding->CurrentSendBinding = NULL;
  3983. newMasterBinding->BindingSetMember = FALSE;
  3984. newMasterBinding->ReceiveBroadcast = TRUE;
  3985. IPX_DEBUG(PNP, ("Master binding: %lx removed, no master: %lx\n", Binding, newMasterBinding));
  3986. } else {
  3987. //
  3988. // RESET: Make the newMasterBinding also the one to receiveBroadcasts [MS]
  3989. //
  3990. newMasterBinding->ReceiveBroadcast = TRUE;
  3991. //
  3992. // set the newMaster pointers in the other slaves [MS]
  3993. //
  3994. tmpBinding = newMasterBinding->NextBinding;
  3995. // This do-while loop assumes that tmpBinding != Binding before it starts.
  3996. do {
  3997. //
  3998. // make sure all bindings point to the new master [MS]
  3999. //
  4000. tmpBinding->MasterBinding = newMasterBinding;
  4001. tmpBinding->CurrentSendBinding = NULL;
  4002. tmpBinding->ReceiveBroadcast = FALSE;
  4003. if (tmpBinding->NextBinding == Binding) {
  4004. tmpBinding->NextBinding = newMasterBinding;
  4005. }
  4006. tmpBinding = tmpBinding->NextBinding;
  4007. } while (tmpBinding != newMasterBinding);
  4008. }
  4009. //
  4010. // Change the slave binding entries to have the master's NicId
  4011. //
  4012. // RipAdjustForBindingChange (Binding->NicId, newMasterBinding->NicId, IpxBindingMoved); // [MS]
  4013. RipAdjustForBindingChange (newMasterBinding->NicId, Binding->NicId, IpxBindingMoved);
  4014. IPX_DEBUG(PNP, ("RipAdjustForBindingChange (%d, %d, IpxBindingMoved)\n", newMasterBinding->NicId, Binding->NicId));
  4015. //
  4016. // Register slave's address with the TDI clients.
  4017. //
  4018. CTEAssert(!newMasterBinding->TdiRegistrationHandle);
  4019. RtlCopyMemory ( Device->TdiRegistrationAddress->Address,
  4020. &newMasterBinding->LocalAddress,
  4021. sizeof(TDI_ADDRESS_IPX));
  4022. if ((ntStatus = TdiRegisterNetAddress(
  4023. Device->TdiRegistrationAddress,
  4024. #if defined(_PNP_POWER_)
  4025. &IpxDeviceName,
  4026. NULL,
  4027. #endif _PNP_POWER_
  4028. &newMasterBinding->TdiRegistrationHandle)) != STATUS_SUCCESS) {
  4029. IPX_DEBUG(PNP, ("TdiRegisterNetAddress failed: %lx", ntStatus));
  4030. }
  4031. //
  4032. // Null out the slave binding
  4033. //
  4034. INSERT_BINDING(Device, newMasterBinding->NicId, NULL);
  4035. // Move other slave binding after the promoted binding foward.
  4036. for (j = newMasterBinding->NicId+1; j <= Device->ValidBindings; j++) {
  4037. PBINDING tmp;
  4038. tmp = NIC_ID_TO_BINDING_NO_ILOCK(Device, j);
  4039. ASSERT(tmp->NicId == j);
  4040. INSERT_BINDING(Device, j-1, tmp);
  4041. if (tmp) {
  4042. USHORT oldId = tmp->NicId;
  4043. --tmp->NicId;
  4044. RipAdjustForBindingChange (oldId, tmp->NicId, IpxBindingMoved);
  4045. }
  4046. }
  4047. INSERT_BINDING(Device, Device->ValidBindings, NULL);
  4048. // Device->ValidBindings-- is done below.
  4049. newMasterBinding->NicId = Binding->NicId;
  4050. } else {
  4051. ULONG j;
  4052. PBINDING WanBinding=NIC_ID_TO_BINDING_NO_ILOCK(Device, Device->HighestLanNicId+1);
  4053. if (WanBinding) {
  4054. --WanBinding->Adapter->LastWanNicId;
  4055. --WanBinding->Adapter->FirstWanNicId;
  4056. }
  4057. //
  4058. // Remove the binding from the array
  4059. //
  4060. RipAdjustForBindingChange (Binding->NicId, 0, IpxBindingDeleted);
  4061. for (j = Binding->NicId+1; j <= Device->ValidBindings; j++) {
  4062. PBINDING tmp;
  4063. INSERT_BINDING(Device, j-1, NIC_ID_TO_BINDING_NO_ILOCK(Device, j));
  4064. tmp = NIC_ID_TO_BINDING_NO_ILOCK(Device, j);
  4065. if (tmp) {
  4066. USHORT oldId = tmp->NicId;
  4067. --tmp->NicId;
  4068. RipAdjustForBindingChange(oldId, tmp->NicId, IpxBindingMoved);
  4069. }
  4070. }
  4071. INSERT_BINDING(Device, Device->ValidBindings, NULL);
  4072. --Device->HighestExternalNicId;
  4073. --Device->HighestLanNicId;
  4074. --Device->HighestType20NicId;
  4075. --Device->SapNicCount;
  4076. }
  4077. --Device->ValidBindings;
  4078. //
  4079. // If this is the first binding, NB's reserved will change.
  4080. // When we inform SPX of an address change later, we dont have
  4081. // this binding to know if this binding was indicated to SPX earlier.
  4082. // So, set SPXInformed, which is used later to determine if an address
  4083. // change is to be indicated to SPX later.
  4084. //
  4085. // Since NB is informed of all adapters, we inform of the reserved address
  4086. // change to NB if the new Binding (now at NicId 1) was indicated earlier.
  4087. //
  4088. if (Binding->NicId == FIRST_REAL_BINDING) {
  4089. NBReservedAddrChanged = TRUE;
  4090. if (Binding->IsnInformed[IDENTIFIER_SPX]) {
  4091. SPXInformed = TRUE;
  4092. }
  4093. }
  4094. CTEAssert(Binding->TdiRegistrationHandle);
  4095. //
  4096. // DeRegister this address with the TDI clients.
  4097. //
  4098. PAGED_CODE();
  4099. if (Binding->TdiRegistrationHandle) {
  4100. if ((ntStatus = TdiDeregisterNetAddress(Binding->TdiRegistrationHandle)) != STATUS_SUCCESS) {
  4101. IPX_DEBUG(PNP, ("TdiDeRegisterNetAddress failed: %lx", ntStatus));
  4102. } else {
  4103. Binding->TdiRegistrationHandle = NULL;
  4104. }
  4105. }
  4106. PAGED_CODE();
  4107. IPX_GET_LOCK(&Device->Lock, &LockHandle);
  4108. if (Device->UpperDriverBound[IDENTIFIER_NB]) {
  4109. IPX_FREE_LOCK(&Device->Lock, LockHandle);
  4110. //
  4111. // If this binding's addition was indicated earlier, indicate its deletion to NB.
  4112. //
  4113. if (Binding->IsnInformed[IDENTIFIER_NB]) {
  4114. IpxPnPInfo.NetworkAddress = Binding->LocalAddress.NetworkAddress;
  4115. RtlCopyMemory(IpxPnPInfo.NodeAddress, Binding->LocalAddress.NodeAddress, 6);
  4116. NIC_HANDLE_FROM_NIC(IpxPnPInfo.NicHandle, Binding->NicId);
  4117. IpxPnPInfo.FirstORLastDevice = FALSE;
  4118. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  4119. IPX_DEBUG(PNP, ("Inform NB: delete LAN device: %lx\n", Binding));
  4120. CTEAssert(Binding->NicId != LOOPBACK_NIC_ID);
  4121. (*Device->UpperDrivers[IDENTIFIER_NB].PnPHandler) (
  4122. IPX_PNP_DELETE_DEVICE,
  4123. &IpxPnPInfo);
  4124. Binding->IsnInformed[IDENTIFIER_NB] = FALSE;
  4125. IPX_DEBUG(PNP,("Indicate to NB IPX_PNP_DELETE_DEVICE with FirstORLastDevice = (%d)",IpxPnPInfo.FirstORLastDevice));
  4126. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  4127. //
  4128. // If this was a Master, indicate the addition of the (promoted) slave
  4129. //
  4130. if (Binding->BindingSetMember) {
  4131. IpxPnPInfo.NetworkAddress = newMasterBinding->LocalAddress.NetworkAddress;
  4132. RtlCopyMemory(IpxPnPInfo.NodeAddress, newMasterBinding->LocalAddress.NodeAddress, 6);
  4133. NIC_HANDLE_FROM_NIC(IpxPnPInfo.NicHandle, newMasterBinding->NicId);
  4134. //
  4135. // In this case, we set the ReservedAddrChanged bit here itself so dont need
  4136. // to indicate a separate address changed.
  4137. //
  4138. IpxPnPInfo.NewReservedAddress = (NBReservedAddrChanged) ? TRUE : FALSE;
  4139. NBReservedAddrChanged = FALSE;
  4140. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  4141. IPX_DEBUG(PNP, ("Inform NB: add slave device: NicId: %lx\n", Binding->NicId));
  4142. ASSERT(IpxHasInformedNbLoopback());
  4143. ASSERT(Binding->NicId != LOOPBACK_NIC_ID);
  4144. ASSERT(IpxPnPInfo.FirstORLastDevice == FALSE);
  4145. (*Device->UpperDrivers[IDENTIFIER_NB].PnPHandler) (
  4146. IPX_PNP_ADD_DEVICE,
  4147. &IpxPnPInfo);
  4148. newMasterBinding->IsnInformed[IDENTIFIER_NB] = TRUE;
  4149. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  4150. }
  4151. }
  4152. } else {
  4153. IPX_FREE_LOCK(&Device->Lock, LockHandle);
  4154. }
  4155. //
  4156. // Last device - inform SPX if it is bound and this device was added earlier.
  4157. //
  4158. if (IpxPnPInfo.FirstORLastDevice) {
  4159. IPX_DEBUG(PNP, ("Last device - inform SPX\n"));
  4160. IPX_GET_LOCK(&Device->Lock, &LockHandle);
  4161. if (Device->UpperDriverBound[IDENTIFIER_SPX]) {
  4162. IPX_FREE_LOCK(&Device->Lock, LockHandle);
  4163. if (Binding->IsnInformed[IDENTIFIER_SPX]) {
  4164. IpxPnPInfo.NetworkAddress = Device->SourceAddress.NetworkAddress;
  4165. RtlCopyMemory(IpxPnPInfo.NodeAddress, Device->SourceAddress.NodeAddress, 6);
  4166. if (Device->VirtualNetwork) {
  4167. NIC_HANDLE_FROM_NIC(IpxPnPInfo.NicHandle, 0);
  4168. } else {
  4169. NIC_HANDLE_FROM_NIC(IpxPnPInfo.NicHandle, 1);
  4170. }
  4171. NIC_HANDLE_FROM_NIC(IpxPnPInfo.NicHandle, Binding->NicId);
  4172. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  4173. IPX_DEBUG(PNP, ("Inform SPX: last LAN device\n"));
  4174. (*Device->UpperDrivers[IDENTIFIER_SPX].PnPHandler) (
  4175. IPX_PNP_DELETE_DEVICE,
  4176. &IpxPnPInfo);
  4177. Binding->IsnInformed[IDENTIFIER_SPX] = FALSE;
  4178. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  4179. }
  4180. } else {
  4181. IPX_FREE_LOCK(&Device->Lock, LockHandle);
  4182. }
  4183. }
  4184. //
  4185. // Unbind from the adapter so it can be deleted
  4186. //
  4187. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  4188. if (Adapter->BindingCount == 1) {
  4189. // The adapter will be destroyed if this is the last binding.
  4190. IpxUnBindFromAdapter(Binding);
  4191. break;
  4192. } else {
  4193. IpxUnBindFromAdapter(Binding);
  4194. }
  4195. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  4196. }
  4197. //
  4198. // Update the Device and RIP tables if this is not the last device.
  4199. // If the reserved address changed, inform NB and SPX of this change.
  4200. //
  4201. if (!IpxPnPInfo.FirstORLastDevice) {
  4202. Binding = NIC_ID_TO_BINDING_NO_ILOCK(Device, 1);
  4203. if (IpxNewVirtualNetwork(Device, NewVirtualNetwork)) {
  4204. IPX_DEBUG(PNP, ("SPX's reserved address changed\n"));
  4205. //
  4206. // SPX's reserved address changed
  4207. //
  4208. IpxPnPInfo.NewReservedAddress = TRUE;
  4209. IPX_GET_LOCK(&Device->Lock, &LockHandle);
  4210. if (Device->UpperDriverBound[IDENTIFIER_SPX]) {
  4211. IPX_FREE_LOCK(&Device->Lock, LockHandle);
  4212. //
  4213. // If this binding's addition was indicated earlier, indicate change of address.
  4214. //
  4215. if (SPXInformed) {
  4216. Binding->IsnInformed[IDENTIFIER_SPX] = TRUE;
  4217. IPX_DEBUG(PNP, ("Inform SPX: reserved address changed\n"));
  4218. IpxPnPInfo.NetworkAddress = Device->SourceAddress.NetworkAddress;
  4219. RtlCopyMemory(IpxPnPInfo.NodeAddress, Device->SourceAddress.NodeAddress, 6);
  4220. if (Device->VirtualNetwork) {
  4221. //
  4222. // new one appeared
  4223. //
  4224. NIC_HANDLE_FROM_NIC(IpxPnPInfo.NicHandle, 0);
  4225. } else {
  4226. //
  4227. // Old one disappeared
  4228. //
  4229. NIC_HANDLE_FROM_NIC(IpxPnPInfo.NicHandle, 1);
  4230. }
  4231. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  4232. (*Device->UpperDrivers[IDENTIFIER_SPX].PnPHandler) (
  4233. IPX_PNP_ADDRESS_CHANGE,
  4234. &IpxPnPInfo);
  4235. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  4236. }
  4237. } else {
  4238. IPX_FREE_LOCK(&Device->Lock, LockHandle);
  4239. }
  4240. } else {
  4241. //
  4242. // Set the first binding's flag so that when this binding goes away, we remember
  4243. // to inform SPX of this device's removal.
  4244. //
  4245. IPX_DEBUG(PNP, ("Transfer SPX informed flag to NicId: %lx\n", Binding->NicId));
  4246. Binding->IsnInformed[IDENTIFIER_SPX] = TRUE;
  4247. }
  4248. if (NBReservedAddrChanged) {
  4249. //
  4250. // NB's reserved address changed.
  4251. //
  4252. IpxPnPInfo.NewReservedAddress = TRUE;
  4253. IPX_GET_LOCK(&Device->Lock, &LockHandle);
  4254. if (Device->UpperDriverBound[IDENTIFIER_NB]) {
  4255. IPX_FREE_LOCK(&Device->Lock, LockHandle);
  4256. //
  4257. // If this binding's addition was indicated earlier, indicate the change of reserved address.
  4258. //
  4259. if (Binding->IsnInformed[IDENTIFIER_NB]) {
  4260. IpxPnPInfo.NetworkAddress = Binding->LocalAddress.NetworkAddress;
  4261. RtlCopyMemory(IpxPnPInfo.NodeAddress, Binding->LocalAddress.NodeAddress, 6);
  4262. NIC_HANDLE_FROM_NIC(IpxPnPInfo.NicHandle, Binding->NicId);
  4263. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  4264. IPX_DEBUG(PNP, ("Inform NB: reserved address changed\n"));
  4265. (*Device->UpperDrivers[IDENTIFIER_NB].PnPHandler) (
  4266. IPX_PNP_ADDRESS_CHANGE,
  4267. &IpxPnPInfo);
  4268. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  4269. }
  4270. } else {
  4271. IPX_FREE_LOCK(&Device->Lock, LockHandle);
  4272. }
  4273. }
  4274. }
  4275. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  4276. }
  4277. //
  4278. // Re-calculate the values of datagram sizes in the Device.
  4279. //
  4280. IpxPnPUpdateDevice(Device);
  4281. IPX_DEBUG(PNP, ("BindingCount: %lu\n", Device->BindingCount));
  4282. IPX_DEBUG(PNP, ("ValidBindings: %lu\n", Device->ValidBindings));
  4283. IPX_DEBUG(PNP, ("HighestLanNicId: %lu\n", Device->HighestLanNicId));
  4284. IPX_DEBUG(PNP, ("HighestExternalNicId: %lu\n", Device->HighestExternalNicId));
  4285. IPX_DEBUG(PNP, ("HighestType20NicId: %lu\n", Device->HighestType20NicId));
  4286. IPX_DEBUG(PNP, ("SapNicCount: %lu\n", Device->SapNicCount));
  4287. IPX_DEBUG(PNP, ("BindingArray: %lx\n", Device->Bindings));
  4288. *Status = NDIS_STATUS_SUCCESS;
  4289. } /* IpxUnbindAdapter */
  4290. #if defined TRANSLATE
  4291. VOID
  4292. IpxTranslate(
  4293. OUT PNDIS_STATUS Status,
  4294. IN NDIS_HANDLE ProtocolBindingContext,
  4295. OUT PNET_PNP_ID IdList,
  4296. IN ULONG IdListLength,
  4297. OUT PULONG BytesReturned
  4298. )
  4299. /*++
  4300. Routine Description:
  4301. This routine receives control from the physical provider as an
  4302. indication that a frame has been received on the physical link.
  4303. The packet passed up from NDIS can be held on to by the TDI clients
  4304. that request TDI_EVENT_RECEIVE_EX_DATAGRAM events with us.
  4305. Arguments:
  4306. ProtocolBindingContext - The Adapter Binding specified at initialization time.
  4307. ReceivedPacket - The packet received
  4308. MediaSpecificInformation - Used for media such as Irda, wireless, etc. Not used here.
  4309. HeaderBufferSize - Size of the MAC header
  4310. Return Value:
  4311. --*/
  4312. {
  4313. } /* IpxTranslate */
  4314. #endif
  4315. NTSTATUS
  4316. IpxBindLoopbackAdapter(
  4317. )
  4318. /*++
  4319. Routine Description:
  4320. This routine creates a loopback adapter for IPX.
  4321. This function is internal to IPX and is called during
  4322. DriverEntry. This adapter will stick around for ever.
  4323. Arguments:
  4324. Return Value:
  4325. Status - NDIS_STATUS_SUCCESS
  4326. --*/
  4327. {
  4328. UCHAR InitialLoopbackNodeAddress[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x02};
  4329. NTSTATUS ntStatus;
  4330. PDEVICE Device = IpxDevice;
  4331. CONFIG Config;
  4332. UINT i;
  4333. ULONG Temp, SuccessfulOpens=0;
  4334. PBINDING LoopbackBinding;
  4335. BINDING_CONFIG ConfigBinding;
  4336. BOOLEAN FirstDevice = FALSE;
  4337. PADAPTER AdapterPtr;
  4338. UNICODE_STRING AdapterName;
  4339. IPX_DEFINE_LOCK_HANDLE(LockHandle1)
  4340. IPX_DEFINE_LOCK_HANDLE(LockHandle)
  4341. //
  4342. // Used for error logging
  4343. //
  4344. Config.DriverObject = (PDRIVER_OBJECT)Device->DeviceObject;
  4345. Config.RegistryPathBuffer = Device->RegistryPathBuffer;
  4346. //
  4347. // Create the loopback binding first.
  4348. //
  4349. if (!NIC_ID_TO_BINDING(Device, (SHORT)LOOPBACK_NIC_ID)) {
  4350. //
  4351. // Prime the Loopback binding too.
  4352. //
  4353. //
  4354. // First allocate the memory for the binding.
  4355. //
  4356. ntStatus = IpxCreateBinding(
  4357. Device,
  4358. NULL,
  4359. 0,
  4360. L"IpxInternalLLoopbackAdapter",
  4361. &LoopbackBinding);
  4362. // 289740
  4363. if (ntStatus != STATUS_SUCCESS) {
  4364. IpxWriteGeneralErrorLog(
  4365. (PVOID)IpxDevice->DeviceObject,
  4366. EVENT_TRANSPORT_RESOURCE_POOL,
  4367. 814,
  4368. ntStatus,
  4369. L"IpxBindLoopbackAdapter: failed to create loopback binding",
  4370. 0,
  4371. NULL);
  4372. DbgPrint("IPX: IpxCreateBinding on loopback binding failed with status %x\n.",ntStatus);
  4373. return ntStatus;
  4374. }
  4375. RtlInitUnicodeString(&AdapterName, L"\\Device\\IpxLoopbackAdapter");
  4376. ntStatus = IpxCreateAdapter(
  4377. Device,
  4378. &AdapterName,
  4379. &AdapterPtr
  4380. );
  4381. // 289740
  4382. if (ntStatus != STATUS_SUCCESS) {
  4383. IpxDestroyBinding(LoopbackBinding);
  4384. return ntStatus;
  4385. }
  4386. //
  4387. // Initialize the LoopbackBinding details first.
  4388. //
  4389. LoopbackBinding->NicId = (USHORT)LOOPBACK_NIC_ID;
  4390. LoopbackBinding->FwdAdapterContext = VIRTUAL_NET_FORWARDER_CONTEXT;
  4391. LoopbackBinding->Device = Device;
  4392. LoopbackBinding->DeviceLock = &Device->Lock;
  4393. LoopbackBinding->MaxSendPacketSize = 1514;
  4394. LoopbackBinding->AutoDetect = FALSE;
  4395. LoopbackBinding->MediumSpeed = 100000; // in units of 100 bytes/sec
  4396. //
  4397. // The loopback node address starts out 0x000000000001
  4398. //
  4399. LoopbackBinding->BindingSetMember = FALSE;
  4400. LoopbackBinding->SendFrameHandler = IpxSendFrame802_3802_2; ;
  4401. LoopbackBinding->FrameType = ISN_FRAME_TYPE_802_2;
  4402. LoopbackBinding->DefHeaderSize = 17; //802_3 802_2
  4403. LoopbackBinding->BcMcHeaderSize = 17; //802_3 802_2
  4404. LoopbackBinding->AnnouncedMaxDatagramSize = 1514; // what we advertise -- assumes worst-case SR
  4405. LoopbackBinding->RealMaxDatagramSize = 1514; // what will really break the card
  4406. LoopbackBinding->MaxLookaheadData = 200;
  4407. //
  4408. // Indicates whether this binding was indicated to the ISN driver
  4409. //
  4410. for (i = 0; i < UPPER_DRIVER_COUNT; i++) {
  4411. LoopbackBinding->IsnInformed[i] = FALSE;
  4412. }
  4413. LoopbackBinding->MaxLookaheadData =
  4414. LoopbackBinding->MaxSendPacketSize -
  4415. sizeof(IPX_HEADER) -
  4416. (LoopbackBinding->DefHeaderSize - 14);
  4417. LoopbackBinding->AnnouncedMaxDatagramSize =
  4418. LoopbackBinding->MaxSendPacketSize -
  4419. 14 -
  4420. sizeof(IPX_HEADER) -
  4421. (LoopbackBinding->DefHeaderSize - 14);
  4422. LoopbackBinding->RealMaxDatagramSize =
  4423. LoopbackBinding->MaxSendPacketSize -
  4424. 14 -
  4425. sizeof(IPX_HEADER) -
  4426. (LoopbackBinding->DefHeaderSize - 14);
  4427. //
  4428. // Copy over all the values from the first WAN binding created above.
  4429. //
  4430. INSERT_BINDING(Device, (SHORT)LOOPBACK_NIC_ID, LoopbackBinding);
  4431. IpxReferenceBinding(LoopbackBinding, BREF_FWDOPEN); // so it appears the FWD opened it.
  4432. //
  4433. // Now fill in the Adapter details
  4434. //
  4435. AdapterPtr->ConfigMaxPacketSize = 1514;
  4436. AdapterPtr->SourceRouting = FALSE;
  4437. AdapterPtr->BindSap = 0x8137;
  4438. AdapterPtr->BindSapNetworkOrder = 0x3781;
  4439. AdapterPtr->MacInfo.SourceRouting = FALSE;
  4440. AdapterPtr->MacInfo.MediumAsync = FALSE;
  4441. AdapterPtr->MacInfo.BroadcastMask = 0x01;
  4442. AdapterPtr->MacInfo.MaxHeaderLength = 14;
  4443. AdapterPtr->MacInfo.MinHeaderLength = 14;
  4444. AdapterPtr->MacInfo.MacOptions = 14;
  4445. AdapterPtr->MacInfo.MediumType = NdisMedium802_3;
  4446. AdapterPtr->DefHeaderSizes[ISN_FRAME_TYPE_802_2] = 17;
  4447. AdapterPtr->DefHeaderSizes[ISN_FRAME_TYPE_802_3] = 14;
  4448. AdapterPtr->DefHeaderSizes[ISN_FRAME_TYPE_ETHERNET_II] = 14;
  4449. AdapterPtr->DefHeaderSizes[ISN_FRAME_TYPE_SNAP] = 22;
  4450. AdapterPtr->BcMcHeaderSizes[ISN_FRAME_TYPE_802_2] = 17;
  4451. AdapterPtr->BcMcHeaderSizes[ISN_FRAME_TYPE_802_3] = 14;
  4452. AdapterPtr->BcMcHeaderSizes[ISN_FRAME_TYPE_ETHERNET_II] = 14;
  4453. AdapterPtr->BcMcHeaderSizes[ISN_FRAME_TYPE_SNAP] = 22;
  4454. AdapterPtr->Bindings[ISN_FRAME_TYPE_802_2] = LoopbackBinding;
  4455. AdapterPtr->Bindings[ISN_FRAME_TYPE_802_3] = NULL;
  4456. AdapterPtr->Bindings[ISN_FRAME_TYPE_ETHERNET_II] = NULL;
  4457. AdapterPtr->Bindings[ISN_FRAME_TYPE_SNAP] = NULL;
  4458. ++AdapterPtr->BindingCount;
  4459. AdapterPtr->NdisBindingHandle = NULL;
  4460. LoopbackBinding->Adapter = AdapterPtr;
  4461. //
  4462. // These were missed [137536].
  4463. //
  4464. AdapterPtr->MediumSpeed = 100000;
  4465. AdapterPtr->MaxReceivePacketSize = 1500;
  4466. AdapterPtr->MaxSendPacketSize = 1514;
  4467. AdapterPtr->ReceiveBufferSpace = 51264;
  4468. }
  4469. //
  4470. // Update the indices
  4471. //
  4472. Device->HighestLanNicId++;
  4473. Device->HighestExternalNicId++;
  4474. Device->ValidBindings++;
  4475. Device->HighestType20NicId++;
  4476. Device->SapNicCount++;
  4477. // These get updated in every BindAdapter.
  4478. Device->Information.MaxDatagramSize = LoopbackBinding->RealMaxDatagramSize;
  4479. Device->RealMaxDatagramSize = LoopbackBinding->RealMaxDatagramSize;
  4480. Device->Information.MaximumLookaheadData = LoopbackBinding->MaxLookaheadData;
  4481. Device->LinkSpeed = LoopbackBinding->MediumSpeed;
  4482. Device->MacOptions = AdapterPtr->MacInfo.MacOptions;
  4483. if (Device->FirstLanNicId == (USHORT)-1) {
  4484. Device->FirstLanNicId = LoopbackBinding->NicId;
  4485. }
  4486. //
  4487. // If at least one card appeared here, set our state
  4488. // to open
  4489. //
  4490. if (Device->ValidBindings > 0) {
  4491. if (Device->State == DEVICE_STATE_LOADED) {
  4492. FirstDevice = TRUE;
  4493. Device->State = DEVICE_STATE_OPEN;
  4494. Device->RealAdapters = FALSE; // no adapters are loaded at this point.
  4495. }
  4496. }
  4497. //
  4498. // Read the registry to see if a virtual network number appeared/disappeared
  4499. //
  4500. ntStatus = IpxPnPGetVirtualNetworkNumber(&Config);
  4501. if (ntStatus != STATUS_SUCCESS) {
  4502. IPX_DEBUG(PNP, ("Could not read the vnet#: registrypathbuffer: %lx\n", Device->RegistryPathBuffer));
  4503. return NDIS_STATUS_SUCCESS;
  4504. }
  4505. Temp = REORDER_ULONG (Config.Parameters[CONFIG_VIRTUAL_NETWORK]);
  4506. if (0 == Temp) {
  4507. Device->VirtualNetworkNumber = 0;
  4508. Device->VirtualNetwork = FALSE;
  4509. LoopbackBinding->LocalAddress.NetworkAddress = REORDER_ULONG(INITIAL_LOOPBACK_NET_ADDRESS);
  4510. RtlCopyMemory (LoopbackBinding->LocalAddress.NodeAddress,InitialLoopbackNodeAddress, 6);
  4511. Device->SourceAddress.NetworkAddress = REORDER_ULONG(INITIAL_LOOPBACK_NET_ADDRESS);
  4512. RtlCopyMemory (LoopbackBinding->LocalMacAddress.Address, InitialLoopbackNodeAddress, 6);
  4513. RtlCopyMemory (Device->SourceAddress.NodeAddress, LoopbackBinding->LocalAddress.NodeAddress, 6);
  4514. ntStatus = RipInsertLocalNetwork(
  4515. LoopbackBinding->LocalAddress.NetworkAddress,
  4516. LoopbackBinding->NicId,
  4517. LoopbackBinding->Adapter->NdisBindingHandle,
  4518. (USHORT)((839 + LoopbackBinding->MediumSpeed) / LoopbackBinding->MediumSpeed));
  4519. if ((ntStatus != STATUS_SUCCESS) &&
  4520. (ntStatus != STATUS_DUPLICATE_NAME)) {
  4521. //
  4522. // We failed to insert, keep it at zero, hopefully
  4523. // we will be able to update later.
  4524. //
  4525. IPX_DEBUG(LOOPB, ("IPX: Could not insert net %lx for binding %lx\n",
  4526. REORDER_ULONG(LoopbackBinding->LocalAddress.NetworkAddress),
  4527. LoopbackBinding));
  4528. } else {
  4529. IPX_DEBUG(LOOPB, ("Inserted the loopback address in the RIP table\n"));
  4530. }
  4531. } else {
  4532. Device->VirtualNetworkNumber = Temp;
  4533. IpxNewVirtualNetwork(Device,TRUE);
  4534. }
  4535. IPX_DEBUG(PNP, ("Virtual net # is: %lx/%lx\n", Temp, REORDER_ULONG(INITIAL_LOOPBACK_NET_ADDRESS)));
  4536. if (FirstDevice) {
  4537. UNICODE_STRING devicename;
  4538. //
  4539. // Inform TDI clients about the open of our device object.
  4540. //
  4541. devicename.MaximumLength = (USHORT)Device->DeviceNameLength;
  4542. devicename.Length = (USHORT)Device->DeviceNameLength - sizeof(WCHAR);
  4543. devicename.Buffer = Device->DeviceName;
  4544. if ((ntStatus = TdiRegisterDeviceObject(
  4545. &devicename,
  4546. &Device->TdiRegistrationHandle)) != STATUS_SUCCESS) {
  4547. DbgPrint("IPX:TdiRegisterDeviceObject failed: %lx", ntStatus);
  4548. Device->TdiRegistrationHandle = NULL;
  4549. }
  4550. }
  4551. LoopbackBinding->PastAutoDetection = TRUE;
  4552. //
  4553. // Register this address with the TDI clients.
  4554. // 1. dereg later
  4555. // 2. which address is this?
  4556. //
  4557. RtlCopyMemory (Device->TdiRegistrationAddress->Address, &LoopbackBinding->LocalAddress, sizeof(TDI_ADDRESS_IPX));
  4558. if ((ntStatus = TdiRegisterNetAddress(
  4559. Device->TdiRegistrationAddress,
  4560. &IpxDeviceName,
  4561. NULL,
  4562. &LoopbackBinding->TdiRegistrationHandle)) != STATUS_SUCCESS) {
  4563. IPX_DEBUG(PNP, ("TdiRegisterNetAddress failed: %lx", ntStatus));
  4564. }
  4565. IPX_DEBUG(PNP, ("BindingCount: %lu\n", Device->BindingCount));
  4566. IPX_DEBUG(PNP, ("ValidBindings: %lu\n", Device->ValidBindings));
  4567. IPX_DEBUG(PNP, ("HighestLanNicId: %lu\n", Device->HighestLanNicId));
  4568. IPX_DEBUG(PNP, ("HighestExternalNicId: %lu\n", Device->HighestExternalNicId));
  4569. IPX_DEBUG(PNP, ("HighestType20NicId: %lu\n", Device->HighestType20NicId));
  4570. IPX_DEBUG(PNP, ("SapNicCount: %lu\n", Device->SapNicCount));
  4571. IPX_DEBUG(PNP, ("BindingArray: %lx\n", Device->Bindings));
  4572. return NDIS_STATUS_SUCCESS;
  4573. } /* IpxBindLoopbackAdapter */