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.

1023 lines
29 KiB

  1. /*++
  2. Copyright(c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. bridge.c
  5. Abstract:
  6. Ethernet MAC level bridge.
  7. SAMPLE program illustrating how to interface with the bridge
  8. driver via IOCTLs
  9. Author:
  10. Mark Aiken
  11. Environment:
  12. User mode
  13. Revision History:
  14. Apr 2000 - Original version
  15. --*/
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <memory.h>
  20. #include <process.h>
  21. #include <ctype.h>
  22. #include <malloc.h>
  23. #include <time.h>
  24. #include <nt.h>
  25. #include <ntrtl.h>
  26. #include <nturtl.h>
  27. #include <winerror.h>
  28. #include <winsock.h>
  29. #include <ntddndis.h>
  30. #include "bioctl.h"
  31. // ===========================================================================
  32. //
  33. // GLOBALS
  34. //
  35. // ===========================================================================
  36. HANDLE gThreadQuitEvent = NULL;
  37. HANDLE gBridgeDeviceWrite = NULL;
  38. HANDLE gBridgeDeviceRead = NULL;
  39. // ===========================================================================
  40. //
  41. // FUNCTIONS
  42. //
  43. // ===========================================================================
  44. VOID
  45. PrintError(
  46. IN DWORD Error
  47. )
  48. /*++
  49. Routine Description:
  50. Prints a description of a system error
  51. Arguments:
  52. Error The error code
  53. --*/
  54. {
  55. TCHAR msg[200];
  56. printf( "(%08x): ", Error );
  57. if( FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, Error, 0, msg, sizeof(msg), NULL ) > 0 )
  58. {
  59. printf( "%s", msg );
  60. }
  61. }
  62. VOID
  63. PrintNotification(
  64. IN PBRIDGE_NOTIFY_HEADER pNotify,
  65. IN DWORD DataBytes
  66. )
  67. /*++
  68. Routine Description:
  69. Prints a notification from the bridge driver
  70. Arguments:
  71. pNotify The notification block
  72. DataBytes Total size of the notification block
  73. --*/
  74. {
  75. BOOLEAN bPrintAdapterInfo = TRUE;
  76. printf( "\n\nNotification on Adapter %p: ", pNotify->Handle );
  77. switch( pNotify->NotifyType )
  78. {
  79. case BrdgNotifyEnumerateAdapters:
  80. printf( "Enumeration was requested\n" );
  81. break;
  82. case BrdgNotifyAddAdapter:
  83. printf( "Adapter was added\n" );
  84. break;
  85. case BrdgNotifyRemoveAdapter:
  86. printf( "Adapter was removed\n" );
  87. bPrintAdapterInfo = FALSE;
  88. break;
  89. case BrdgNotifyLinkSpeedChange:
  90. printf( "Link speed changed\n" );
  91. break;
  92. case BrdgNotifyMediaStateChange:
  93. printf( "Media state changed\n" );
  94. break;
  95. case BrdgNotifyAdapterStateChange:
  96. printf( "Forwarding state changed\n" );
  97. break;
  98. default:
  99. printf( "UNKNOWN NOTIFICATION\n" );
  100. bPrintAdapterInfo = FALSE;
  101. break;
  102. }
  103. if( bPrintAdapterInfo )
  104. {
  105. PBRIDGE_ADAPTER_INFO pInfo = (PBRIDGE_ADAPTER_INFO)((PUCHAR)pNotify + sizeof(BRIDGE_NOTIFY_HEADER));
  106. printf("Adapter information:\n\n");
  107. printf("Link Speed: %iMbps\n", pInfo->LinkSpeed / 10000);
  108. printf("Media State: %s\n", pInfo->MediaState == NdisMediaStateConnected ? "CONNECTED" : "DISCONNECTED" );
  109. printf("Physical Medium: %08x\n", pInfo->PhysicalMedium);
  110. printf("Forwarding state: ");
  111. switch( pInfo->State )
  112. {
  113. case Disabled:
  114. printf("** DISABLED **\n");
  115. break;
  116. case Blocking:
  117. printf("BLOCKING\n");
  118. break;
  119. case Listening:
  120. printf("Listening\n");
  121. break;
  122. case Learning:
  123. printf("Learning\n");
  124. break;
  125. case Forwarding:
  126. printf("Forwarding\n");
  127. break;
  128. }
  129. printf("MAC Address: %02x-%02x-%02x-%02x-%02x-%02x\n", pInfo->MACAddress[0], pInfo->MACAddress[1],
  130. pInfo->MACAddress[2], pInfo->MACAddress[3], pInfo->MACAddress[4], pInfo->MACAddress[5]);
  131. }
  132. }
  133. VOID __cdecl
  134. NotificationThread(
  135. PVOID pv
  136. )
  137. /*++
  138. Routine Description:
  139. Notification-listening thread
  140. Pends an IOCTL call and waits for notifications from the bridge driver
  141. --*/
  142. {
  143. BOOLEAN bQuit = FALSE;
  144. HANDLE Handles[2];
  145. DWORD WaitResult, WrittenBytes;
  146. UCHAR OutBuffer[sizeof(BRIDGE_NOTIFY_HEADER) + 1514];
  147. OVERLAPPED Overlap;
  148. Handles[0] = gThreadQuitEvent;
  149. // Create an event to sleep against for the request
  150. Handles[1] = CreateEvent( NULL, FALSE/*auto-reset*/, FALSE/*Start unsignalled*/, NULL );
  151. if( Handles[1] == NULL )
  152. {
  153. printf( "Couldn't create an event: " );
  154. PrintError( GetLastError() );
  155. _endthread();
  156. }
  157. Overlap.Offset = Overlap.OffsetHigh = 0L;
  158. Overlap.hEvent = Handles[1];
  159. while( ! bQuit )
  160. {
  161. // Ask for a notification
  162. if( ! DeviceIoControl( gBridgeDeviceWrite, BRIDGE_IOCTL_REQUEST_NOTIFY, NULL, 0L, OutBuffer,
  163. sizeof(OutBuffer), &WrittenBytes, &Overlap ) )
  164. {
  165. DWORD Error = GetLastError();
  166. if( Error != ERROR_IO_PENDING )
  167. {
  168. printf( "DeviceIoControl returned an error: " );
  169. PrintError( Error );
  170. _endthread();
  171. }
  172. }
  173. // Wait against the completion event and the kill event
  174. WaitResult = WaitForMultipleObjects( 2, Handles, FALSE, INFINITE );
  175. if( WaitResult == WAIT_OBJECT_0 )
  176. {
  177. // The quit event was signaled
  178. bQuit = TRUE;
  179. }
  180. else if( WaitResult != WAIT_OBJECT_0 + 1 )
  181. {
  182. printf( "Error waiting: " );
  183. PrintError( GetLastError() );
  184. _endthread();
  185. }
  186. else
  187. {
  188. // The completion event was signaled.
  189. // Try to retrieve the number of bytes read
  190. if( !GetOverlappedResult(gBridgeDeviceWrite, &Overlap, &WrittenBytes, FALSE) )
  191. {
  192. printf( "Couldn't get the device call result: " );
  193. PrintError( GetLastError() );
  194. _endthread();
  195. }
  196. PrintNotification( (PBRIDGE_NOTIFY_HEADER)OutBuffer, WrittenBytes );
  197. }
  198. }
  199. printf("Notification thread exiting.\n");
  200. _endthread();
  201. }
  202. HANDLE
  203. OpenDevice(
  204. CHAR *pDeviceName,
  205. DWORD DesiredAccess
  206. )
  207. /*++
  208. Routine Description:
  209. Opens a device
  210. Arguments:
  211. pDeviceName The device's name
  212. Return Value:
  213. A handle to the opened device or INVALID_HANDLE_VALUE on failure;
  214. --*/
  215. {
  216. DWORD ShareMode;
  217. LPSECURITY_ATTRIBUTES lpSecurityAttributes = NULL;
  218. DWORD CreationDistribution;
  219. DWORD FlagsAndAttributes;
  220. HANDLE TemplateFile;
  221. HANDLE Handle = NULL;
  222. ShareMode = 0;
  223. CreationDistribution = OPEN_EXISTING;
  224. FlagsAndAttributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;
  225. TemplateFile = (HANDLE)INVALID_HANDLE_VALUE;
  226. Handle = CreateFile(
  227. pDeviceName,
  228. DesiredAccess,
  229. ShareMode,
  230. lpSecurityAttributes,
  231. CreationDistribution,
  232. FlagsAndAttributes,
  233. TemplateFile
  234. );
  235. return (Handle);
  236. }
  237. BOOL
  238. DoBlockingRequest(
  239. IN DWORD IOCTL,
  240. IN PVOID inBuff,
  241. IN DWORD inSize,
  242. IN PVOID outBuff,
  243. IN DWORD outSize,
  244. OUT OPTIONAL PDWORD pWrittenBytes
  245. )
  246. /*++
  247. Routine Description:
  248. Makes an IOCTL call to a driver and blocks until the request completes
  249. Arguments:
  250. IOCTL The IOCTL code
  251. inBuff The input data buffer
  252. inSize The size of the input buffer
  253. outBuff The output buffer
  254. outSize The size of the output buffer
  255. pWrittenBytes (optional) returns the number of bytes written to outBuff
  256. Return Value:
  257. TRUE for success, FALSE for failure
  258. --*/
  259. {
  260. DWORD WrittenBytes;
  261. OVERLAPPED Overlap;
  262. if( pWrittenBytes == NULL )
  263. {
  264. pWrittenBytes = &WrittenBytes;
  265. }
  266. // Create an event to sleep against for the request
  267. Overlap.hEvent = CreateEvent( NULL, FALSE/*auto-reset*/, FALSE/*Start unsignalled*/, NULL );
  268. if( Overlap.hEvent == NULL )
  269. {
  270. printf( "Couldn't create an event: " );
  271. PrintError( GetLastError() );
  272. return FALSE;
  273. }
  274. Overlap.Offset = Overlap.OffsetHigh = 0L;
  275. // Make the request
  276. if( ! DeviceIoControl( gBridgeDeviceRead, IOCTL, inBuff, inSize, outBuff,
  277. outSize,pWrittenBytes, &Overlap ) )
  278. {
  279. DWORD Error = GetLastError();
  280. if( Error != ERROR_IO_PENDING )
  281. {
  282. return FALSE;
  283. }
  284. }
  285. // Wait for the result
  286. if( !GetOverlappedResult(gBridgeDeviceRead, &Overlap,pWrittenBytes, TRUE) )
  287. {
  288. return FALSE;
  289. }
  290. return TRUE;
  291. }
  292. PVOID
  293. GetVariableData(
  294. IN ULONG IOCTL,
  295. IN PVOID inBuff,
  296. IN ULONG inBuffSize,
  297. OUT PULONG pNumBytes,
  298. IN ULONG safetyBuffer
  299. )
  300. /*++
  301. Routine Description:
  302. Makes an IOCTL call that returns variable-sized data (for which two calls must
  303. be made, one to determine the size of the data and the other to retrieve it)
  304. Arguments:
  305. IOCTL The IOCTL code
  306. inBuff The input data buffer
  307. inBuffSize The size of the input buffer
  308. pNumBytes The size of the allocated buffer holding the result
  309. safetyBuffer A count of bytes to allocate beyond the claimed size of
  310. the data (a safeguard against dynamically changing data)
  311. Return Value:
  312. A freshly allocated buffer, *pNumBytes large, with the return data
  313. NULL on failure
  314. --*/
  315. {
  316. // First make a request to discover the number of necessary bytes
  317. if( ! DoBlockingRequest( IOCTL, inBuff, inBuffSize, NULL, 0L, pNumBytes ) )
  318. {
  319. DWORD Error = GetLastError();
  320. // Expect the error to be ERROR_MORE_DATA since we didn't provide an output buffer!
  321. if( Error == ERROR_MORE_DATA )
  322. {
  323. if( *pNumBytes > 0L )
  324. {
  325. // Allocate safetyBuffer extra bytes in case the data is dynamic
  326. PUCHAR pData = (PUCHAR)HeapAlloc(GetProcessHeap(), 0, *pNumBytes + safetyBuffer);
  327. ULONG i;
  328. if( pData == NULL )
  329. {
  330. printf( "Failed to allocate %i bytes of memory: ", *pNumBytes + safetyBuffer );
  331. PrintError( GetLastError() );
  332. return NULL;
  333. }
  334. // Make the request again to actually retrieve the addresses
  335. if( ! DoBlockingRequest( IOCTL, inBuff, inBuffSize, pData, *pNumBytes + safetyBuffer, pNumBytes ) )
  336. {
  337. HeapFree( GetProcessHeap(), 0, pData );
  338. printf( "Failed to read variable-length data: " );
  339. PrintError( GetLastError() );
  340. return NULL;
  341. }
  342. // Success. Hand back the data buffer.
  343. return pData;
  344. }
  345. else
  346. {
  347. printf( "Driver returned zero bytes: " );
  348. PrintError( GetLastError() );
  349. return NULL;
  350. }
  351. }
  352. else
  353. {
  354. printf( "Failed to get the number of necessary bytes: " );
  355. PrintError( GetLastError() );
  356. return NULL;
  357. }
  358. }
  359. return NULL;
  360. }
  361. _inline VOID
  362. PrintByteString(
  363. IN PUCHAR pData,
  364. IN UINT numChars
  365. )
  366. {
  367. UINT i;
  368. for( i = 0; i < numChars; i++ )
  369. {
  370. printf( "%02x", pData[i] );
  371. if( i != numChars - 1 )
  372. {
  373. printf( "-" );
  374. }
  375. }
  376. printf( "\n" );
  377. }
  378. VOID
  379. PrintAdapterSTAInfo(
  380. IN BRIDGE_ADAPTER_HANDLE Handle
  381. )
  382. {
  383. BRIDGE_STA_ADAPTER_INFO info;
  384. if(! DoBlockingRequest(BRIDGE_IOCTL_GET_ADAPTER_STA_INFO, &Handle, sizeof(Handle), &info, sizeof(info), NULL) )
  385. {
  386. printf( "Couldn't request STA information for adapter %p : ", Handle );
  387. PrintError( GetLastError() );
  388. }
  389. else
  390. {
  391. printf( "\nSTA Information for adapter %p:\n\n", Handle );
  392. printf( "Port unique ID : %i\n", info.ID );
  393. printf( "Path Cost : %i\n", info.PathCost );
  394. printf( "Designated Root : " );
  395. PrintByteString( info.DesignatedRootID, BRIDGE_ID_LEN );
  396. printf( "Designated Cost : %i\n", info.DesignatedCost );
  397. printf( "Designated Bridge : " );
  398. PrintByteString( info.DesignatedBridgeID, BRIDGE_ID_LEN );
  399. printf( "Designated Port : %i\n\n", info.DesignatedPort );
  400. }
  401. }
  402. VOID
  403. PrintSTAInfo(
  404. )
  405. {
  406. BRIDGE_STA_GLOBAL_INFO info;
  407. if(! DoBlockingRequest(BRIDGE_IOCTL_GET_GLOBAL_STA_INFO, NULL, 0L, &info, sizeof(info), NULL) )
  408. {
  409. printf( "Couldn't request global STA information : " );
  410. PrintError( GetLastError() );
  411. }
  412. else
  413. {
  414. printf( "This bridge's ID : " );
  415. PrintByteString( info.OurID, BRIDGE_ID_LEN );
  416. printf( "Designated Root : " );
  417. PrintByteString( info.DesignatedRootID, BRIDGE_ID_LEN );
  418. printf( "Cost to root : %i\n", info.RootCost );
  419. printf( "Root adapter : %p\n", info.RootAdapter );
  420. printf( "MaxAge : %i\n", info.MaxAge );
  421. printf( "HelloTime : %i\n", info.HelloTime );
  422. printf( "ForwardDelay : %i\n", info.ForwardDelay );
  423. printf( "TopologyChangeDetected : " );
  424. if( info.bTopologyChangeDetected )
  425. {
  426. printf( "TRUE\n" );
  427. }
  428. else
  429. {
  430. printf( "FALSE\n" );
  431. }
  432. printf( "TopologyChange : " );
  433. if( info.bTopologyChange )
  434. {
  435. printf( "TRUE\n\n" );
  436. }
  437. else
  438. {
  439. printf( "FALSE\n\n" );
  440. }
  441. }
  442. }
  443. VOID
  444. PrintTableEntries(
  445. IN BRIDGE_ADAPTER_HANDLE Handle
  446. )
  447. /*++
  448. Routine Description:
  449. Retrieves and prints the MAC table entries for a particular adapter
  450. Arguments:
  451. Handle The adapter
  452. --*/
  453. {
  454. PUCHAR pAddresses;
  455. ULONG i, numBytes;
  456. pAddresses = GetVariableData( BRIDGE_IOCTL_GET_TABLE_ENTRIES, &Handle, sizeof(Handle), &numBytes, 60L );
  457. if( pAddresses == NULL )
  458. {
  459. printf( "Failed to read table entries: " );
  460. PrintError( GetLastError() );
  461. return;
  462. }
  463. printf( "Forwarding table entries for adapter %x: \n", Handle );
  464. for( i = 0L; i < numBytes / ETH_LENGTH_OF_ADDRESS; i++ )
  465. {
  466. PrintByteString( pAddresses, ETH_LENGTH_OF_ADDRESS );
  467. pAddresses += ETH_LENGTH_OF_ADDRESS;
  468. }
  469. HeapFree( GetProcessHeap(), 0, pAddresses );
  470. }
  471. VOID
  472. PrintPacketStats(
  473. IN PBRIDGE_PACKET_STATISTICS pStats
  474. )
  475. /*++
  476. Routine Description:
  477. Prints a BRIDGE_PACKET_STATISTICS structure in a friendly way
  478. Arguments:
  479. pStats The structure
  480. --*/
  481. {
  482. printf("Bridge packet statistics:\n\n");
  483. printf("Transmitted Frames: %16I64u\n", pStats->TransmittedFrames);
  484. printf("Transmitted Frames w/Errors: %16I64u\n", pStats->TransmittedErrorFrames);
  485. printf("Transmitted Directed Frames: %16I64u\n", pStats->DirectedTransmittedFrames);
  486. printf("Transmitted Multicast Frames: %16I64u\n", pStats->MulticastTransmittedFrames);
  487. printf("Transmitted Broadcast Frames: %16I64u\n\n", pStats->BroadcastTransmittedFrames);
  488. printf("Transmitted Bytes: %16I64u\n", pStats->TransmittedBytes);
  489. printf("Transmitted Directed Bytes %16I64u\n", pStats->DirectedTransmittedBytes);
  490. printf("Transmitted Multicast Bytes: %16I64u\n", pStats->MulticastTransmittedBytes);
  491. printf("Transmitted Broadcast Bytes: %16I64u\n\n", pStats->BroadcastTransmittedBytes);
  492. printf("Indicated Frames: %16I64u\n", pStats->IndicatedFrames);
  493. printf("Indicated Frames w/Errors: %16I64u\n\n", pStats->IndicatedDroppedFrames);
  494. printf("Indicated Directed Frames: %16I64u\n", pStats->DirectedIndicatedFrames);
  495. printf("Indicated Multicast Frames: %16I64u\n", pStats->MulticastIndicatedFrames);
  496. printf("Indicated Broadcast Frames: %16I64u\n\n", pStats->BroadcastIndicatedFrames);
  497. printf("Indicated Bytes: %16I64u\n", pStats->IndicatedBytes);
  498. printf("Indicated Directed Bytes: %16I64u\n", pStats->DirectedIndicatedBytes);
  499. printf("Indicated Multicast Bytes: %16I64u\n", pStats->MulticastIndicatedBytes);
  500. printf("Indicated Broadcast Bytes: %16I64u\n\n", pStats->BroadcastIndicatedBytes);
  501. printf("Received Frames (incl. relay): %16I64u\n", pStats->ReceivedFrames);
  502. printf("Received Bytes (incl. relay): %16I64u\n", pStats->ReceivedBytes);
  503. printf("Received Frames w/Copy: %16I64u\n", pStats->ReceivedCopyFrames);
  504. printf("Received Bytes w/Copy: %16I64u\n", pStats->ReceivedCopyBytes);
  505. printf("Received Frames w/No Copy: %16I64u\n", pStats->ReceivedNoCopyFrames);
  506. printf("Received Bytes w/No Copy: %16I64u\n", pStats->ReceivedNoCopyBytes);
  507. }
  508. VOID
  509. PrintAdapterPacketStats(
  510. IN PBRIDGE_ADAPTER_PACKET_STATISTICS pStats
  511. )
  512. /*++
  513. Routine Description:
  514. Prints a BRIDGE_ADAPTER_PACKET_STATISTICS structure in a friendly way
  515. Arguments:
  516. pStats The structure
  517. --*/
  518. {
  519. PUCHAR pc = (PUCHAR)pStats;
  520. printf("Bridge per-adapter packet statistics:\n\n");
  521. printf("Transmitted Frames: %16I64u\n", pStats->SentFrames);
  522. printf("Transmitted Bytes: %16I64u\n", pStats->SentBytes);
  523. printf("Transmitted Local-Source Frames: %16I64u\n", pStats->SentLocalFrames);
  524. printf("Transmitted Local-Source Bytes: %16I64u\n", pStats->SentLocalBytes);
  525. printf("Received Frames: %16I64u\n", pStats->ReceivedFrames);
  526. printf("Received Bytes: %16I64u\n\n", pStats->ReceivedBytes);
  527. }
  528. VOID
  529. PrintBufferStats(
  530. IN PBRIDGE_BUFFER_STATISTICS pStats
  531. )
  532. /*++
  533. Routine Description:
  534. Prints a BRIDGE_BUFFER_STATISTICS structure in a friendly way
  535. Arguments:
  536. pStats The structure
  537. --*/
  538. {
  539. printf("Bridge buffer statistics:\n\n");
  540. printf("Copy Packets In Use: %4lu\n", pStats->UsedCopyPackets);
  541. printf("Total Copy Packets Available: %4lu\n", pStats->MaxCopyPackets);
  542. printf("Safety Copy Packets: %4lu\n", pStats->SafetyCopyPackets);
  543. printf("Copy Pool Overflows: %10I64u\n\n", pStats->CopyPoolOverflows);
  544. printf("Wrapper Packets In Use: %4lu\n", pStats->UsedWrapperPackets);
  545. printf("Total Wrapper Packets Available: %4lu\n", pStats->MaxWrapperPackets);
  546. printf("Safety Wrapper Packets: %4lu\n", pStats->SafetyWrapperPackets);
  547. printf("Wrapper Pool Overflows: %10I64u\n\n", pStats->WrapperPoolOverflows);
  548. printf("Surprise Alloc Failures: %10I64u\n", pStats->AllocFailures);
  549. }
  550. BOOLEAN
  551. ReadUlongArg(
  552. IN PUCHAR inbuf,
  553. OUT PULONG arg
  554. )
  555. /*++
  556. Routine Description:
  557. Reads an unsigned decimal value from a string and returns it
  558. The value must occur as the second word of the string
  559. Arguments:
  560. inbuf The input string
  561. arg The resulting number
  562. Return Value:
  563. TRUE for success, FALSE for failure
  564. --*/
  565. {
  566. UCHAR scratch[100];
  567. if( sscanf(inbuf, "%s %lu", scratch, arg) < 2 )
  568. {
  569. return FALSE;
  570. }
  571. return TRUE;
  572. }
  573. BOOLEAN
  574. ReadHexPtrArg(
  575. IN PUCHAR inbuf,
  576. OUT PULONG_PTR arg
  577. )
  578. /*++
  579. Routine Description:
  580. Reads an unsigned hexidecimal value from a string and returns it
  581. The value must occur as the second word of the string
  582. Arguments:
  583. inbuf The input string
  584. arg The resulting number
  585. Return Value:
  586. TRUE for success, FALSE for failure
  587. --*/
  588. {
  589. UCHAR scratch[100];
  590. INT read;
  591. if( sizeof(*arg) <= sizeof(ULONG) )
  592. {
  593. read = sscanf(inbuf, "%s %lx", scratch, arg);
  594. }
  595. else
  596. {
  597. read = sscanf(inbuf, "%s %I64x", scratch, arg);
  598. }
  599. if( (read != EOF) && (read < 2) )
  600. {
  601. return FALSE;
  602. }
  603. return TRUE;
  604. }
  605. VOID __cdecl
  606. main(
  607. INT argc,
  608. CHAR *argv[]
  609. )
  610. {
  611. CHAR inbuf[100], command[100];
  612. BOOLEAN bQuit = FALSE;
  613. printf("\nSAMPLE MAC Bridge control program\n");
  614. // Open the bridge device for Read Access
  615. gBridgeDeviceRead = OpenDevice( BRIDGE_DOS_DEVICE_NAME , GENERIC_READ);
  616. if( gBridgeDeviceRead == INVALID_HANDLE_VALUE )
  617. {
  618. printf( "Couldn't open bridge device: " );
  619. PrintError( GetLastError() );
  620. return;
  621. }
  622. // Open the bridge device for Write Access
  623. gBridgeDeviceWrite = OpenDevice( BRIDGE_DOS_DEVICE_NAME , GENERIC_WRITE);
  624. if( gBridgeDeviceWrite == INVALID_HANDLE_VALUE )
  625. {
  626. printf( "Couldn't open bridge device: " );
  627. PrintError( GetLastError() );
  628. return;
  629. }
  630. // Create the thread-quit notification event
  631. gThreadQuitEvent = CreateEvent( NULL, FALSE/*auto-reset*/, FALSE/*Start unsignalled*/, NULL );
  632. if( gThreadQuitEvent == NULL )
  633. {
  634. printf( "Couldn't create an event: " );
  635. PrintError( GetLastError() );
  636. return;
  637. }
  638. // Spin up a thread to handle notifications
  639. _beginthread( NotificationThread, 0, NULL );
  640. while( ! bQuit )
  641. {
  642. PCHAR pSpace;
  643. printf( "> " );
  644. // Get a line of input
  645. gets( inbuf );
  646. // Find the first word delimiter
  647. pSpace = strchr( inbuf, ' ' );
  648. // Copy over the first word
  649. if( pSpace != NULL )
  650. {
  651. strncpy( command, inbuf, pSpace - inbuf );
  652. command[pSpace-inbuf] = '\0';
  653. }
  654. else
  655. {
  656. strcpy( command, inbuf );
  657. }
  658. if( _stricmp(command, "enum") == 0 )
  659. {
  660. if(! DoBlockingRequest(BRIDGE_IOCTL_GET_ADAPTERS, NULL, 0L, NULL, 0L, NULL) )
  661. {
  662. printf( "Couldn't request an adapter re-enumeration : " );
  663. PrintError( GetLastError() );
  664. }
  665. else
  666. {
  667. printf("Requested an adapter re-enumeration.\n" );
  668. }
  669. }
  670. else if( (_stricmp(command, "devicename") == 0) ||
  671. (_stricmp(command, "friendlyname") == 0) )
  672. {
  673. ULONG IOCTL = (_stricmp(command, "devicename") == 0) ? BRIDGE_IOCTL_GET_ADAPT_DEVICE_NAME :
  674. BRIDGE_IOCTL_GET_ADAPT_FRIENDLY_NAME;
  675. BRIDGE_ADAPTER_HANDLE Handle;
  676. PWCHAR pName;
  677. ULONG numBytes;
  678. if( ! ReadHexPtrArg(inbuf, &Handle) )
  679. {
  680. printf("Must supply an adapter handle for this command.\n");
  681. }
  682. else
  683. {
  684. pName = (PWCHAR)GetVariableData( IOCTL, &Handle, sizeof(Handle), &numBytes, 0L );
  685. if( pName == NULL )
  686. {
  687. printf("Couldn't get name for adapter %p: ", Handle);
  688. PrintError( GetLastError() );
  689. }
  690. else
  691. {
  692. printf("The name is: %S\n", pName);
  693. }
  694. HeapFree( GetProcessHeap(), 0, pName );
  695. }
  696. }
  697. else if( _stricmp(command, "table") == 0 )
  698. {
  699. BRIDGE_ADAPTER_HANDLE Handle;
  700. if( ! ReadHexPtrArg(inbuf, &Handle) )
  701. {
  702. printf("Must supply an adapter handle for this command.\n");
  703. }
  704. else
  705. {
  706. PrintTableEntries(Handle);
  707. }
  708. }
  709. else if( _stricmp(command, "mac") == 0 )
  710. {
  711. UCHAR addr[ETH_LENGTH_OF_ADDRESS];
  712. if(! DoBlockingRequest(BRIDGE_IOCTL_GET_MAC_ADDRESS, NULL, 0L, addr, sizeof(addr), NULL) )
  713. {
  714. printf("Attempt to query MAC address failed: ");
  715. PrintError( GetLastError() );
  716. }
  717. else
  718. {
  719. printf( "Bridge MAC address is %02x-%02x-%02x-%02x-%02x-%02x\n", addr[0], addr[1],
  720. addr[2], addr[3], addr[4], addr[5] );
  721. }
  722. }
  723. else if( _stricmp(command, "packetstats") == 0 )
  724. {
  725. BRIDGE_ADAPTER_HANDLE Handle;
  726. if( ! ReadHexPtrArg(inbuf, &Handle) )
  727. {
  728. BRIDGE_PACKET_STATISTICS Stats;
  729. if(! DoBlockingRequest(BRIDGE_IOCTL_GET_PACKET_STATS, NULL, 0L, &Stats, sizeof(Stats), NULL) )
  730. {
  731. printf("Attempt to retrieve global packet statistics failed: ");
  732. PrintError( GetLastError() );
  733. }
  734. else
  735. {
  736. PrintPacketStats(&Stats);
  737. }
  738. }
  739. else
  740. {
  741. BRIDGE_ADAPTER_PACKET_STATISTICS Stats;
  742. if(! DoBlockingRequest(BRIDGE_IOCTL_GET_ADAPTER_PACKET_STATS, &Handle, sizeof(Handle), &Stats, sizeof(Stats), NULL) )
  743. {
  744. printf("Attempt to retrieve packet statistics for adapter %p failed: ", Handle);
  745. PrintError( GetLastError() );
  746. }
  747. else
  748. {
  749. PrintAdapterPacketStats(&Stats);
  750. }
  751. }
  752. }
  753. else if( _stricmp(command, "bufferstats") == 0 )
  754. {
  755. BRIDGE_BUFFER_STATISTICS Stats;
  756. if(! DoBlockingRequest(BRIDGE_IOCTL_GET_BUFFER_STATS, NULL, 0L, &Stats, sizeof(Stats), NULL) )
  757. {
  758. printf("Attempt to retrieve buffer statistics failed: ");
  759. PrintError( GetLastError() );
  760. }
  761. else
  762. {
  763. PrintBufferStats(&Stats);
  764. }
  765. }
  766. else if( _stricmp(command, "stainfo") == 0 )
  767. {
  768. BRIDGE_ADAPTER_HANDLE Handle;
  769. if( ! ReadHexPtrArg(inbuf, &Handle) )
  770. {
  771. PrintSTAInfo();
  772. }
  773. else
  774. {
  775. PrintAdapterSTAInfo( Handle );
  776. }
  777. }
  778. else if( _stricmp( command, "quit" ) == 0 )
  779. {
  780. printf( "Signalling an exit...\n" );
  781. if( ! SetEvent( gThreadQuitEvent ) )
  782. {
  783. printf( "Couldn't signal an event: " );
  784. PrintError( GetLastError() );
  785. return;
  786. }
  787. bQuit = TRUE;
  788. }
  789. else
  790. {
  791. // Print a list of commands to help the user
  792. printf( "\n\nSupported commands:\n\n" );
  793. printf( "ENUM - Enumerates adapters\n" );
  794. printf( "DEVICENAME <handle> - Retrieves the device name of the indicated adapter\n" );
  795. printf( "FRIENDLYNAME <handle> - Retrieves the friendly name of the indicated adapter\n" );
  796. printf( "TABLE <handle> - Prints the forwarding table for the indicated adapter\n" );
  797. printf( "MAC - Prints the bridge's MAC address\n" );
  798. printf( "PACKETSTATS [<handle>] - Retrieves packet-handling statistics for a particular\n" );
  799. printf( " adapter (or global data if no adapter handle is\n" );
  800. printf( " provided)\n" );
  801. printf( "BUFFERSTATS - Retrieves buffer-management statistics\n" );
  802. printf( "STAINFO [<handle>] - Retrieves STA info for a particular adapter (or global\n" );
  803. printf( " info if no adapter handle is provided)\n" );
  804. printf( "QUIT - Exits\n\n" );
  805. }
  806. }
  807. CloseHandle( gBridgeDeviceRead );
  808. CloseHandle( gBridgeDeviceWrite );
  809. }