Source code of Windows XP (NT5)
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.

1038 lines
28 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 gBridgeDevice = NULL;
  38. // ===========================================================================
  39. //
  40. // FUNCTIONS
  41. //
  42. // ===========================================================================
  43. VOID
  44. PrintError(
  45. IN DWORD Error
  46. )
  47. /*++
  48. Routine Description:
  49. Prints a description of a system error
  50. Arguments:
  51. Error The error code
  52. --*/
  53. {
  54. TCHAR msg[200];
  55. printf( "(%08x): ", Error );
  56. if( FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, Error, 0, msg, sizeof(msg), NULL ) > 0 )
  57. {
  58. printf( "%s", msg );
  59. }
  60. }
  61. VOID
  62. PrintNotification(
  63. IN PBRIDGE_NOTIFY_HEADER pNotify,
  64. IN DWORD DataBytes
  65. )
  66. /*++
  67. Routine Description:
  68. Prints a notification from the bridge driver
  69. Arguments:
  70. pNotify The notification block
  71. DataBytes Total size of the notification block
  72. --*/
  73. {
  74. BOOLEAN bPrintAdapterInfo = TRUE;
  75. printf( "\n\nNotification on Adapter %p: ", pNotify->Handle );
  76. switch( pNotify->NotifyType )
  77. {
  78. case BrdgNotifyEnumerateAdapters:
  79. printf( "Enumeration was requested\n" );
  80. break;
  81. case BrdgNotifyAddAdapter:
  82. printf( "Adapter was added\n" );
  83. break;
  84. case BrdgNotifyRemoveAdapter:
  85. printf( "Adapter was removed\n" );
  86. bPrintAdapterInfo = FALSE;
  87. break;
  88. case BrdgNotifyLinkSpeedChange:
  89. printf( "Link speed changed\n" );
  90. break;
  91. case BrdgNotifyMediaStateChange:
  92. printf( "Media state changed\n" );
  93. break;
  94. case BrdgNotifyAdapterStateChange:
  95. printf( "Forwarding state changed\n" );
  96. break;
  97. default:
  98. printf( "UNKNOWN NOTIFICATION\n" );
  99. bPrintAdapterInfo = FALSE;
  100. break;
  101. }
  102. if( bPrintAdapterInfo )
  103. {
  104. PBRIDGE_ADAPTER_INFO pInfo = (PBRIDGE_ADAPTER_INFO)((PUCHAR)pNotify + sizeof(BRIDGE_NOTIFY_HEADER));
  105. printf("Adapter information:\n\n");
  106. printf("Link Speed: %iMbps\n", pInfo->LinkSpeed / 10000);
  107. printf("Media State: %s\n", pInfo->MediaState == NdisMediaStateConnected ? "CONNECTED" : "DISCONNECTED" );
  108. printf("Physical Medium: %08x\n", pInfo->PhysicalMedium);
  109. printf("Forwarding state: ");
  110. switch( pInfo->State )
  111. {
  112. case Disabled:
  113. printf("** DISABLED **\n");
  114. break;
  115. case Blocking:
  116. printf("BLOCKING\n");
  117. break;
  118. case Listening:
  119. printf("Listening\n");
  120. break;
  121. case Learning:
  122. printf("Learning\n");
  123. break;
  124. case Forwarding:
  125. printf("Forwarding\n");
  126. break;
  127. }
  128. printf("MAC Address: %02x-%02x-%02x-%02x-%02x-%02x\n", pInfo->MACAddress[0], pInfo->MACAddress[1],
  129. pInfo->MACAddress[2], pInfo->MACAddress[3], pInfo->MACAddress[4], pInfo->MACAddress[5]);
  130. }
  131. }
  132. VOID __cdecl
  133. NotificationThread(
  134. PVOID pv
  135. )
  136. /*++
  137. Routine Description:
  138. Notification-listening thread
  139. Pends an IOCTL call and waits for notifications from the bridge driver
  140. --*/
  141. {
  142. BOOLEAN bQuit = FALSE;
  143. HANDLE Handles[2];
  144. DWORD WaitResult, WrittenBytes;
  145. UCHAR OutBuffer[sizeof(BRIDGE_NOTIFY_HEADER) + 1514];
  146. OVERLAPPED Overlap;
  147. Handles[0] = gThreadQuitEvent;
  148. // Create an event to sleep against for the request
  149. Handles[1] = CreateEvent( NULL, FALSE/*auto-reset*/, FALSE/*Start unsignalled*/, NULL );
  150. if( Handles[1] == NULL )
  151. {
  152. printf( "Couldn't create an event: " );
  153. PrintError( GetLastError() );
  154. _endthread();
  155. }
  156. Overlap.Offset = Overlap.OffsetHigh = 0L;
  157. Overlap.hEvent = Handles[1];
  158. while( ! bQuit )
  159. {
  160. // Ask for a notification
  161. if( ! DeviceIoControl( gBridgeDevice, BRIDGE_IOCTL_REQUEST_NOTIFY, NULL, 0L, OutBuffer,
  162. sizeof(OutBuffer), &WrittenBytes, &Overlap ) )
  163. {
  164. DWORD Error = GetLastError();
  165. if( Error != ERROR_IO_PENDING )
  166. {
  167. printf( "DeviceIoControl returned an error: " );
  168. PrintError( Error );
  169. _endthread();
  170. }
  171. }
  172. // Wait against the completion event and the kill event
  173. WaitResult = WaitForMultipleObjects( 2, Handles, FALSE, INFINITE );
  174. if( WaitResult == WAIT_OBJECT_0 )
  175. {
  176. // The quit event was signaled
  177. bQuit = TRUE;
  178. }
  179. else if( WaitResult != WAIT_OBJECT_0 + 1 )
  180. {
  181. printf( "Error waiting: " );
  182. PrintError( GetLastError() );
  183. _endthread();
  184. }
  185. else
  186. {
  187. // The completion event was signaled.
  188. // Try to retrieve the number of bytes read
  189. if( !GetOverlappedResult(gBridgeDevice, &Overlap, &WrittenBytes, FALSE) )
  190. {
  191. printf( "Couldn't get the device call result: " );
  192. PrintError( GetLastError() );
  193. _endthread();
  194. }
  195. PrintNotification( (PBRIDGE_NOTIFY_HEADER)OutBuffer, WrittenBytes );
  196. }
  197. }
  198. printf("Notification thread exiting.\n");
  199. _endthread();
  200. }
  201. HANDLE
  202. OpenDevice(
  203. CHAR *pDeviceName
  204. )
  205. /*++
  206. Routine Description:
  207. Opens a device
  208. Arguments:
  209. pDeviceName The device's name
  210. Return Value:
  211. A handle to the opened device or INVALID_HANDLE_VALUE on failure;
  212. --*/
  213. {
  214. DWORD DesiredAccess;
  215. DWORD ShareMode;
  216. LPSECURITY_ATTRIBUTES lpSecurityAttributes = NULL;
  217. DWORD CreationDistribution;
  218. DWORD FlagsAndAttributes;
  219. HANDLE TemplateFile;
  220. HANDLE Handle = NULL;
  221. DesiredAccess = GENERIC_READ|GENERIC_WRITE;
  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( gBridgeDevice, 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(gBridgeDevice, &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
  615. gBridgeDevice = OpenDevice( BRIDGE_DOS_DEVICE_NAME );
  616. if( gBridgeDevice == INVALID_HANDLE_VALUE )
  617. {
  618. printf( "Couldn't open bridge device: " );
  619. PrintError( GetLastError() );
  620. return;
  621. }
  622. // Create the thread-quit notification event
  623. gThreadQuitEvent = CreateEvent( NULL, FALSE/*auto-reset*/, FALSE/*Start unsignalled*/, NULL );
  624. if( gThreadQuitEvent == NULL )
  625. {
  626. printf( "Couldn't create an event: " );
  627. PrintError( GetLastError() );
  628. return;
  629. }
  630. // Spin up a thread to handle notifications
  631. _beginthread( NotificationThread, 0, NULL );
  632. while( ! bQuit )
  633. {
  634. PCHAR pSpace;
  635. printf( "> " );
  636. // Get a line of input
  637. gets( inbuf );
  638. // Find the first word delimiter
  639. pSpace = strchr( inbuf, ' ' );
  640. // Copy over the first word
  641. if( pSpace != NULL )
  642. {
  643. strncpy( command, inbuf, pSpace - inbuf );
  644. command[pSpace-inbuf] = '\0';
  645. }
  646. else
  647. {
  648. strcpy( command, inbuf );
  649. }
  650. if( _stricmp(command, "enum") == 0 )
  651. {
  652. if(! DoBlockingRequest(BRIDGE_IOCTL_GET_ADAPTERS, NULL, 0L, NULL, 0L, NULL) )
  653. {
  654. printf( "Couldn't request an adapter re-enumeration : " );
  655. PrintError( GetLastError() );
  656. }
  657. else
  658. {
  659. printf("Requested an adapter re-enumeration.\n" );
  660. }
  661. }
  662. else if( (_stricmp(command, "devicename") == 0) ||
  663. (_stricmp(command, "friendlyname") == 0) )
  664. {
  665. ULONG IOCTL = (_stricmp(command, "devicename") == 0) ? BRIDGE_IOCTL_GET_ADAPT_DEVICE_NAME :
  666. BRIDGE_IOCTL_GET_ADAPT_FRIENDLY_NAME;
  667. BRIDGE_ADAPTER_HANDLE Handle;
  668. PWCHAR pName;
  669. ULONG numBytes;
  670. if( ! ReadHexPtrArg(inbuf, &Handle) )
  671. {
  672. printf("Must supply an adapter handle for this command.\n");
  673. }
  674. else
  675. {
  676. pName = (PWCHAR)GetVariableData( IOCTL, &Handle, sizeof(Handle), &numBytes, 0L );
  677. if( pName == NULL )
  678. {
  679. printf("Couldn't get name for adapter %p: ", Handle);
  680. PrintError( GetLastError() );
  681. }
  682. else
  683. {
  684. printf("The name is: %S\n", pName);
  685. }
  686. HeapFree( GetProcessHeap(), 0, pName );
  687. }
  688. }
  689. else if( _stricmp(command, "table") == 0 )
  690. {
  691. BRIDGE_ADAPTER_HANDLE Handle;
  692. if( ! ReadHexPtrArg(inbuf, &Handle) )
  693. {
  694. printf("Must supply an adapter handle for this command.\n");
  695. }
  696. else
  697. {
  698. PrintTableEntries(Handle);
  699. }
  700. }
  701. else if( _stricmp(command, "mac") == 0 )
  702. {
  703. UCHAR addr[ETH_LENGTH_OF_ADDRESS];
  704. if(! DoBlockingRequest(BRIDGE_IOCTL_GET_MAC_ADDRESS, NULL, 0L, addr, sizeof(addr), NULL) )
  705. {
  706. printf("Attempt to query MAC address failed: ");
  707. PrintError( GetLastError() );
  708. }
  709. else
  710. {
  711. printf( "Bridge MAC address is %02x-%02x-%02x-%02x-%02x-%02x\n", addr[0], addr[1],
  712. addr[2], addr[3], addr[4], addr[5] );
  713. }
  714. }
  715. else if( _stricmp(command, "onretain") == 0 )
  716. {
  717. if(! DoBlockingRequest(BRIDGE_IOCTL_RETAIN_PACKETS, NULL, 0L, NULL, 0L, NULL) )
  718. {
  719. printf("Attempt to turn ON packet retention failed: ");
  720. PrintError( GetLastError() );
  721. }
  722. else
  723. {
  724. printf("Packet retention ENABLED.\n");
  725. }
  726. }
  727. else if( _stricmp(command, "offretain") == 0 )
  728. {
  729. if(! DoBlockingRequest(BRIDGE_IOCTL_NO_RETAIN_PACKETS, NULL, 0L, NULL, 0L, NULL) )
  730. {
  731. printf("Attempt to turn OFF packet retention failed: ");
  732. PrintError( GetLastError() );
  733. }
  734. else
  735. {
  736. printf("Packet retention DISABLED.\n");
  737. }
  738. }
  739. else if( _stricmp(command, "packetstats") == 0 )
  740. {
  741. BRIDGE_ADAPTER_HANDLE Handle;
  742. if( ! ReadHexPtrArg(inbuf, &Handle) )
  743. {
  744. BRIDGE_PACKET_STATISTICS Stats;
  745. if(! DoBlockingRequest(BRIDGE_IOCTL_GET_PACKET_STATS, NULL, 0L, &Stats, sizeof(Stats), NULL) )
  746. {
  747. printf("Attempt to retrieve global packet statistics failed: ");
  748. PrintError( GetLastError() );
  749. }
  750. else
  751. {
  752. PrintPacketStats(&Stats);
  753. }
  754. }
  755. else
  756. {
  757. BRIDGE_ADAPTER_PACKET_STATISTICS Stats;
  758. if(! DoBlockingRequest(BRIDGE_IOCTL_GET_ADAPTER_PACKET_STATS, &Handle, sizeof(Handle), &Stats, sizeof(Stats), NULL) )
  759. {
  760. printf("Attempt to retrieve packet statistics for adapter %p failed: ", Handle);
  761. PrintError( GetLastError() );
  762. }
  763. else
  764. {
  765. PrintAdapterPacketStats(&Stats);
  766. }
  767. }
  768. }
  769. else if( _stricmp(command, "bufferstats") == 0 )
  770. {
  771. BRIDGE_BUFFER_STATISTICS Stats;
  772. if(! DoBlockingRequest(BRIDGE_IOCTL_GET_BUFFER_STATS, NULL, 0L, &Stats, sizeof(Stats), NULL) )
  773. {
  774. printf("Attempt to retrieve buffer statistics failed: ");
  775. PrintError( GetLastError() );
  776. }
  777. else
  778. {
  779. PrintBufferStats(&Stats);
  780. }
  781. }
  782. else if( _stricmp(command, "stainfo") == 0 )
  783. {
  784. BRIDGE_ADAPTER_HANDLE Handle;
  785. if( ! ReadHexPtrArg(inbuf, &Handle) )
  786. {
  787. PrintSTAInfo();
  788. }
  789. else
  790. {
  791. PrintAdapterSTAInfo( Handle );
  792. }
  793. }
  794. else if( _stricmp( command, "quit" ) == 0 )
  795. {
  796. printf( "Signalling an exit...\n" );
  797. if( ! SetEvent( gThreadQuitEvent ) )
  798. {
  799. printf( "Couldn't signal an event: " );
  800. PrintError( GetLastError() );
  801. return;
  802. }
  803. bQuit = TRUE;
  804. }
  805. else
  806. {
  807. // Print a list of commands to help the user
  808. printf( "\n\nSupported commands:\n\n" );
  809. printf( "ENUM - Enumerates adapters\n" );
  810. printf( "DEVICENAME <handle> - Retrieves the device name of the indicated adapter\n" );
  811. printf( "FRIENDLYNAME <handle> - Retrieves the friendly name of the indicated adapter\n" );
  812. printf( "TABLE <handle> - Prints the forwarding table for the indicated adapter\n" );
  813. printf( "MAC - Prints the bridge's MAC address\n" );
  814. printf( "ONRETAIN - Turns ON NIC packet retention\n" );
  815. printf( "OFFRETAIN - Turns OFF NIC packet retention\n" );
  816. printf( "PACKETSTATS [<handle>] - Retrieves packet-handling statistics for a particular\n" );
  817. printf( " adapter (or global data if no adapter handle is\n" );
  818. printf( " provided)\n" );
  819. printf( "BUFFERSTATS - Retrieves buffer-management statistics\n" );
  820. printf( "STAINFO [<handle>] - Retrieves STA info for a particular adapter (or global\n" );
  821. printf( " info if no adapter handle is provided)\n" );
  822. printf( "QUIT - Exits\n\n" );
  823. }
  824. }
  825. CloseHandle( gBridgeDevice );
  826. }