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.

2519 lines
75 KiB

  1. /*++
  2. Copyright(c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. brdgmini.c
  5. Abstract:
  6. Ethernet MAC level bridge.
  7. Miniport section
  8. Author:
  9. Mark Aiken
  10. (original bridge by Jameel Hyder)
  11. Environment:
  12. Kernel mode driver
  13. Revision History:
  14. Sept 1999 - Original version
  15. Feb 2000 - Overhaul
  16. --*/
  17. #define NDIS_MINIPORT_DRIVER
  18. #define NDIS50_MINIPORT 1
  19. #define NDIS_WDM 1
  20. #pragma warning( push, 3 )
  21. #include <ndis.h>
  22. #pragma warning( pop )
  23. #include <netevent.h>
  24. #include "bridge.h"
  25. #include "brdgmini.h"
  26. #include "brdgfwd.h"
  27. #include "brdgprot.h"
  28. #include "brdgbuf.h"
  29. #include "brdgsta.h"
  30. #include "brdgcomp.h"
  31. // ===========================================================================
  32. //
  33. // GLOBALS
  34. //
  35. // ===========================================================================
  36. // NDIS Wrapper handle
  37. NDIS_HANDLE gNDISWrapperHandle = NULL;
  38. // Handle to our miniport driver
  39. NDIS_HANDLE gMiniPortDriverHandle = NULL;
  40. // ----------------------------------------------
  41. // The handle of the miniport (NULL if not initialized)
  42. NDIS_HANDLE gMiniPortAdapterHandle = NULL;
  43. // Refcount to allow waiting for other code to finish using the miniport
  44. WAIT_REFCOUNT gMiniPortAdapterRefcount;
  45. // Refcount indicating whether the bridge miniport is media-connected
  46. WAIT_REFCOUNT gMiniPortConnectedRefcount;
  47. // Refcount indicating whether the bridge miniport is in the middle of a media
  48. // state toggle.
  49. WAIT_REFCOUNT gMiniPortToggleRefcount;
  50. // ----------------------------------------------
  51. //
  52. // Refcount for use in passing through requests to underlying NICs
  53. // This works because NDIS doesn't make requests re-entrantly. That
  54. // is, only one SetInfo operation can be pending at any given time.
  55. //
  56. LONG gRequestRefCount;
  57. // ----------------------------------------------
  58. // Virtual characteristics of the bridge adapter
  59. ULONG gBridgeLinkSpeed = 10000L, // Start at 1Mbps, since reporting
  60. // zero makes some components unhappy.
  61. // Measured in 100's of bps.
  62. gBridgeMediaState = NdisMediaStateDisconnected;
  63. // MAC Address of the bridge. This does not change once
  64. // it has been set.
  65. UCHAR gBridgeAddress[ETH_LENGTH_OF_ADDRESS];
  66. // Whether we have chosen an address yet
  67. BOOLEAN gHaveAddress;
  68. // Current bridge packet filter
  69. ULONG gPacketFilter = 0L;
  70. // Current multicast list
  71. PUCHAR gMulticastList = NULL;
  72. ULONG gMulticastListLength = 0L;
  73. // Device name of the bridge miniport (from the registry)
  74. PWCHAR gBridgeDeviceName = NULL;
  75. ULONG gBridgeDeviceNameSize = 0L;
  76. // RW lock to protect all above bridge variables
  77. NDIS_RW_LOCK gBridgeStateLock;
  78. //-----------------------------------------------
  79. // Name of the registry entry for the device name
  80. const PWCHAR gDeviceNameEntry = L"Device";
  81. // Description of our miniport
  82. const PCHAR gDriverDescription = "Microsoft MAC Bridge Virtual NIC";
  83. // ----------------------------------------------
  84. // Device object so user-mode code can talk to us
  85. PDEVICE_OBJECT gDeviceObject = NULL;
  86. // NDIS handle to track the device object
  87. NDIS_HANDLE gDeviceHandle = NULL;
  88. // ----------------------------------------------
  89. // List of supported OIDs
  90. NDIS_OID gSupportedOIDs[] =
  91. {
  92. // General characteristics
  93. OID_GEN_SUPPORTED_LIST,
  94. OID_GEN_HARDWARE_STATUS,
  95. OID_GEN_MEDIA_SUPPORTED,
  96. OID_GEN_MEDIA_IN_USE,
  97. OID_GEN_MAXIMUM_LOOKAHEAD,
  98. OID_GEN_MAXIMUM_FRAME_SIZE,
  99. OID_GEN_LINK_SPEED,
  100. OID_GEN_TRANSMIT_BUFFER_SPACE,
  101. OID_GEN_RECEIVE_BUFFER_SPACE,
  102. OID_GEN_TRANSMIT_BLOCK_SIZE,
  103. OID_GEN_RECEIVE_BLOCK_SIZE,
  104. OID_GEN_VENDOR_ID,
  105. OID_GEN_VENDOR_DESCRIPTION,
  106. OID_GEN_CURRENT_PACKET_FILTER,
  107. OID_GEN_CURRENT_LOOKAHEAD,
  108. OID_GEN_DRIVER_VERSION,
  109. OID_GEN_MAXIMUM_TOTAL_SIZE,
  110. OID_GEN_PROTOCOL_OPTIONS,
  111. OID_GEN_MAC_OPTIONS,
  112. OID_GEN_MEDIA_CONNECT_STATUS,
  113. OID_GEN_MAXIMUM_SEND_PACKETS,
  114. OID_GEN_VENDOR_DRIVER_VERSION,
  115. // Set only characteristics (relayed)
  116. OID_GEN_NETWORK_LAYER_ADDRESSES,
  117. OID_GEN_TRANSPORT_HEADER_OFFSET,
  118. // General statistics
  119. OID_GEN_XMIT_OK,
  120. OID_GEN_RCV_OK,
  121. OID_GEN_XMIT_ERROR,
  122. OID_GEN_RCV_NO_BUFFER,
  123. OID_GEN_RCV_NO_BUFFER,
  124. OID_GEN_DIRECTED_BYTES_XMIT,
  125. OID_GEN_DIRECTED_FRAMES_XMIT,
  126. OID_GEN_MULTICAST_BYTES_XMIT,
  127. OID_GEN_MULTICAST_FRAMES_XMIT,
  128. OID_GEN_BROADCAST_BYTES_XMIT,
  129. OID_GEN_BROADCAST_FRAMES_XMIT,
  130. OID_GEN_DIRECTED_BYTES_RCV,
  131. OID_GEN_DIRECTED_FRAMES_RCV,
  132. OID_GEN_MULTICAST_BYTES_RCV,
  133. OID_GEN_MULTICAST_FRAMES_RCV,
  134. OID_GEN_BROADCAST_BYTES_RCV,
  135. OID_GEN_BROADCAST_FRAMES_RCV,
  136. // Ethernet characteristics
  137. OID_802_3_PERMANENT_ADDRESS,
  138. OID_802_3_CURRENT_ADDRESS,
  139. OID_802_3_MULTICAST_LIST,
  140. OID_802_3_MAXIMUM_LIST_SIZE,
  141. // Ethernet statistics
  142. OID_802_3_RCV_ERROR_ALIGNMENT,
  143. OID_802_3_XMIT_ONE_COLLISION,
  144. OID_802_3_XMIT_MORE_COLLISIONS,
  145. // PnP OIDs
  146. OID_PNP_QUERY_POWER,
  147. OID_PNP_SET_POWER,
  148. // tcp oids
  149. OID_TCP_TASK_OFFLOAD
  150. };
  151. // 1394 specific related global variables
  152. #define OID_1394_ENTER_BRIDGE_MODE 0xFF00C914
  153. #define OID_1394_EXIT_BRIDGE_MODE 0xFF00C915
  154. // Set when the bridge knows that tcpip has been loaded
  155. // set on receiving the OID_TCP_TASK_OFFLOAD Oid
  156. BOOLEAN g_fIsTcpIpLoaded = FALSE;
  157. // ===========================================================================
  158. //
  159. // PRIVATE PROTOTYPES
  160. //
  161. // ===========================================================================
  162. VOID
  163. BrdgMiniHalt(
  164. IN NDIS_HANDLE MiniportAdapterContext
  165. );
  166. NDIS_STATUS
  167. BrdgMiniInitialize(
  168. OUT PNDIS_STATUS OpenErrorStatus,
  169. OUT PUINT SelectedMediumIndex,
  170. IN PNDIS_MEDIUM MediumArray,
  171. IN UINT MediumArraySize,
  172. IN NDIS_HANDLE MiniportAdapterHandle,
  173. IN NDIS_HANDLE WrapperConfigurationContext
  174. );
  175. NDIS_STATUS
  176. BrdgMiniQueryInfo(
  177. IN NDIS_HANDLE MiniportAdapterContext,
  178. IN NDIS_OID Oid,
  179. IN PVOID InformationBuffer,
  180. IN ULONG InformationBufferLength,
  181. OUT PULONG BytesWritten,
  182. OUT PULONG BytesNeeded
  183. );
  184. NDIS_STATUS
  185. BrdgMiniReset(
  186. OUT PBOOLEAN AddressingReset,
  187. IN NDIS_HANDLE MiniportAdapterContext
  188. );
  189. VOID
  190. BrdgMiniSendPackets(
  191. IN NDIS_HANDLE MiniportAdapterContext,
  192. IN PPNDIS_PACKET PacketArray,
  193. IN UINT NumberOfPackets
  194. );
  195. NDIS_STATUS
  196. BrdgMiniSetInfo(
  197. IN NDIS_HANDLE MiniportAdapterContext,
  198. IN NDIS_OID Oid,
  199. IN PVOID InformationBuffer,
  200. IN ULONG InformationBufferLength,
  201. OUT PULONG BytesRead,
  202. OUT PULONG BytesNeeded
  203. );
  204. BOOLEAN
  205. BrdgMiniAddrIsInMultiList(
  206. IN PUCHAR pTargetAddr
  207. );
  208. VOID
  209. BrdgMiniRelayedRequestComplete(
  210. PNDIS_REQUEST_BETTER pRequest,
  211. PVOID unused
  212. );
  213. VOID
  214. BrdgMiniReAcquireMiniport();
  215. // ===========================================================================
  216. //
  217. // PUBLIC FUNCTIONS
  218. //
  219. // ===========================================================================
  220. NTSTATUS
  221. BrdgMiniDriverInit()
  222. /*++
  223. Routine Description:
  224. Load-time initialization function
  225. Must run at PASSIVE_LEVEL since we call NdisRegisterDevice().
  226. Arguments:
  227. None
  228. Return Value:
  229. Status of initialization. A return code != STATUS_SUCCESS causes driver load
  230. to fail. Any event causing a failure return code must be logged, as it
  231. prevents us from loading successfully.
  232. --*/
  233. {
  234. NDIS_MINIPORT_CHARACTERISTICS MiniPortChars;
  235. NDIS_STATUS NdisStatus;
  236. PDRIVER_DISPATCH DispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1];
  237. NDIS_STRING DeviceName, LinkName;
  238. SAFEASSERT(CURRENT_IRQL == PASSIVE_LEVEL);
  239. NdisInitializeReadWriteLock( &gBridgeStateLock );
  240. BrdgInitializeWaitRef( &gMiniPortAdapterRefcount, FALSE );
  241. BrdgInitializeWaitRef( &gMiniPortConnectedRefcount, TRUE );
  242. BrdgInitializeWaitRef( &gMiniPortToggleRefcount, FALSE );
  243. // Put the miniport refcount into shutdown mode (so a refcount can't be acquired)
  244. // since we don't have a miniport yet
  245. BrdgShutdownWaitRefOnce( &gMiniPortAdapterRefcount );
  246. // We start out disconnected so shutdown the media-connect waitref too.
  247. BrdgShutdownWaitRefOnce( &gMiniPortConnectedRefcount );
  248. NdisInitUnicodeString( &DeviceName, DEVICE_NAME );
  249. NdisInitUnicodeString( &LinkName, SYMBOLIC_NAME );
  250. // Must first tell NDIS we're a miniport driver and initializing
  251. NdisMInitializeWrapper( &gNDISWrapperHandle, gDriverObject, &gRegistryPath, NULL );
  252. // Fill in the description of our miniport
  253. NdisZeroMemory(&MiniPortChars, sizeof(MiniPortChars));
  254. MiniPortChars.MajorNdisVersion = 5;
  255. MiniPortChars.MinorNdisVersion = 0;
  256. MiniPortChars.HaltHandler = BrdgMiniHalt;
  257. MiniPortChars.InitializeHandler = BrdgMiniInitialize;
  258. MiniPortChars.QueryInformationHandler = BrdgMiniQueryInfo;
  259. MiniPortChars.ResetHandler = BrdgMiniReset;
  260. MiniPortChars.SendPacketsHandler = BrdgMiniSendPackets;
  261. MiniPortChars.SetInformationHandler = BrdgMiniSetInfo;
  262. //
  263. // Wire the ReturnPacketHandler straight into the forwarding engine
  264. //
  265. MiniPortChars.ReturnPacketHandler = BrdgFwdReturnIndicatedPacket;
  266. // Create a virtual NIC
  267. NdisStatus = NdisIMRegisterLayeredMiniport( gNDISWrapperHandle, &MiniPortChars, sizeof(MiniPortChars),
  268. &gMiniPortDriverHandle );
  269. if (NdisStatus != NDIS_STATUS_SUCCESS)
  270. {
  271. NdisWriteEventLogEntry( gDriverObject, EVENT_BRIDGE_MINIPORT_REGISTER_FAILED, 0, 0, NULL,
  272. sizeof(NDIS_STATUS), &NdisStatus );
  273. DBGPRINT(MINI, ("Failed to create an NDIS virtual NIC: %08x\n", NdisStatus));
  274. NdisTerminateWrapper( gNDISWrapperHandle, NULL );
  275. return NdisStatus;
  276. }
  277. //
  278. // Initialize Dispatch Table array before setting selected members
  279. //
  280. NdisZeroMemory( DispatchTable, sizeof( DispatchTable ) );
  281. //
  282. // Register a device object and symbolic link so user-mode code can talk to us
  283. //
  284. DispatchTable[IRP_MJ_CREATE] = BrdgDispatchRequest;
  285. DispatchTable[IRP_MJ_CLEANUP] = BrdgDispatchRequest;
  286. DispatchTable[IRP_MJ_CLOSE] = BrdgDispatchRequest;
  287. DispatchTable[IRP_MJ_DEVICE_CONTROL] = BrdgDispatchRequest;
  288. NdisStatus = NdisMRegisterDevice( gNDISWrapperHandle, &DeviceName, &LinkName, DispatchTable,
  289. &gDeviceObject, &gDeviceHandle );
  290. if( NdisStatus != NDIS_STATUS_SUCCESS )
  291. {
  292. NdisWriteEventLogEntry( gDriverObject, EVENT_BRIDGE_DEVICE_CREATION_FAILED, 0, 0, NULL,
  293. sizeof(NDIS_STATUS), &NdisStatus );
  294. DBGPRINT(MINI, ("Failed to create a device object and sym link: %08x\n", NdisStatus));
  295. NdisIMDeregisterLayeredMiniport( gMiniPortDriverHandle );
  296. NdisTerminateWrapper( gNDISWrapperHandle, NULL );
  297. return NdisStatus;
  298. }
  299. // Register the unload function
  300. NdisMRegisterUnloadHandler(gNDISWrapperHandle, BrdgUnload);
  301. return STATUS_SUCCESS;
  302. }
  303. VOID
  304. BrdgMiniCleanup()
  305. /*++
  306. Routine Description:
  307. Unload-time orderly shutdown function
  308. This function is guaranteed to be called exactly once
  309. Must run at PASSIVE_LEVEL since we call NdisIMDeInitializeDeviceInstance
  310. Arguments:
  311. None
  312. Return Value:
  313. None
  314. --*/
  315. {
  316. NDIS_STATUS NdisStatus;
  317. SAFEASSERT(CURRENT_IRQL == PASSIVE_LEVEL);
  318. DBGPRINT(MINI, ("BrdgMiniCleanup\n"));
  319. if( gMiniPortAdapterHandle != NULL )
  320. {
  321. SAFEASSERT( gNDISWrapperHandle != NULL );
  322. // This should cause a call to BrdgMiniHalt where gMiniPortAdapterHandle
  323. // is NULLed out
  324. NdisStatus = NdisIMDeInitializeDeviceInstance( gMiniPortAdapterHandle );
  325. SAFEASSERT( NdisStatus == NDIS_STATUS_SUCCESS );
  326. }
  327. else
  328. {
  329. //
  330. // Tear down our device object. This is normally done when the miniport
  331. // shuts down, but in scenarios where the miniport was never created,
  332. // the device object still exists at this point.
  333. //
  334. NDIS_HANDLE Scratch = gDeviceHandle;
  335. if( Scratch != NULL )
  336. {
  337. // Tear down the device object
  338. gDeviceHandle = gDeviceObject = NULL;
  339. NdisMDeregisterDevice( Scratch );
  340. }
  341. }
  342. // Unregister ourselves as an intermediate driver
  343. NdisIMDeregisterLayeredMiniport( gMiniPortDriverHandle );
  344. }
  345. BOOLEAN
  346. BrdgMiniIsBridgeDeviceName(
  347. IN PNDIS_STRING pDeviceName
  348. )
  349. /*++
  350. Routine Description:
  351. Compares a device name to the current device name of the bridge miniport.
  352. This actually requires that we allocate memory, so it should be called sparingly.
  353. Arguments:
  354. pDeviceName The name of a device
  355. Return Value:
  356. TRUE if the names match (case is ignored), FALSE otherwise.
  357. --*/
  358. {
  359. LOCK_STATE LockState;
  360. BOOLEAN rc = FALSE;
  361. NDIS_STATUS Status;
  362. ULONG BridgeNameCopySize = 0L;
  363. PWCHAR pBridgeNameCopy = NULL;
  364. // The bridge device name must be read inside the gBridgeStateLock
  365. NdisAcquireReadWriteLock( &gBridgeStateLock, FALSE/*Read access*/, &LockState );
  366. if( gBridgeDeviceName != NULL )
  367. {
  368. if( gBridgeDeviceNameSize > 0 )
  369. {
  370. // Alloc memory for the copy of the name
  371. Status = NdisAllocateMemoryWithTag( &pBridgeNameCopy, gBridgeDeviceNameSize, 'gdrB' );
  372. if( Status == NDIS_STATUS_SUCCESS )
  373. {
  374. // Copy the name
  375. NdisMoveMemory( pBridgeNameCopy, gBridgeDeviceName, gBridgeDeviceNameSize );
  376. BridgeNameCopySize = gBridgeDeviceNameSize;
  377. }
  378. else
  379. {
  380. SAFEASSERT( pBridgeNameCopy == NULL );
  381. }
  382. }
  383. else
  384. {
  385. SAFEASSERT( FALSE );
  386. }
  387. }
  388. NdisReleaseReadWriteLock( &gBridgeStateLock, &LockState );
  389. if( pBridgeNameCopy != NULL )
  390. {
  391. NDIS_STRING NdisStr;
  392. NdisInitUnicodeString( &NdisStr, pBridgeNameCopy );
  393. if( NdisEqualString( &NdisStr, pDeviceName, TRUE/*Ignore case*/ ) )
  394. {
  395. rc = TRUE;
  396. }
  397. NdisFreeMemory( pBridgeNameCopy, BridgeNameCopySize, 0 );
  398. }
  399. return rc;
  400. }
  401. VOID
  402. BrdgMiniInstantiateMiniport()
  403. /*++
  404. Routine Description:
  405. Instantiates the virtual NIC we expose to overlying protocols.
  406. At least one adapter must be in the global adapter list, since we build
  407. our MAC address with the MAC address of the first bound adapter.
  408. Must run at < DISPATCH_LEVEL since we call NdisIMInitializeDeviceInstanceEx
  409. Arguments:
  410. None
  411. Return Value:
  412. None
  413. --*/
  414. {
  415. NDIS_STATUS Status;
  416. NTSTATUS NtStatus;
  417. NDIS_STRING NdisString;
  418. LOCK_STATE LockState;
  419. PWCHAR pDeviceName;
  420. ULONG DeviceNameSize;
  421. SAFEASSERT(CURRENT_IRQL < DISPATCH_LEVEL);
  422. DBGPRINT(MINI, ("About to instantiate the miniport...\n"));
  423. //
  424. // Retrieve our device name from the registry
  425. // (it is written there by our notify object during install)
  426. //
  427. NtStatus = BrdgReadRegUnicode( &gRegistryPath, gDeviceNameEntry, &pDeviceName, &DeviceNameSize );
  428. if( NtStatus != STATUS_SUCCESS )
  429. {
  430. NdisWriteEventLogEntry( gDriverObject, EVENT_BRIDGE_MINIPROT_DEVNAME_MISSING, 0, 0, NULL,
  431. sizeof(NTSTATUS), &NtStatus );
  432. DBGPRINT(MINI, ("Failed to retrieve the miniport's device name: %08x\n", NtStatus));
  433. return;
  434. }
  435. SAFEASSERT( pDeviceName != NULL );
  436. DBGPRINT(MINI, ("Initializing miniport with device name %ws\n", pDeviceName));
  437. NdisAcquireReadWriteLock( &gBridgeStateLock, TRUE/*Write access*/, &LockState );
  438. if( ! gHaveAddress )
  439. {
  440. // We don't have a MAC address yet. This is fatal.
  441. NdisReleaseReadWriteLock( &gBridgeStateLock, &LockState );
  442. NdisWriteEventLogEntry( gDriverObject, EVENT_BRIDGE_NO_BRIDGE_MAC_ADDR, 0L, 0L, NULL,
  443. sizeof(NDIS_STATUS), &Status );
  444. DBGPRINT(MINI, ("Failed to determine a MAC address: %08x\n", Status));
  445. NdisFreeMemory( pDeviceName, DeviceNameSize, 0 );
  446. return;
  447. }
  448. //
  449. // Save the device name in our global for use until we reinitialize.
  450. // Must do this before calling NdisIMInitializeDeviceInstanceEx, since NDIS calls
  451. // BrdgProtBindAdapter in the context of our call to NdisIMInitializeDeviceInstanceEx
  452. // and we want to consult the bridge's device name when binding
  453. //
  454. if( gBridgeDeviceName != NULL )
  455. {
  456. // Free the old name
  457. NdisFreeMemory( gBridgeDeviceName, gBridgeDeviceNameSize, 0 );
  458. }
  459. gBridgeDeviceName = pDeviceName;
  460. gBridgeDeviceNameSize = DeviceNameSize;
  461. NdisReleaseReadWriteLock( &gBridgeStateLock, &LockState );
  462. // Go ahead and intantiate the miniport.
  463. NdisInitUnicodeString( &NdisString, pDeviceName );
  464. Status = NdisIMInitializeDeviceInstanceEx(gMiniPortDriverHandle, &NdisString, NULL);
  465. if( Status != NDIS_STATUS_SUCCESS )
  466. {
  467. // Log this error since it means we can't create the miniport
  468. NdisWriteEventLogEntry( gDriverObject, EVENT_BRIDGE_MINIPORT_INIT_FAILED, 0L, 0L, NULL,
  469. sizeof(NDIS_STATUS), &Status );
  470. DBGPRINT(MINI, ("NdisIMInitializeDeviceInstanceEx failed: %08x\n", Status));
  471. // Destroy the stored device name for the miniport
  472. NdisAcquireReadWriteLock( &gBridgeStateLock, TRUE/*Write access*/, &LockState );
  473. if( gBridgeDeviceName != NULL )
  474. {
  475. // Free the old name
  476. NdisFreeMemory( gBridgeDeviceName, gBridgeDeviceNameSize, 0 );
  477. }
  478. gBridgeDeviceName = NULL;
  479. gBridgeDeviceNameSize = 0L;
  480. NdisReleaseReadWriteLock( &gBridgeStateLock, &LockState );
  481. }
  482. }
  483. BOOLEAN
  484. BrdgMiniShouldIndicatePacket(
  485. IN PUCHAR pTargetAddr
  486. )
  487. /*++
  488. Routine Description:
  489. Determines whether an inbound packet should be indicated to overlying protocols through
  490. our virtual NIC
  491. Arguments:
  492. pTargetAddr The target MAC address of a packet
  493. Return Value:
  494. TRUE : The packet should be indicated
  495. FALSE : The packet should not be indicated
  496. --*/
  497. {
  498. BOOLEAN bIsBroadcast, bIsMulticast, bIsLocalUnicast, rc = FALSE;
  499. LOCK_STATE LockState;
  500. if( gMiniPortAdapterHandle == NULL )
  501. {
  502. // Yikes! The miniport isn't set up yet. Definitely don't indicate!
  503. return FALSE;
  504. }
  505. bIsBroadcast = ETH_IS_BROADCAST(pTargetAddr);
  506. bIsMulticast = ETH_IS_MULTICAST(pTargetAddr);
  507. bIsLocalUnicast = BrdgMiniIsUnicastToBridge(pTargetAddr);
  508. // Get read access to the packet filter
  509. NdisAcquireReadWriteLock( &gBridgeStateLock, FALSE /*Read-only*/, &LockState );
  510. do
  511. {
  512. // Promiscuous / ALL_LOCAL means indicate everything
  513. if( (gPacketFilter & (NDIS_PACKET_TYPE_PROMISCUOUS | NDIS_PACKET_TYPE_ALL_LOCAL)) != 0 )
  514. {
  515. rc = TRUE;
  516. break;
  517. }
  518. if( ((gPacketFilter & NDIS_PACKET_TYPE_BROADCAST) != 0) && bIsBroadcast )
  519. {
  520. rc = TRUE;
  521. break;
  522. }
  523. if( ((gPacketFilter & NDIS_PACKET_TYPE_DIRECTED) != 0) && bIsLocalUnicast )
  524. {
  525. rc = TRUE;
  526. break;
  527. }
  528. if( bIsMulticast )
  529. {
  530. if( (gPacketFilter & NDIS_PACKET_TYPE_ALL_MULTICAST) != 0 )
  531. {
  532. rc = TRUE;
  533. break;
  534. }
  535. else if( (gPacketFilter & NDIS_PACKET_TYPE_MULTICAST) != 0 )
  536. {
  537. rc = BrdgMiniAddrIsInMultiList( pTargetAddr );
  538. }
  539. }
  540. }
  541. while (FALSE);
  542. NdisReleaseReadWriteLock( &gBridgeStateLock, &LockState );
  543. return rc;
  544. }
  545. BOOLEAN
  546. BrdgMiniIsUnicastToBridge (
  547. IN PUCHAR Address
  548. )
  549. /*++
  550. Routine Description:
  551. Determines whether a given packet is a directed packet unicast straight to
  552. the bridge's host machine
  553. Arguments:
  554. Address The target MAC address of a packet
  555. Return Value:
  556. TRUE : This is a directed packet destined for the local machine
  557. FALSE : The above is not true
  558. --*/
  559. {
  560. UINT Result;
  561. if( gHaveAddress )
  562. {
  563. // Not necessary to acquire a lock to read gBridgeAddress since it cannot
  564. // change once it is set.
  565. ETH_COMPARE_NETWORK_ADDRESSES_EQ( Address, gBridgeAddress, &Result );
  566. }
  567. else
  568. {
  569. // We have no MAC address, so this can't be addressed to us!
  570. Result = 1; // Inequality
  571. }
  572. return (BOOLEAN)(Result == 0); // Zero is equality
  573. }
  574. VOID
  575. BrdgMiniAssociate()
  576. /*++
  577. Routine Description:
  578. Associates our miniport with our protocol
  579. Must run at PASSIVE_LEVEL
  580. Arguments:
  581. None
  582. Return Value:
  583. None
  584. --*/
  585. {
  586. SAFEASSERT(CURRENT_IRQL == PASSIVE_LEVEL);
  587. // Associate ourselves with the protocol section in NDIS's tortured mind
  588. NdisIMAssociateMiniport( gMiniPortDriverHandle, gProtHandle );
  589. }
  590. VOID
  591. BrdgMiniDeferredMediaDisconnect(
  592. IN PVOID arg
  593. )
  594. /*++
  595. Routine Description:
  596. Signals a media-disconnect to NDIS
  597. Must run at PASSIVE IRQL, since we have to wait for all packet indications
  598. to complete before indicating media-disconnect.
  599. Arguments:
  600. arg The bridge miniport handle (must be released)
  601. Return Value:
  602. None
  603. --*/
  604. {
  605. NDIS_HANDLE MiniportHandle = (NDIS_HANDLE)arg;
  606. if( BrdgShutdownBlockedWaitRef(&gMiniPortConnectedRefcount) )
  607. {
  608. // Nobody can indicate packets anymore.
  609. LOCK_STATE LockState;
  610. //
  611. // Close a timing window: we may have just gone media-connect but our high-IRQL
  612. // processing may not yet have reset the wait-refcount. Serialize here so it's
  613. // impossible for us to signal a disconnect to NDIS after we have actually
  614. // gone media-connect.
  615. //
  616. // This RELIES on high-IRQL processing acquiring gBridgeStateLock to set
  617. // gBridgeMediaState to NdisMediaStateConnected BEFORE signalling the
  618. // media-connected state to NDIS.
  619. //
  620. NdisAcquireReadWriteLock( &gBridgeStateLock, FALSE /*Read access*/, &LockState );
  621. if( gBridgeMediaState == NdisMediaStateDisconnected )
  622. {
  623. DBGPRINT(MINI, ("Signalled media-disconnect from deferred function\n"));
  624. NdisMIndicateStatus( MiniportHandle, NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0L );
  625. }
  626. else
  627. {
  628. DBGPRINT(MINI, ("Aborted deferred media-disconnect: media state inconsistent\n"));
  629. }
  630. NdisReleaseReadWriteLock( &gBridgeStateLock, &LockState );
  631. }
  632. else
  633. {
  634. // Someone set us back to the connected state before we got executed
  635. DBGPRINT(MINI, ("Aborted deferred media-disconnect: wait-ref reset\n"));
  636. }
  637. BrdgMiniReleaseMiniport();
  638. }
  639. VOID
  640. BrdgMiniDeferredMediaToggle(
  641. IN PVOID arg
  642. )
  643. /*++
  644. Routine Description:
  645. Signals a media-disconnect to NDIS followed quickly by a media-connect. Used
  646. to indicate to upper-layer protocols like TCPIP that the bridge may have
  647. disconnected from a network segment it could previously reach, or that we may
  648. now be able to reach a network segment that we couldn't before.
  649. Must run at PASSIVE IRQL, since we have to wait for all packet indications
  650. to complete before indicating media-disconnect.
  651. Arguments:
  652. arg The bridge miniport handle (must be released)
  653. Return Value:
  654. None
  655. --*/
  656. {
  657. NDIS_HANDLE MiniportHandle = (NDIS_HANDLE)arg;
  658. // We need a guarantee that the miniport is media-connect to be able to do
  659. // the toggle properly.
  660. if( BrdgIncrementWaitRef(&gMiniPortConnectedRefcount) )
  661. {
  662. // Stop people from indicating packets
  663. if( BrdgShutdownWaitRef(&gMiniPortToggleRefcount) )
  664. {
  665. DBGPRINT(MINI, ("Doing deferred media toggle\n"));
  666. // Toggle our media state with NDIS
  667. NdisMIndicateStatus( MiniportHandle, NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0L );
  668. NdisMIndicateStatus( MiniportHandle, NDIS_STATUS_MEDIA_CONNECT, NULL, 0L );
  669. // Allow people to indicate packets again
  670. BrdgResetWaitRef( &gMiniPortToggleRefcount );
  671. }
  672. else
  673. {
  674. DBGPRINT(MINI, ("Multiple toggles in progress simultaneously\n"));
  675. }
  676. BrdgDecrementWaitRef( &gMiniPortConnectedRefcount );
  677. }
  678. // else the miniport isn't media-connect, so the toggle makes no sense.
  679. BrdgMiniReleaseMiniport();
  680. }
  681. VOID
  682. BrdgMiniUpdateCharacteristics(
  683. IN BOOLEAN bConnectivityChange
  684. )
  685. /*++
  686. Routine Description:
  687. Recalculates the link speed and media status (connected / disconnected) that
  688. our virtual NIC exposes to overlying protocols
  689. Arguments:
  690. bConnectivityChange Whether the change that prompted this call is a change
  691. in connectivity (i.e., we acquired or lost an adapter).
  692. Return Value:
  693. None
  694. --*/
  695. {
  696. LOCK_STATE LockState, ListLockState, AdaptersLockState;
  697. PADAPT pAdapt;
  698. ULONG MediaState = NdisMediaStateDisconnected;
  699. ULONG FastestSpeed = 0L;
  700. BOOLEAN UpdateSpeed = FALSE, UpdateMediaState = FALSE;
  701. NDIS_HANDLE MiniportHandle;
  702. // Need to read the adapter list and also have the adapters' characteristics not change
  703. NdisAcquireReadWriteLock( &gAdapterListLock, FALSE /*Read-only*/, &ListLockState );
  704. NdisAcquireReadWriteLock( &gAdapterCharacteristicsLock, FALSE /*Read-only*/, &AdaptersLockState );
  705. pAdapt = gAdapterList;
  706. while( pAdapt != NULL )
  707. {
  708. // An adapter must be connected and actively handling packets to change our
  709. // virtual media state.
  710. if( (pAdapt->MediaState == NdisMediaStateConnected) && (pAdapt->State == Forwarding) )
  711. {
  712. // We're connected if at least one NIC is connected
  713. MediaState = NdisMediaStateConnected;
  714. // The NIC must be connected for us to consider its speed
  715. if( pAdapt->LinkSpeed > FastestSpeed )
  716. {
  717. FastestSpeed = pAdapt->LinkSpeed;
  718. }
  719. }
  720. pAdapt = pAdapt->Next;
  721. }
  722. NdisReleaseReadWriteLock( &gAdapterCharacteristicsLock, &AdaptersLockState );
  723. NdisReleaseReadWriteLock( &gAdapterListLock, &ListLockState );
  724. // Update the characteristics
  725. NdisAcquireReadWriteLock( &gBridgeStateLock, TRUE /*Write access*/, &LockState );
  726. //
  727. // Only update our virtual link speed if we actually got at least one real speed
  728. // from our NICs. If everything is disconnected, the resulting FastestSpeed is
  729. // zero. In this case, we don't want to actually report a zero speed up to
  730. // overlying protocols; we stick at the last known speed until someone reconnects.
  731. //
  732. if( (gBridgeLinkSpeed != FastestSpeed) && (FastestSpeed != 0L) )
  733. {
  734. UpdateSpeed = TRUE;
  735. gBridgeLinkSpeed = FastestSpeed;
  736. DBGPRINT(MINI, ("Updated bridge speed to %iMbps\n", FastestSpeed / 10000));
  737. }
  738. if( gBridgeMediaState != MediaState )
  739. {
  740. UpdateMediaState = TRUE;
  741. gBridgeMediaState = MediaState;
  742. if( MediaState == NdisMediaStateConnected )
  743. {
  744. DBGPRINT(MINI, ("CONNECT\n"));
  745. }
  746. else
  747. {
  748. DBGPRINT(MINI, ("DISCONNECT\n"));
  749. }
  750. }
  751. NdisReleaseReadWriteLock( &gBridgeStateLock, &LockState );
  752. MiniportHandle = BrdgMiniAcquireMiniport();
  753. if( MiniportHandle != NULL )
  754. {
  755. if( UpdateMediaState )
  756. {
  757. // Our link state has changed.
  758. if( MediaState == NdisMediaStateConnected )
  759. {
  760. //
  761. // Tell NDIS we will be indicating packets again.
  762. //
  763. // NOTE: BrdgMiniDeferredMediaDisconnect RELIES on us doing this after
  764. // having updated gBridgeMediaState inside gBridgeStateLock so it can
  765. // close the timing window between this call and the BrdgResetWaitRef() call.
  766. //
  767. NdisMIndicateStatus( MiniportHandle, NDIS_STATUS_MEDIA_CONNECT, NULL, 0L );
  768. // Re-enable packet indication.
  769. BrdgResetWaitRef( &gMiniPortConnectedRefcount );
  770. }
  771. else
  772. {
  773. SAFEASSERT( MediaState == NdisMediaStateDisconnected );
  774. // Stop people from indicating packets
  775. BrdgBlockWaitRef( &gMiniPortConnectedRefcount );
  776. // We hand MiniportHandle to our deferred function
  777. BrdgMiniReAcquireMiniport();
  778. // Have to do the media-disconnect indication at PASSIVE level, since we must
  779. // first wait for everyone to finish indicating packets.
  780. if( BrdgDeferFunction( BrdgMiniDeferredMediaDisconnect, MiniportHandle ) != NDIS_STATUS_SUCCESS )
  781. {
  782. // Failed to defer the function. Avoid leaking a refcount
  783. BrdgMiniReleaseMiniport();
  784. }
  785. }
  786. }
  787. else if( bConnectivityChange )
  788. {
  789. //
  790. // There was no actual change to our media state. However, if the change that prompted this call
  791. // is a connectivity change and our media state is currently CONNECTED, we toggle it to
  792. // DISCONNECTED and back again to "hint" to upper-layer protocols like IP that the underlying
  793. // network may have changed. For example, in IP's case, a DHCP server may have become visible
  794. // (or a previously visible server may have disappeared) because of a connectivity change.
  795. // The hint causes IP to look for a DHCP server afresh.
  796. //
  797. if( MediaState == NdisMediaStateConnected )
  798. {
  799. // We hand MiniportHandle to our deferred function
  800. BrdgMiniReAcquireMiniport();
  801. // Toggle has to be done at PASSIVE level.
  802. if( BrdgDeferFunction( BrdgMiniDeferredMediaToggle, MiniportHandle ) != NDIS_STATUS_SUCCESS )
  803. {
  804. // Failed to defer the function. Avoid leaking a refcount
  805. BrdgMiniReleaseMiniport();
  806. }
  807. }
  808. }
  809. if( UpdateSpeed )
  810. {
  811. // Tell overlying protocols that our speed has changed
  812. NdisMIndicateStatus( MiniportHandle, NDIS_STATUS_LINK_SPEED_CHANGE, &FastestSpeed, sizeof(ULONG) );
  813. }
  814. BrdgMiniReleaseMiniport();
  815. }
  816. }
  817. NDIS_HANDLE
  818. BrdgMiniAcquireMiniportForIndicate()
  819. /*++
  820. Routine Description:
  821. Acquires the bridge miniport handle for the purpose of indicating packets.
  822. In addition to guaranteeing that the miniport will exist until the caller calls
  823. BrdgMiniReleaseMiniportForIndicate(), the caller is also allowed to indicate
  824. packets using the returned miniport handle until the miniport is released.
  825. Arguments:
  826. None
  827. Return Value:
  828. The NDIS handle for the virtual NIC. This can be used to indicate packets
  829. until a reciprocal call to BrdgMiniReleaseMiniportForIndicate().
  830. --*/
  831. {
  832. if( BrdgIncrementWaitRef(&gMiniPortAdapterRefcount) )
  833. {
  834. SAFEASSERT( gMiniPortAdapterHandle != NULL );
  835. // The miniport needs to be media-connect to indicate packets.
  836. if( BrdgIncrementWaitRef(&gMiniPortConnectedRefcount) )
  837. {
  838. // A media-state toggle had better not be in progress
  839. if( BrdgIncrementWaitRef(&gMiniPortToggleRefcount) )
  840. {
  841. // Caller can use the miniport
  842. return gMiniPortAdapterHandle;
  843. }
  844. // else miniport exists but is toggling its state
  845. BrdgDecrementWaitRef( &gMiniPortConnectedRefcount );
  846. }
  847. // else miniport exists but is media-disconnected
  848. BrdgDecrementWaitRef( &gMiniPortAdapterRefcount );
  849. }
  850. // else miniport does not exist.
  851. return NULL;
  852. }
  853. NDIS_HANDLE
  854. BrdgMiniAcquireMiniport()
  855. /*++
  856. Routine Description:
  857. Increments the miniport's refcount so it cannot be torn down until a corresponding
  858. BrdgMiniReleaseMiniport() call is made.
  859. The caller may NOT use the returned miniport handle to indicate packets, since the
  860. miniport is not guaranteed to be in an appropriate state.
  861. Arguments:
  862. None
  863. Return Value:
  864. The NDIS handle for the virtual NIC. This can be used safely until a reciprocal call
  865. to BrdgMiniReleaseMiniport().
  866. --*/
  867. {
  868. if( gMiniPortAdapterHandle && BrdgIncrementWaitRef(&gMiniPortAdapterRefcount) )
  869. {
  870. return gMiniPortAdapterHandle;
  871. }
  872. // else miniport does not exist.
  873. return NULL;
  874. }
  875. VOID
  876. BrdgMiniReAcquireMiniport()
  877. /*++
  878. Routine Description:
  879. Reacquires the miniport (caller must have previously called BrdgMiniAcquireMiniport()
  880. and not yet called BrdgMiniReleaseMiniport().
  881. Arguments:
  882. None
  883. Return Value:
  884. None. The caller should already be holding a handle for the miniport.
  885. --*/
  886. {
  887. BrdgReincrementWaitRef(&gMiniPortAdapterRefcount);
  888. }
  889. VOID
  890. BrdgMiniReleaseMiniport()
  891. /*++
  892. Routine Description:
  893. Decrements the miniport's refcount. The caller should no longer use the handle
  894. previously returned by BrdgMiniAcquireMiniport().
  895. Arguments:
  896. None
  897. Return Value:
  898. None
  899. --*/
  900. {
  901. BrdgDecrementWaitRef( &gMiniPortAdapterRefcount );
  902. }
  903. VOID
  904. BrdgMiniReleaseMiniportForIndicate()
  905. /*++
  906. Routine Description:
  907. Decrements the miniport's refcount. The caller should no longer use the handle
  908. previously returned by BrdgMiniAcquireMiniportForIndicate().
  909. Arguments:
  910. None
  911. Return Value:
  912. None
  913. --*/
  914. {
  915. BrdgDecrementWaitRef( &gMiniPortToggleRefcount );
  916. BrdgDecrementWaitRef( &gMiniPortConnectedRefcount );
  917. BrdgDecrementWaitRef( &gMiniPortAdapterRefcount );
  918. }
  919. BOOLEAN
  920. BrdgMiniReadMACAddress(
  921. OUT PUCHAR pAddr
  922. )
  923. /*++
  924. Routine Description:
  925. Reads the bridge miniport's MAC address.
  926. Arguments:
  927. Address of a buffer to receive the address
  928. Return Value:
  929. TRUE if the value was copied out successfully
  930. FALSE if we don't yet have a MAC address (nothing was copied)
  931. --*/
  932. {
  933. BOOLEAN rc;
  934. if( gHaveAddress )
  935. {
  936. // Not necessary to acquire a lock to read the address since
  937. // it cannot change once it is set
  938. ETH_COPY_NETWORK_ADDRESS( pAddr, gBridgeAddress );
  939. rc = TRUE;
  940. }
  941. else
  942. {
  943. rc = FALSE;
  944. }
  945. return rc;
  946. }
  947. // ===========================================================================
  948. //
  949. // PRIVATE FUNCTIONS
  950. //
  951. // ===========================================================================
  952. VOID
  953. BrdgMiniInitFromAdapter(
  954. IN PADAPT pAdapt
  955. )
  956. /*++
  957. Routine Description:
  958. Called by the protocol section to give us a chance to establish the bridge's
  959. MAC address when a new adapter arrives. If we succeed in determining a MAC
  960. address from the given adapter, we in turn call the STA module to tell it
  961. our MAC address, which it needs as early as possible.
  962. The MAC address of the bridge is set as the MAC address of the given adapter
  963. with the "locally administered" bit set. This should (hopefully) make the
  964. address unique in the local network as well as unique within our machine.
  965. This function is called for every new adapter but we only need to initialize
  966. once.
  967. Arguments:
  968. pAdapt An adapter to use to initialize
  969. Return Value:
  970. Status of the operation
  971. --*/
  972. {
  973. if( ! gHaveAddress )
  974. {
  975. LOCK_STATE LockState;
  976. NdisAcquireReadWriteLock( &gBridgeStateLock, TRUE/*Write access*/, &LockState );
  977. // Possible for the gHaveAddress flag to have changed before acquiring the lock
  978. if( ! gHaveAddress )
  979. {
  980. // Copy out the NIC's MAC address
  981. ETH_COPY_NETWORK_ADDRESS( gBridgeAddress, pAdapt->MACAddr );
  982. //
  983. // Set the second-least significant bit of the NIC's MAC address. This moves the address
  984. // into the locally administered space.
  985. //
  986. gBridgeAddress[0] |= (UCHAR)0x02;
  987. DBGPRINT(MINI, ("Using MAC Address %02x-%02x-%02x-%02x-%02x-%02x\n",
  988. (UINT)gBridgeAddress[0], (UINT)gBridgeAddress[1], (UINT)gBridgeAddress[2],
  989. (UINT)gBridgeAddress[3], (UINT)gBridgeAddress[4], (UINT)gBridgeAddress[5]));
  990. gHaveAddress = TRUE;
  991. NdisReleaseReadWriteLock( &gBridgeStateLock, &LockState );
  992. if( !gDisableSTA )
  993. {
  994. // We are responsible for calling the STA module to complete its initialization once
  995. // we know our MAC address.
  996. BrdgSTADeferredInit( gBridgeAddress );
  997. }
  998. // We are also responsible for letting the compatibility-mode code know about our
  999. // MAC address once it is set.
  1000. BrdgCompNotifyMACAddress( gBridgeAddress );
  1001. }
  1002. else
  1003. {
  1004. NdisReleaseReadWriteLock( &gBridgeStateLock, &LockState );
  1005. }
  1006. }
  1007. }
  1008. BOOLEAN
  1009. BrdgMiniAddrIsInMultiList(
  1010. IN PUCHAR pTargetAddr
  1011. )
  1012. /*++
  1013. Routine Description:
  1014. Determines whether a given multicast address is in the list of addresses that
  1015. we must indicate to overlying protocols
  1016. The caller is responsible for synchronization; it must have AT LEAST a read lock on
  1017. gBridgeStateLock.
  1018. Arguments:
  1019. pTargetAddr The address to analyze
  1020. Return Value:
  1021. TRUE : This address is a multicast address that we have been asked
  1022. to indicate
  1023. FALSE : The above is not true
  1024. --*/
  1025. {
  1026. PUCHAR pCurAddr = gMulticastList;
  1027. ULONG i;
  1028. BOOLEAN rc = FALSE;
  1029. // The list must have an integral number of addresses!
  1030. SAFEASSERT( (gMulticastListLength % ETH_LENGTH_OF_ADDRESS) == 0 );
  1031. for( i = 0;
  1032. i < (gMulticastListLength / ETH_LENGTH_OF_ADDRESS);
  1033. i++, pCurAddr += ETH_LENGTH_OF_ADDRESS
  1034. )
  1035. {
  1036. UINT Result;
  1037. ETH_COMPARE_NETWORK_ADDRESSES_EQ( pTargetAddr, pCurAddr, &Result );
  1038. if( Result == 0 )
  1039. {
  1040. rc = TRUE;
  1041. break;
  1042. }
  1043. }
  1044. return rc;
  1045. }
  1046. VOID
  1047. BrdgMiniHalt(
  1048. IN NDIS_HANDLE MiniportAdapterContext
  1049. )
  1050. /*++
  1051. Routine Description:
  1052. Called when the virtual NIC is de-instantiated. We NULL out the miniport handle and
  1053. stall the tear-down until everyone is done using the miniport.
  1054. Must be called at PASSIVE_LEVEL since we wait on an event
  1055. Arguments:
  1056. MiniportAdapterContext Ignored
  1057. Return Value:
  1058. None
  1059. --*/
  1060. {
  1061. NDIS_HANDLE Scratch = gDeviceHandle;
  1062. LOCK_STATE LockState;
  1063. SAFEASSERT(CURRENT_IRQL == PASSIVE_LEVEL);
  1064. DBGPRINT(MINI, ("BrdgMiniHalt\n"));
  1065. if( Scratch != NULL )
  1066. {
  1067. // Tear down the device object
  1068. gDeviceHandle = gDeviceObject = NULL;
  1069. NdisMDeregisterDevice( Scratch );
  1070. }
  1071. if( gMiniPortAdapterHandle != NULL )
  1072. {
  1073. // Stall before returning until everyone is done using the miniport handle.
  1074. // This also prevents people from acquiring the miniport handle.
  1075. BrdgShutdownWaitRefOnce( &gMiniPortAdapterRefcount );
  1076. gMiniPortAdapterHandle = NULL;
  1077. DBGPRINT(MINI, ("Done stall\n"));
  1078. }
  1079. NdisAcquireReadWriteLock( &gBridgeStateLock, TRUE/*Write access*/, &LockState );
  1080. if( gBridgeDeviceName != NULL )
  1081. {
  1082. NdisFreeMemory( gBridgeDeviceName, gBridgeDeviceNameSize, 0 );
  1083. gBridgeDeviceName = NULL;
  1084. gBridgeDeviceNameSize = 0L;
  1085. }
  1086. // Ditch our packet filter and multicast list
  1087. gPacketFilter = 0L;
  1088. if( gMulticastList != NULL )
  1089. {
  1090. SAFEASSERT( gMulticastListLength > 0L );
  1091. NdisFreeMemory( gMulticastList, gMulticastListLength, 0 );
  1092. gMulticastList = NULL;
  1093. gMulticastListLength = 0L;
  1094. }
  1095. NdisReleaseReadWriteLock( &gBridgeStateLock, &LockState );
  1096. }
  1097. NDIS_STATUS
  1098. BrdgMiniInitialize(
  1099. OUT PNDIS_STATUS OpenErrorStatus,
  1100. OUT PUINT SelectedMediumIndex,
  1101. IN PNDIS_MEDIUM MediumArray,
  1102. IN UINT MediumArraySize,
  1103. IN NDIS_HANDLE MiniPortAdapterHandle,
  1104. IN NDIS_HANDLE WrapperConfigurationContext
  1105. )
  1106. /*++
  1107. Routine Description:
  1108. NDIS entry point called to initialize our virtual NIC following a call to
  1109. NdisIMInitializeDeviceInstance
  1110. Must run at PASSIVE_LEVEL since we call NdisMSetAttributesEx
  1111. Arguments:
  1112. OpenErrorStatus Where to return the specific error code if an open fails
  1113. SelectedMediumIndex Where to specify which media we selected from MediumArray
  1114. MediumArray A list of media types to choose from
  1115. MediumArraySize Number of entries in MediumArray
  1116. MiniPortAdapterHandle The handle for our virtual NIC (we save this)
  1117. WrapperConfigurationContext Not used
  1118. Return Value:
  1119. Status of the initialization. A result != NDIS_STATUS_SUCCESS fails the NIC initialization
  1120. and the miniport is not exposed to upper-layer protocols
  1121. --*/
  1122. {
  1123. UINT i;
  1124. SAFEASSERT(CURRENT_IRQL == PASSIVE_LEVEL);
  1125. DBGPRINT(MINI, ("BrdgMiniInitialize\n"));
  1126. for( i = 0; i < MediumArraySize; i++ )
  1127. {
  1128. if( MediumArray[i] == NdisMedium802_3 ) // Ethernet
  1129. {
  1130. *SelectedMediumIndex = NdisMedium802_3;
  1131. break;
  1132. }
  1133. }
  1134. if( i == MediumArraySize )
  1135. {
  1136. // Log this error since it's fatal
  1137. NdisWriteEventLogEntry( gDriverObject, EVENT_BRIDGE_ETHERNET_NOT_OFFERED, 0L, 0L, NULL, 0L, NULL );
  1138. DBGPRINT(MINI, ("Ethernet not offered; failing\n"));
  1139. return NDIS_STATUS_UNSUPPORTED_MEDIA;
  1140. }
  1141. NdisMSetAttributesEx( MiniPortAdapterHandle,
  1142. NULL,
  1143. 0, // CheckForHangTimeInSeconds
  1144. NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT |
  1145. NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT|
  1146. NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER |
  1147. NDIS_ATTRIBUTE_DESERIALIZE |
  1148. NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND,
  1149. 0);
  1150. // Save the adapter handle for future use
  1151. gMiniPortAdapterHandle = MiniPortAdapterHandle;
  1152. // Allow people to acquire the miniport
  1153. BrdgResetWaitRef( &gMiniPortAdapterRefcount );
  1154. return NDIS_STATUS_SUCCESS;
  1155. }
  1156. NDIS_STATUS
  1157. BrdgMiniReset(
  1158. OUT PBOOLEAN AddressingReset,
  1159. IN NDIS_HANDLE MiniportAdapterContext
  1160. )
  1161. /*++
  1162. Routine Description:
  1163. NDIS entry point called reset our miniport. We do nothing in response to this.
  1164. Arguments:
  1165. AddressingReset Whether NDIS needs to prod us some more by calling MiniportSetInformation
  1166. after we return to restore various pieces of state
  1167. MiniportAdapterContext Ignored
  1168. Return Value:
  1169. Status of the reset
  1170. --*/
  1171. {
  1172. DBGPRINT(MINI, ("BrdgMiniReset\n"));
  1173. return NDIS_STATUS_SUCCESS;
  1174. }
  1175. VOID
  1176. BrdgMiniSendPackets(
  1177. IN NDIS_HANDLE MiniportAdapterContext,
  1178. IN PPNDIS_PACKET PacketArray,
  1179. IN UINT NumberOfPackets
  1180. )
  1181. /*++
  1182. Routine Description:
  1183. NDIS entry point called to send packets through our virtual NIC.
  1184. We just call the forwarding logic code to handle each packet.
  1185. Arguments:
  1186. MiniportAdapterContext Ignored
  1187. PacketArray Array of packet pointers to send
  1188. NumberOfPacket Like it says
  1189. Return Value:
  1190. None
  1191. --*/
  1192. {
  1193. UINT i;
  1194. NDIS_STATUS Status;
  1195. for (i = 0; i < NumberOfPackets; i++)
  1196. {
  1197. PNDIS_PACKET pPacket = PacketArray[i];
  1198. // Hand this packet to the forwarding engine for processing
  1199. Status = BrdgFwdSendPacket( pPacket );
  1200. if( Status != NDIS_STATUS_PENDING )
  1201. {
  1202. // The forwarding engine completed immediately
  1203. // NDIS should prevent the miniport from being shut down
  1204. // until we return from this function
  1205. SAFEASSERT( gMiniPortAdapterHandle != NULL );
  1206. NdisMSendComplete(gMiniPortAdapterHandle, pPacket, Status);
  1207. }
  1208. // else the forwarding engine will call NdisMSendComplete()
  1209. }
  1210. }
  1211. NDIS_STATUS
  1212. BrdgMiniQueryInfo(
  1213. IN NDIS_HANDLE MiniportAdapterContext,
  1214. IN NDIS_OID Oid,
  1215. IN PVOID InformationBuffer,
  1216. IN ULONG InformationBufferLength,
  1217. OUT PULONG BytesWritten,
  1218. OUT PULONG BytesNeeded
  1219. )
  1220. /*++
  1221. Routine Description:
  1222. NDIS entry point called to retrieve various pieces of info from our miniport
  1223. Arguments:
  1224. MiniportAdapterContext Ignored
  1225. Oid The request code
  1226. InformationBuffer Place to return information
  1227. InformationBufferLength Size of InformationBuffer
  1228. BytesWritten Output of the number of written bytes
  1229. BytesNeeded If the provided buffer is too small, this is how many we need.
  1230. Return Value:
  1231. Status of the request
  1232. --*/
  1233. {
  1234. // Macros for use in this function alone
  1235. #define REQUIRE_AT_LEAST(n) \
  1236. { \
  1237. if(InformationBufferLength < (n)) \
  1238. { \
  1239. *BytesNeeded = (n); \
  1240. return NDIS_STATUS_INVALID_LENGTH; \
  1241. }\
  1242. }
  1243. #define RETURN_BYTES(p,n) \
  1244. { \
  1245. NdisMoveMemory( InformationBuffer, (p), (n) ); \
  1246. *BytesWritten = (n); \
  1247. return NDIS_STATUS_SUCCESS; \
  1248. }
  1249. switch( Oid )
  1250. {
  1251. // General characteristics
  1252. case OID_GEN_SUPPORTED_LIST:
  1253. {
  1254. REQUIRE_AT_LEAST( sizeof(gSupportedOIDs) );
  1255. RETURN_BYTES( gSupportedOIDs, sizeof(gSupportedOIDs));
  1256. }
  1257. break;
  1258. case OID_GEN_HARDWARE_STATUS:
  1259. {
  1260. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1261. *((ULONG*)InformationBuffer) = NdisHardwareStatusReady;
  1262. *BytesWritten = sizeof(ULONG);
  1263. return NDIS_STATUS_SUCCESS;
  1264. }
  1265. break;
  1266. case OID_GEN_MEDIA_SUPPORTED:
  1267. case OID_GEN_MEDIA_IN_USE:
  1268. {
  1269. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1270. // We support Ethernet only
  1271. *((ULONG*)InformationBuffer) = NdisMedium802_3;
  1272. *BytesWritten = sizeof(ULONG);
  1273. return NDIS_STATUS_SUCCESS;
  1274. }
  1275. break;
  1276. case OID_GEN_TRANSMIT_BUFFER_SPACE:
  1277. {
  1278. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1279. // Lie and claim to have 15K of send space, a common
  1280. // Ethernet card value.
  1281. // REVIEW: Is there a better value?
  1282. *((ULONG*)InformationBuffer) = 15 * 1024;
  1283. *BytesWritten = sizeof(ULONG);
  1284. return NDIS_STATUS_SUCCESS;
  1285. }
  1286. break;
  1287. case OID_GEN_RECEIVE_BUFFER_SPACE:
  1288. {
  1289. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1290. // Lie and claim to have 150K of receive space, a common
  1291. // Ethernet card value.
  1292. // REVIEW: Is there a better value?
  1293. *((ULONG*)InformationBuffer) = 150 * 1024;
  1294. *BytesWritten = sizeof(ULONG);
  1295. return NDIS_STATUS_SUCCESS;
  1296. }
  1297. break;
  1298. case OID_GEN_MAXIMUM_SEND_PACKETS:
  1299. case OID_802_3_MAXIMUM_LIST_SIZE:
  1300. {
  1301. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1302. // Return a generic large integer
  1303. // REVIEW: Is there a better value to hand out?
  1304. *((ULONG*)InformationBuffer) = 0x000000FF;
  1305. *BytesWritten = sizeof(ULONG);
  1306. return NDIS_STATUS_SUCCESS;
  1307. }
  1308. break;
  1309. case OID_GEN_MAXIMUM_FRAME_SIZE:
  1310. {
  1311. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1312. // Ethernet payloads can be up to 1500 bytes
  1313. *((ULONG*)InformationBuffer) = 1500L;
  1314. *BytesWritten = sizeof(ULONG);
  1315. return NDIS_STATUS_SUCCESS;
  1316. }
  1317. break;
  1318. // We indicate full packets up to NDIS, so these values are the same and
  1319. // equal to the maximum size of a packet
  1320. case OID_GEN_MAXIMUM_LOOKAHEAD:
  1321. case OID_GEN_CURRENT_LOOKAHEAD:
  1322. // These are also just the maximum total size of a frame
  1323. case OID_GEN_MAXIMUM_TOTAL_SIZE:
  1324. case OID_GEN_RECEIVE_BLOCK_SIZE:
  1325. case OID_GEN_TRANSMIT_BLOCK_SIZE:
  1326. {
  1327. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1328. // Ethernet frames with header can be up to 1514 bytes
  1329. *((ULONG*)InformationBuffer) = 1514L;
  1330. *BytesWritten = sizeof(ULONG);
  1331. return NDIS_STATUS_SUCCESS;
  1332. }
  1333. break;
  1334. case OID_GEN_MAC_OPTIONS:
  1335. {
  1336. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1337. // We have no internal loopback support
  1338. *((ULONG*)InformationBuffer) = NDIS_MAC_OPTION_NO_LOOPBACK;
  1339. *BytesWritten = sizeof(ULONG);
  1340. return NDIS_STATUS_SUCCESS;
  1341. }
  1342. break;
  1343. case OID_GEN_LINK_SPEED:
  1344. {
  1345. LOCK_STATE LockState;
  1346. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1347. NdisAcquireReadWriteLock( &gBridgeStateLock, FALSE /*Read only*/, &LockState );
  1348. *((ULONG*)InformationBuffer) = gBridgeLinkSpeed;
  1349. NdisReleaseReadWriteLock( &gBridgeStateLock, &LockState );
  1350. *BytesWritten = sizeof(ULONG);
  1351. return NDIS_STATUS_SUCCESS;
  1352. }
  1353. break;
  1354. // Ethernet characteristics
  1355. case OID_802_3_PERMANENT_ADDRESS:
  1356. case OID_802_3_CURRENT_ADDRESS:
  1357. {
  1358. SAFEASSERT( gHaveAddress );
  1359. // Don't need a read lock because the address shouldn't change once set
  1360. REQUIRE_AT_LEAST( sizeof(gBridgeAddress) );
  1361. RETURN_BYTES( gBridgeAddress, sizeof(gBridgeAddress));
  1362. }
  1363. break;
  1364. case OID_GEN_MEDIA_CONNECT_STATUS:
  1365. {
  1366. LOCK_STATE LockState;
  1367. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1368. NdisAcquireReadWriteLock( &gBridgeStateLock, FALSE /*Read only*/, &LockState );
  1369. *((ULONG*)InformationBuffer) = gBridgeMediaState;
  1370. NdisReleaseReadWriteLock( &gBridgeStateLock, &LockState );
  1371. *BytesWritten = sizeof(ULONG);
  1372. return NDIS_STATUS_SUCCESS;
  1373. }
  1374. break;
  1375. case OID_GEN_VENDOR_ID:
  1376. {
  1377. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1378. // We don't have an IEEE-assigned ID so use this constant
  1379. *((ULONG*)InformationBuffer) = 0xFFFFFF;
  1380. *BytesWritten = sizeof(ULONG);
  1381. return NDIS_STATUS_SUCCESS;
  1382. }
  1383. break;
  1384. case OID_GEN_VENDOR_DESCRIPTION:
  1385. {
  1386. UINT len = (UINT)strlen( gDriverDescription ) + 1;
  1387. REQUIRE_AT_LEAST( len );
  1388. RETURN_BYTES( gDriverDescription, len);
  1389. }
  1390. break;
  1391. case OID_GEN_VENDOR_DRIVER_VERSION:
  1392. {
  1393. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1394. // We are version 1.0
  1395. *((ULONG*)InformationBuffer) = 0x00010000;
  1396. *BytesWritten = sizeof(ULONG);
  1397. return NDIS_STATUS_SUCCESS;
  1398. }
  1399. break;
  1400. case OID_GEN_DRIVER_VERSION:
  1401. {
  1402. REQUIRE_AT_LEAST( sizeof(USHORT) );
  1403. // We are using version 5.0 of NDIS
  1404. *((USHORT*)InformationBuffer) = 0x0500;
  1405. *BytesWritten = sizeof(USHORT);
  1406. return NDIS_STATUS_SUCCESS;
  1407. }
  1408. break;
  1409. //
  1410. // General Statistics
  1411. //
  1412. case OID_GEN_XMIT_OK:
  1413. {
  1414. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1415. // Reply with the number of local-sourced sent frames
  1416. *((ULONG*)InformationBuffer) = gStatTransmittedFrames.LowPart;
  1417. *BytesWritten = sizeof(ULONG);
  1418. return NDIS_STATUS_SUCCESS;
  1419. }
  1420. break;
  1421. case OID_GEN_XMIT_ERROR:
  1422. {
  1423. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1424. // Reply with the number of local-sourced frames sent with errors
  1425. *((ULONG*)InformationBuffer) = gStatTransmittedErrorFrames.LowPart;
  1426. *BytesWritten = sizeof(ULONG);
  1427. return NDIS_STATUS_SUCCESS;
  1428. }
  1429. break;
  1430. case OID_GEN_RCV_OK:
  1431. {
  1432. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1433. // Reply with the number of indicated frames
  1434. *((ULONG*)InformationBuffer) = gStatIndicatedFrames.LowPart;
  1435. *BytesWritten = sizeof(ULONG);
  1436. return NDIS_STATUS_SUCCESS;
  1437. }
  1438. break;
  1439. // Answer the same for these two
  1440. case OID_GEN_RCV_NO_BUFFER:
  1441. case OID_GEN_RCV_ERROR:
  1442. {
  1443. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1444. // Reply with the number of packets we wanted to indicate but couldn't
  1445. *((ULONG*)InformationBuffer) = gStatIndicatedDroppedFrames.LowPart;
  1446. *BytesWritten = sizeof(ULONG);
  1447. return NDIS_STATUS_SUCCESS;
  1448. }
  1449. break;
  1450. case OID_GEN_DIRECTED_BYTES_XMIT:
  1451. {
  1452. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1453. *((ULONG*)InformationBuffer) = gStatDirectedTransmittedBytes.LowPart;
  1454. *BytesWritten = sizeof(ULONG);
  1455. return NDIS_STATUS_SUCCESS;
  1456. }
  1457. break;
  1458. case OID_GEN_DIRECTED_FRAMES_XMIT:
  1459. {
  1460. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1461. // Reply with the number of packets we wanted to indicate but couldn't
  1462. *((ULONG*)InformationBuffer) = gStatDirectedTransmittedFrames.LowPart;
  1463. *BytesWritten = sizeof(ULONG);
  1464. return NDIS_STATUS_SUCCESS;
  1465. }
  1466. break;
  1467. case OID_GEN_MULTICAST_BYTES_XMIT:
  1468. {
  1469. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1470. // Reply with the number of packets we wanted to indicate but couldn't
  1471. *((ULONG*)InformationBuffer) = gStatMulticastTransmittedBytes.LowPart;
  1472. *BytesWritten = sizeof(ULONG);
  1473. return NDIS_STATUS_SUCCESS;
  1474. }
  1475. break;
  1476. case OID_GEN_MULTICAST_FRAMES_XMIT:
  1477. {
  1478. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1479. // Reply with the number of packets we wanted to indicate but couldn't
  1480. *((ULONG*)InformationBuffer) = gStatMulticastTransmittedFrames.LowPart;
  1481. *BytesWritten = sizeof(ULONG);
  1482. return NDIS_STATUS_SUCCESS;
  1483. }
  1484. break;
  1485. case OID_GEN_BROADCAST_BYTES_XMIT:
  1486. {
  1487. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1488. // Reply with the number of packets we wanted to indicate but couldn't
  1489. *((ULONG*)InformationBuffer) = gStatBroadcastTransmittedBytes.LowPart;
  1490. *BytesWritten = sizeof(ULONG);
  1491. return NDIS_STATUS_SUCCESS;
  1492. }
  1493. break;
  1494. case OID_GEN_BROADCAST_FRAMES_XMIT:
  1495. {
  1496. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1497. // Reply with the number of packets we wanted to indicate but couldn't
  1498. *((ULONG*)InformationBuffer) = gStatBroadcastTransmittedFrames.LowPart;
  1499. *BytesWritten = sizeof(ULONG);
  1500. return NDIS_STATUS_SUCCESS;
  1501. }
  1502. break;
  1503. case OID_GEN_DIRECTED_BYTES_RCV:
  1504. {
  1505. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1506. // Reply with the number of packets we wanted to indicate but couldn't
  1507. *((ULONG*)InformationBuffer) = gStatDirectedIndicatedBytes.LowPart;
  1508. *BytesWritten = sizeof(ULONG);
  1509. return NDIS_STATUS_SUCCESS;
  1510. }
  1511. break;
  1512. case OID_GEN_DIRECTED_FRAMES_RCV:
  1513. {
  1514. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1515. // Reply with the number of packets we wanted to indicate but couldn't
  1516. *((ULONG*)InformationBuffer) = gStatDirectedIndicatedFrames.LowPart;
  1517. *BytesWritten = sizeof(ULONG);
  1518. return NDIS_STATUS_SUCCESS;
  1519. }
  1520. break;
  1521. case OID_GEN_MULTICAST_BYTES_RCV:
  1522. {
  1523. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1524. // Reply with the number of packets we wanted to indicate but couldn't
  1525. *((ULONG*)InformationBuffer) = gStatMulticastIndicatedBytes.LowPart;
  1526. *BytesWritten = sizeof(ULONG);
  1527. return NDIS_STATUS_SUCCESS;
  1528. }
  1529. break;
  1530. case OID_GEN_MULTICAST_FRAMES_RCV:
  1531. {
  1532. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1533. // Reply with the number of packets we wanted to indicate but couldn't
  1534. *((ULONG*)InformationBuffer) = gStatMulticastIndicatedFrames.LowPart;
  1535. *BytesWritten = sizeof(ULONG);
  1536. return NDIS_STATUS_SUCCESS;
  1537. }
  1538. break;
  1539. case OID_GEN_BROADCAST_BYTES_RCV:
  1540. {
  1541. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1542. // Reply with the number of packets we wanted to indicate but couldn't
  1543. *((ULONG*)InformationBuffer) = gStatBroadcastIndicatedBytes.LowPart;
  1544. *BytesWritten = sizeof(ULONG);
  1545. return NDIS_STATUS_SUCCESS;
  1546. }
  1547. break;
  1548. case OID_GEN_BROADCAST_FRAMES_RCV:
  1549. {
  1550. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1551. // Reply with the number of packets we wanted to indicate but couldn't
  1552. *((ULONG*)InformationBuffer) = gStatBroadcastIndicatedFrames.LowPart;
  1553. *BytesWritten = sizeof(ULONG);
  1554. return NDIS_STATUS_SUCCESS;
  1555. }
  1556. break;
  1557. // Ethernet statistics
  1558. case OID_802_3_RCV_ERROR_ALIGNMENT:
  1559. case OID_802_3_XMIT_ONE_COLLISION:
  1560. case OID_802_3_XMIT_MORE_COLLISIONS:
  1561. {
  1562. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1563. // We have no way of collecting this information sensibly from lower NICs, so
  1564. // pretend these types of events never happen.
  1565. *((ULONG*)InformationBuffer) = 0L;
  1566. *BytesWritten = sizeof(ULONG);
  1567. return NDIS_STATUS_SUCCESS;
  1568. }
  1569. break;
  1570. case OID_GEN_CURRENT_PACKET_FILTER:
  1571. {
  1572. LOCK_STATE LockState;
  1573. REQUIRE_AT_LEAST( sizeof(ULONG) );
  1574. NdisAcquireReadWriteLock( &gBridgeStateLock, FALSE /*Read only*/, &LockState );
  1575. *((ULONG*)InformationBuffer) = gPacketFilter;
  1576. NdisReleaseReadWriteLock( &gBridgeStateLock, &LockState );
  1577. *BytesWritten = sizeof(ULONG);
  1578. return NDIS_STATUS_SUCCESS;
  1579. }
  1580. break;
  1581. case OID_802_3_MULTICAST_LIST:
  1582. {
  1583. LOCK_STATE LockState;
  1584. NdisAcquireReadWriteLock( &gBridgeStateLock, FALSE /*Read only*/, &LockState );
  1585. if(InformationBufferLength < gMulticastListLength)
  1586. {
  1587. *BytesNeeded = gMulticastListLength;
  1588. NdisReleaseReadWriteLock( &gBridgeStateLock, &LockState );
  1589. return NDIS_STATUS_INVALID_LENGTH;
  1590. }
  1591. NdisMoveMemory( InformationBuffer, gMulticastList, gMulticastListLength );
  1592. *BytesWritten = gMulticastListLength;
  1593. NdisReleaseReadWriteLock( &gBridgeStateLock, &LockState );
  1594. return NDIS_STATUS_SUCCESS;
  1595. }
  1596. break;
  1597. case OID_PNP_QUERY_POWER:
  1598. {
  1599. return NDIS_STATUS_SUCCESS;
  1600. }
  1601. break;
  1602. case OID_TCP_TASK_OFFLOAD:
  1603. {
  1604. // Mark that Tcp.ip has been loaded
  1605. g_fIsTcpIpLoaded = TRUE;
  1606. // Set the underlying 1394 miniport to ON
  1607. BrdgSetMiniportsToBridgeMode(NULL,TRUE);
  1608. return NDIS_STATUS_NOT_SUPPORTED;
  1609. }
  1610. break;
  1611. }
  1612. // We don't understand the OID
  1613. return NDIS_STATUS_NOT_SUPPORTED;
  1614. #undef REQUIRE_AT_LEAST
  1615. #undef RETURN_BYTES
  1616. }
  1617. NDIS_STATUS
  1618. BrdgMiniSetInfo(
  1619. IN NDIS_HANDLE MiniportAdapterContext,
  1620. IN NDIS_OID Oid,
  1621. IN PVOID InformationBuffer,
  1622. IN ULONG InformationBufferLength,
  1623. OUT PULONG BytesRead,
  1624. OUT PULONG BytesNeeded
  1625. )
  1626. /*++
  1627. Routine Description:
  1628. NDIS entry point called to set various pieces of info to our miniport
  1629. Arguments:
  1630. MiniportAdapterContext Ignored
  1631. Oid The request code
  1632. InformationBuffer Input information buffer
  1633. InformationBufferLength Size of InformationBuffer
  1634. BytesRead Number of bytes read from InformationBuffer
  1635. BytesNeeded If the provided buffer is too small, this is how many we need.
  1636. Return Value:
  1637. Status of the request
  1638. --*/
  1639. {
  1640. LOCK_STATE LockState;
  1641. NDIS_STATUS Status;
  1642. switch( Oid )
  1643. {
  1644. case OID_GEN_CURRENT_PACKET_FILTER:
  1645. {
  1646. SAFEASSERT( InformationBufferLength == sizeof(ULONG) );
  1647. // Get write access to the packet filter
  1648. NdisAcquireReadWriteLock( &gBridgeStateLock, TRUE /*Read-Write*/, &LockState );
  1649. gPacketFilter = *((ULONG*)InformationBuffer);
  1650. NdisReleaseReadWriteLock( &gBridgeStateLock, &LockState );
  1651. DBGPRINT(MINI, ("Set the packet filter to %08x\n", gPacketFilter));
  1652. *BytesRead = sizeof(ULONG);
  1653. return NDIS_STATUS_SUCCESS;
  1654. }
  1655. break;
  1656. case OID_802_3_MULTICAST_LIST:
  1657. {
  1658. PUCHAR pOldList, pNewList;
  1659. ULONG oldListLength;
  1660. // The incoming buffer should contain an integral number of Ethernet MAC
  1661. // addresses
  1662. SAFEASSERT( (InformationBufferLength % ETH_LENGTH_OF_ADDRESS) == 0 );
  1663. DBGPRINT(MINI, ("Modifying the multicast list; now has %i entries\n",
  1664. InformationBufferLength / ETH_LENGTH_OF_ADDRESS));
  1665. // Alloc and copy to the new multicast list
  1666. if( InformationBufferLength > 0 )
  1667. {
  1668. Status = NdisAllocateMemoryWithTag( &pNewList, InformationBufferLength, 'gdrB' );
  1669. if( Status != NDIS_STATUS_SUCCESS )
  1670. {
  1671. DBGPRINT(MINI, ("NdisAllocateMemoryWithTag failed while recording multicast list\n"));
  1672. return NDIS_STATUS_NOT_ACCEPTED;
  1673. }
  1674. // Copy the list
  1675. NdisMoveMemory( pNewList, InformationBuffer, InformationBufferLength );
  1676. }
  1677. else
  1678. {
  1679. pNewList = NULL;
  1680. }
  1681. // Swap in the new list
  1682. NdisAcquireReadWriteLock( &gBridgeStateLock, TRUE /*Read-Write*/, &LockState );
  1683. pOldList = gMulticastList;
  1684. oldListLength = gMulticastListLength;
  1685. gMulticastList = pNewList;
  1686. gMulticastListLength = InformationBufferLength;
  1687. NdisReleaseReadWriteLock( &gBridgeStateLock, &LockState );
  1688. // Free the old multicast list if there was one
  1689. if( pOldList != NULL )
  1690. {
  1691. NdisFreeMemory( pOldList, oldListLength, 0 );
  1692. }
  1693. *BytesRead = InformationBufferLength;
  1694. return NDIS_STATUS_SUCCESS;
  1695. }
  1696. break;
  1697. case OID_GEN_CURRENT_LOOKAHEAD:
  1698. case OID_GEN_PROTOCOL_OPTIONS:
  1699. {
  1700. // We accept these but do nothing
  1701. return NDIS_STATUS_SUCCESS;
  1702. }
  1703. break;
  1704. // Overlying protocols telling us about their network addresses
  1705. case OID_GEN_NETWORK_LAYER_ADDRESSES:
  1706. {
  1707. // Let the compatibility-mode code note the addresses
  1708. BrdgCompNotifyNetworkAddresses( InformationBuffer, InformationBufferLength );
  1709. }
  1710. //
  1711. // DELIBERATELY FALL THROUGH
  1712. //
  1713. // All relayed OIDs go here
  1714. case OID_GEN_TRANSPORT_HEADER_OFFSET:
  1715. {
  1716. LOCK_STATE LockState;
  1717. PADAPT Adapters[MAX_ADAPTERS], pAdapt;
  1718. LONG NumAdapters = 0L, i;
  1719. PNDIS_REQUEST_BETTER pRequest;
  1720. NDIS_STATUS Status, rc;
  1721. // We read the entire request
  1722. *BytesRead = InformationBufferLength;
  1723. // Pass these straight through to underlying NICs
  1724. NdisAcquireReadWriteLock( &gAdapterListLock, FALSE /*Read only*/, &LockState );
  1725. // Make a list of the adapters to send the request to
  1726. pAdapt = gAdapterList;
  1727. while( pAdapt != NULL )
  1728. {
  1729. if( NumAdapters < MAX_ADAPTERS )
  1730. {
  1731. Adapters[NumAdapters] = pAdapt;
  1732. // We will be using this adapter outside the list lock
  1733. BrdgAcquireAdapterInLock( pAdapt );
  1734. NumAdapters++;
  1735. }
  1736. else
  1737. {
  1738. SAFEASSERT( FALSE );
  1739. DBGPRINT(MINI, ("Too many adapters to relay a SetInfo request to!\n"));
  1740. }
  1741. pAdapt = pAdapt->Next;
  1742. }
  1743. // The refcount is the number of requests we will make
  1744. gRequestRefCount = NumAdapters;
  1745. NdisReleaseReadWriteLock( &gAdapterListLock, &LockState );
  1746. if( NumAdapters == 0 )
  1747. {
  1748. // Nothing to do!
  1749. rc = NDIS_STATUS_SUCCESS;
  1750. }
  1751. else
  1752. {
  1753. // Request will pend unless all adapters return immediately
  1754. rc = NDIS_STATUS_PENDING;
  1755. for( i = 0L; i < NumAdapters; i++ )
  1756. {
  1757. // Allocate memory for the request
  1758. Status = NdisAllocateMemoryWithTag( &pRequest, sizeof(NDIS_REQUEST_BETTER), 'gdrB' );
  1759. if( Status != NDIS_STATUS_SUCCESS )
  1760. {
  1761. LONG NewCount = InterlockedDecrement( &gRequestRefCount );
  1762. DBGPRINT(MINI, ("NdisAllocateMemoryWithTag failed while relaying an OID\n"));
  1763. if( NewCount == 0 )
  1764. {
  1765. // This could only have happened with the last adapter
  1766. SAFEASSERT( i == NumAdapters - 1 );
  1767. // We're all done since everyone else has completed too
  1768. rc = NDIS_STATUS_SUCCESS;
  1769. }
  1770. // Let go of the adapter
  1771. BrdgReleaseAdapter( Adapters[i] );
  1772. continue;
  1773. }
  1774. // Set up the request as a mirror of ours
  1775. pRequest->Request.RequestType = NdisRequestSetInformation;
  1776. pRequest->Request.DATA.SET_INFORMATION.Oid = Oid ;
  1777. pRequest->Request.DATA.SET_INFORMATION.InformationBuffer = InformationBuffer;
  1778. pRequest->Request.DATA.SET_INFORMATION.InformationBufferLength = InformationBufferLength;
  1779. NdisInitializeEvent( &pRequest->Event );
  1780. NdisResetEvent( &pRequest->Event );
  1781. pRequest->pFunc = BrdgMiniRelayedRequestComplete;
  1782. pRequest->FuncArg = NULL;
  1783. // Fire it off
  1784. NdisRequest( &Status, Adapters[i]->BindingHandle, &pRequest->Request );
  1785. // Let go of the adapter; NDIS should not permit it to be unbound while
  1786. // a request is in progress
  1787. BrdgReleaseAdapter( Adapters[i] );
  1788. if( Status != NDIS_STATUS_PENDING )
  1789. {
  1790. // The cleanup function won't get called
  1791. BrdgMiniRelayedRequestComplete( pRequest, NULL );
  1792. }
  1793. }
  1794. }
  1795. //
  1796. // Paranoia for future maintainance: can't refer to pointer parameters
  1797. // at this point, as the relayed requests may have completed already, making
  1798. // them stale.
  1799. //
  1800. InformationBuffer = NULL;
  1801. BytesRead = NULL;
  1802. BytesNeeded = NULL;
  1803. return rc;
  1804. }
  1805. break;
  1806. case OID_PNP_SET_POWER:
  1807. {
  1808. return NDIS_STATUS_SUCCESS;
  1809. }
  1810. break;
  1811. }
  1812. return NDIS_STATUS_NOT_SUPPORTED;
  1813. }
  1814. VOID
  1815. BrdgMiniRelayedRequestComplete(
  1816. PNDIS_REQUEST_BETTER pRequest,
  1817. PVOID unused
  1818. )
  1819. /*++
  1820. Routine Description:
  1821. Called when a SetInformation request that we relayed completes.
  1822. Arguments:
  1823. pRequest The NDIS_REQUEST_BETTER structure we allocated
  1824. in BrdgMiniSetInformation().
  1825. unused Unused
  1826. Return Value:
  1827. Status of the request
  1828. --*/
  1829. {
  1830. LONG NewCount = InterlockedDecrement( &gRequestRefCount );
  1831. if( NewCount == 0 )
  1832. {
  1833. // NDIS Should not permit the miniport to shut down with a request
  1834. // in progress
  1835. SAFEASSERT( gMiniPortAdapterHandle != NULL );
  1836. // The operation always succeeds
  1837. NdisMSetInformationComplete( gMiniPortAdapterHandle, NDIS_STATUS_SUCCESS );
  1838. }
  1839. // Free the request structure since we allocated it ourselves
  1840. NdisFreeMemory( pRequest, sizeof(PNDIS_REQUEST_BETTER), 0 );
  1841. }
  1842. VOID
  1843. BrdgMiniLocalRequestComplete(
  1844. PNDIS_REQUEST_BETTER pRequest,
  1845. PVOID pContext
  1846. )
  1847. /*++
  1848. Routine Description:
  1849. Called when bridge allocated request completes.
  1850. Arguments:
  1851. pRequest The NDIS_REQUEST_BETTER structure we allocated
  1852. in BrdgSetMiniportsToBridgeMode.
  1853. Context pAdapt structure
  1854. Return Value:
  1855. Status of the request
  1856. --*/
  1857. {
  1858. PADAPT pAdapt = (PADAPT)pContext;
  1859. // Let go of the adapter;
  1860. BrdgReleaseAdapter( pAdapt);
  1861. // Free the request structure since we allocated it ourselves
  1862. NdisFreeMemory( pRequest, sizeof(PNDIS_REQUEST_BETTER), 0 );
  1863. }
  1864. VOID
  1865. BrdgSetMiniportsToBridgeMode(
  1866. PADAPT pAdapt,
  1867. BOOLEAN fSet
  1868. )
  1869. /*++
  1870. Routine Description:
  1871. Sends a 1394 specific OID to the miniport informing it that TCP/IP
  1872. has been activated
  1873. Arguments:
  1874. pAdapt - If adapt is not NULL, send Request to this adapt.
  1875. Otherwise send it to all of them.
  1876. fSet - if True, then set Bridge Mode ON, otherwise set it OFF
  1877. Return Value:
  1878. Status of the request
  1879. --*/
  1880. {
  1881. LOCK_STATE LockState;
  1882. PADAPT Adapters[MAX_ADAPTERS];
  1883. LONG NumAdapters = 0L, i;
  1884. NDIS_OID Oid;
  1885. if (pAdapt != NULL)
  1886. {
  1887. if (pAdapt->PhysicalMedium == NdisPhysicalMedium1394)
  1888. {
  1889. // We have a 1394 adapt, ref it and send the request to it
  1890. if (BrdgAcquireAdapter (pAdapt))
  1891. {
  1892. Adapters[0] = pAdapt;
  1893. NumAdapters = 1;
  1894. }
  1895. }
  1896. }
  1897. else
  1898. {
  1899. // walk through the list and Acquire all the 1394 adapts
  1900. NdisAcquireReadWriteLock( &gAdapterListLock, FALSE /*Read only*/, &LockState );
  1901. // Make a list of the adapters to send the request to
  1902. pAdapt = gAdapterList;
  1903. while( pAdapt != NULL )
  1904. {
  1905. if( NumAdapters < MAX_ADAPTERS && pAdapt->PhysicalMedium == NdisPhysicalMedium1394)
  1906. {
  1907. Adapters[NumAdapters] = pAdapt;
  1908. // We will be using this adapter outside the list lock
  1909. BrdgAcquireAdapterInLock( pAdapt ); // cannot fail
  1910. NumAdapters++;
  1911. }
  1912. pAdapt = pAdapt->Next;
  1913. }
  1914. NdisReleaseReadWriteLock( &gAdapterListLock, &LockState );
  1915. }
  1916. if (NumAdapters == 0)
  1917. {
  1918. return;
  1919. }
  1920. if (fSet == TRUE)
  1921. {
  1922. Oid = OID_1394_ENTER_BRIDGE_MODE ;
  1923. DBGPRINT(MINI, ("Setting 1394 miniport bridge mode - ON !\n"));
  1924. }
  1925. else
  1926. {
  1927. Oid = OID_1394_EXIT_BRIDGE_MODE ;
  1928. DBGPRINT(MINI, ("Setting 1394 miniport bridge mode - OFF !\n"));
  1929. }
  1930. for( i = 0L; i < NumAdapters; i++ )
  1931. {
  1932. NDIS_STATUS Status;
  1933. PNDIS_REQUEST_BETTER pRequest;
  1934. Status = NdisAllocateMemoryWithTag( &pRequest, sizeof(NDIS_REQUEST_BETTER), 'gdrB' );
  1935. if( Status != NDIS_STATUS_SUCCESS )
  1936. {
  1937. DBGPRINT(MINI, ("NdisAllocateMemoryWithTag failed while allocating a request structure \n"));
  1938. // Let go of the adapter
  1939. BrdgReleaseAdapter( Adapters[i] );
  1940. continue;
  1941. }
  1942. // Set up the request
  1943. pRequest->Request.RequestType = NdisRequestSetInformation;
  1944. pRequest->Request.DATA.SET_INFORMATION.Oid = Oid;
  1945. pRequest->Request.DATA.SET_INFORMATION.InformationBuffer = NULL;
  1946. pRequest->Request.DATA.SET_INFORMATION.InformationBufferLength = 0 ;
  1947. NdisInitializeEvent( &pRequest->Event );
  1948. NdisResetEvent( &pRequest->Event );
  1949. pRequest->pFunc = BrdgMiniLocalRequestComplete;
  1950. pRequest->FuncArg = Adapters[i];
  1951. // Fire it off
  1952. NdisRequest( &Status, Adapters[i]->BindingHandle, &pRequest->Request );
  1953. if( Status != NDIS_STATUS_PENDING )
  1954. {
  1955. // The cleanup function won't get called
  1956. BrdgMiniLocalRequestComplete( pRequest, Adapters[i] );
  1957. }
  1958. } // end of for loop
  1959. return;
  1960. }