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.

817 lines
21 KiB

  1. /*
  2. Module Name:
  3. btest.c
  4. Abstract:
  5. This module sends sample BINL packets to the BINL server of your choice.
  6. -b Use broadcast rather than directed datagram to <ServerName>
  7. -s <Servername> To specify a BINL server of your choice. Default is COLINW2
  8. Author:
  9. Colin Watson Apr 29 1997
  10. Revision History:
  11. */
  12. #include <binl.h>
  13. #pragma hdrstop
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <time.h>
  17. #include <tdiinfo.h>
  18. #include <wsipx.h>
  19. #include <wsnwlink.h>
  20. #include <nb30.h>
  21. #include <binldef.h>
  22. #define MAX_MSGLEN 80
  23. #define MAX_ADDLEN 80
  24. #define MAX_MSLOTNAME 80
  25. typedef struct _OPTION2 {
  26. BYTE OptionType;
  27. BYTE OptionLength;
  28. BYTE OptionValue[];
  29. } OPTION2, *POPTION2, *LPOPTION2;
  30. BOOL __stdcall
  31. CtrlCHandler (
  32. DWORD dwEvent
  33. );
  34. void __stdcall
  35. Udp (
  36. );
  37. void __stdcall
  38. Usage (
  39. CHAR *pszProgramName
  40. );
  41. void __stdcall
  42. PrintError (
  43. LPSTR lpszRoutine,
  44. LPSTR lpszCallName,
  45. DWORD dwError
  46. );
  47. void __stdcall
  48. DoStartup ( void );
  49. void __stdcall
  50. DoCleanup ( void );
  51. VOID
  52. GetHardwareAddress(
  53. PUCHAR Address
  54. );
  55. VOID
  56. DumpMessage(
  57. LPDHCP_MESSAGE BinlMessage
  58. );
  59. //
  60. // Global Variables
  61. //
  62. // If Startup was successful, fStarted is used to keep track.
  63. BOOL fStarted = FALSE;
  64. BOOL fBroadcast = FALSE;
  65. // Global socket descriptor
  66. SOCKET sock = INVALID_SOCKET;
  67. LPSTR ServerName = "COLINW2";
  68. ULONG ServerAddress;
  69. ULONG ClientAddress;
  70. void __cdecl
  71. main (
  72. INT argc,
  73. CHAR **argv
  74. )
  75. {
  76. int i;
  77. //
  78. // Install the CTRL+BREAK Handler
  79. //
  80. if ( FALSE == SetConsoleCtrlHandler ( (PHANDLER_ROUTINE) CtrlCHandler,
  81. TRUE
  82. ) ){
  83. PrintError ( "main", "SetConsoleCtrlHandler", GetLastError ( ) );
  84. }
  85. //
  86. // allow the user to override settings with command line switches
  87. //
  88. for ( i = 1; i < argc; i++ )
  89. {
  90. if ( ( *argv[i] == '-' ) || ( *argv[i] == '/' ) )
  91. {
  92. switch ( tolower ( *( argv[i]+1 ) ) )
  93. {
  94. //
  95. // Broadcast
  96. //
  97. case 'b':
  98. fBroadcast = TRUE;
  99. break;
  100. //
  101. // ServerName.
  102. //
  103. case 's':
  104. ServerName = argv[++i];
  105. break;
  106. //
  107. // Help.
  108. //
  109. case 'h':
  110. case '?':
  111. default:
  112. Usage ( argv[0] );
  113. }
  114. }
  115. else
  116. //
  117. // Help.
  118. //
  119. Usage ( argv[0] );
  120. }
  121. //
  122. // Print a Summary of the switches specfied
  123. // Helpful for debugging
  124. //
  125. fprintf ( stdout, "SUMMARY:\n" );
  126. if (fBroadcast) {
  127. fprintf ( stdout, "Broadcast test\n" );
  128. } else {
  129. fprintf ( stdout, "Unicast to BINL server %s\n", ServerName );
  130. }
  131. DoStartup ( );
  132. Udp();
  133. return;
  134. }
  135. //
  136. // CtrlCHandler () intercepts the CTRL+BREAK or CTRL+C events and calls the
  137. // cleanup routines.
  138. //
  139. BOOL __stdcall
  140. CtrlCHandler (
  141. DWORD dwEvent
  142. )
  143. {
  144. if ( ( CTRL_C_EVENT == dwEvent ) || ( CTRL_BREAK_EVENT == dwEvent ) )
  145. {
  146. DoCleanup ( );
  147. }
  148. return FALSE;
  149. }
  150. void __stdcall
  151. Discover(
  152. )
  153. {
  154. // IP address structures needed to fill the source and destination
  155. // addresses.
  156. SOCKADDR_IN saUdpServ, saUdpCli;
  157. INT err;
  158. DWORD nSize;
  159. UCHAR MessageBuffer[DHCP_MESSAGE_SIZE];
  160. PDHCP_MESSAGE Message = (PDHCP_MESSAGE)&MessageBuffer[0];
  161. // Data used for building Messages
  162. LPOPTION Option;
  163. UCHAR MagicCookie[] = {DHCP_MAGIC_COOKIE_BYTE1,
  164. DHCP_MAGIC_COOKIE_BYTE2,
  165. DHCP_MAGIC_COOKIE_BYTE3,
  166. DHCP_MAGIC_COOKIE_BYTE4};
  167. #define COOKIESIZE (4)
  168. OPTION2 DiscoverOption = {OPTION_MESSAGE_TYPE, 1, DHCP_DISCOVER_MESSAGE};
  169. #define DISCOVEROPTIONSIZE (DiscoverOption.OptionLength + 2)
  170. OPTION2 ClientOption = {OPTION_CLIENT_CLASS_INFO,9,"PXEClient"};
  171. // Size must ignore null at end of the string.
  172. #define CLIENTOPTIONSIZE (ClientOption.OptionLength + 2)
  173. OPTION2 NITOption = {OPTION_NETWORK_INTERFACE_TYPE,3,1,2,0};
  174. // Size must ignore null at end of the string.
  175. #define NITOPTIONSIZE (NITOption.OptionLength + 2)
  176. OPTION2 SAOption = {OPTION_SYSTEM_ARCHITECTURE,1,0};
  177. // Size must ignore null at end of the string.
  178. #define SAOPTIONSIZE (SAOption.OptionLength + 2)
  179. OPTION2 EndOption = {OPTION_END,0};
  180. // Size must ignore null at end of the string.
  181. #define ENDOPTIONSIZE (1)
  182. do {
  183. sendagain:
  184. //
  185. // Fill an IP address structure, to send an IP broadcast.
  186. //
  187. saUdpServ.sin_family = AF_INET;
  188. if (fBroadcast) {
  189. saUdpServ.sin_addr.s_addr = htonl ( INADDR_BROADCAST );
  190. } else {
  191. saUdpServ.sin_addr.s_addr = ServerAddress;
  192. }
  193. saUdpServ.sin_port = htons ( DHCP_SERVR_PORT );
  194. // Practice with a dummy BINL Discover packet
  195. ZeroMemory(MessageBuffer, sizeof(MessageBuffer));
  196. Message->Operation = BOOT_REQUEST;
  197. Option = &Message->Option;
  198. GetHardwareAddress(Message->HardwareAddress);
  199. Message->HardwareAddressType = 1;
  200. Message->HardwareAddressLength = 6;
  201. Message->TransactionID = 0x12345678;
  202. memcpy(Option, &MagicCookie, COOKIESIZE);
  203. Option = (LPOPTION)((PUCHAR)Option + COOKIESIZE);
  204. memcpy(Option, &DiscoverOption, DISCOVEROPTIONSIZE);
  205. Option = (LPOPTION)((PUCHAR)Option + DISCOVEROPTIONSIZE);
  206. memcpy(Option, &ClientOption, CLIENTOPTIONSIZE);
  207. Option = (LPOPTION)((PUCHAR)Option + CLIENTOPTIONSIZE);
  208. memcpy(Option, &NITOption, NITOPTIONSIZE);
  209. Option = (LPOPTION)((PUCHAR)Option + NITOPTIONSIZE);
  210. memcpy(Option, &SAOption, SAOPTIONSIZE);
  211. Option = (LPOPTION)((PUCHAR)Option + SAOPTIONSIZE);
  212. memcpy(Option, &EndOption, ENDOPTIONSIZE);
  213. Option = (LPOPTION)((PUCHAR)Option + ENDOPTIONSIZE);
  214. err = sendto ( sock,
  215. (PUCHAR)Message,
  216. (PUCHAR)Option - (PUCHAR)Message,
  217. 0,
  218. (SOCKADDR *) &saUdpServ,
  219. sizeof ( SOCKADDR_IN )
  220. );
  221. if ( SOCKET_ERROR == err )
  222. {
  223. PrintError ( "Udp", "sendto", WSAGetLastError ( ) );
  224. }
  225. fprintf ( stdout, "%d bytes of data sent\n", err );
  226. Sleep(1000); // Give server a few seconds to respond.
  227. do {
  228. err = ioctlsocket( sock, FIONREAD, &nSize);
  229. if ( SOCKET_ERROR == err )
  230. {
  231. PrintError ( "Udp", "recvfrom", WSAGetLastError ( ) );
  232. }
  233. if (!nSize) {
  234. goto sendagain; // we have processed all the DHCP/BINL responses
  235. }
  236. //
  237. // receive a datagram on the bound port number.
  238. //
  239. nSize = sizeof ( SOCKADDR_IN );
  240. err = recvfrom ( sock,
  241. (PUCHAR)Message,
  242. DHCP_MESSAGE_SIZE,
  243. 0,
  244. (SOCKADDR FAR *) &saUdpCli,
  245. &nSize
  246. );
  247. if ( SOCKET_ERROR == err )
  248. {
  249. PrintError ( "Udp", "recvfrom", WSAGetLastError ( ) );
  250. }
  251. if (Message->TransactionID == 0x12345678) {
  252. goto processit;
  253. }
  254. } while ( 1 ); // while there are datagrams queued
  255. } while (1);
  256. processit:
  257. //
  258. // print the sender's information.
  259. //
  260. fprintf ( stdout, "A Udp Datagram of length %d bytes received from ", err );
  261. fprintf ( stdout, "\n\tIP Adress->%s ", inet_ntoa ( saUdpCli.sin_addr ) );
  262. fprintf ( stdout, "\n\tPort Number->%d\n", ntohs ( saUdpCli.sin_port ) );
  263. DumpMessage(Message);
  264. }
  265. void __stdcall
  266. Request(
  267. )
  268. {
  269. // IP address structures needed to fill the source and destination
  270. // addresses.
  271. SOCKADDR_IN saUdpServ, saUdpCli;
  272. INT err;
  273. DWORD nSize;
  274. UCHAR MessageBuffer[DHCP_MESSAGE_SIZE];
  275. PDHCP_MESSAGE Message = (PDHCP_MESSAGE)&MessageBuffer[0];
  276. // Data used for building Messages
  277. LPOPTION Option;
  278. UCHAR MagicCookie[] = {DHCP_MAGIC_COOKIE_BYTE1,
  279. DHCP_MAGIC_COOKIE_BYTE2,
  280. DHCP_MAGIC_COOKIE_BYTE3,
  281. DHCP_MAGIC_COOKIE_BYTE4};
  282. #define COOKIESIZE (4)
  283. OPTION2 RequestOption = {OPTION_MESSAGE_TYPE, 1, DHCP_REQUEST_MESSAGE};
  284. #define REQUESTOPTIONSIZE (RequestOption.OptionLength + 2)
  285. OPTION2 ClientOption = {OPTION_CLIENT_CLASS_INFO,9,"PXEClient"};
  286. // Size must ignore null at end of the string.
  287. #define CLIENTOPTIONSIZE (ClientOption.OptionLength + 2)
  288. OPTION2 NITOption = {OPTION_NETWORK_INTERFACE_TYPE,3,1,2,0};
  289. // Size must ignore null at end of the string.
  290. #define NITOPTIONSIZE (NITOption.OptionLength + 2)
  291. OPTION2 SAOption = {OPTION_SYSTEM_ARCHITECTURE,1,0};
  292. // Size must ignore null at end of the string.
  293. #define SAOPTIONSIZE (SAOption.OptionLength + 2)
  294. OPTION2 EndOption = {OPTION_END,0};
  295. // Size must ignore null at end of the string.
  296. #define ENDOPTIONSIZE (1)
  297. do {
  298. sendagain:
  299. //
  300. // Fill an IP address structure, to send an IP broadcast.
  301. //
  302. saUdpServ.sin_family = AF_INET;
  303. if (fBroadcast) {
  304. saUdpServ.sin_addr.s_addr = htonl ( INADDR_BROADCAST );
  305. } else {
  306. saUdpServ.sin_addr.s_addr = ServerAddress;
  307. }
  308. //saUdpServ.sin_port = htons ( BINL_DEFAULT_PORT );
  309. saUdpServ.sin_port = htons ( 0xaee8 );
  310. // Practice with a dummy BINL Request packet
  311. ZeroMemory(MessageBuffer, sizeof(MessageBuffer));
  312. Message->Operation = BOOT_REQUEST;
  313. Option = &Message->Option;
  314. GetHardwareAddress(Message->HardwareAddress);
  315. Message->HardwareAddressType = 1;
  316. Message->HardwareAddressLength = 6;
  317. Message->TransactionID = 0x56781234;
  318. Message->YourIpAddress = ClientAddress;
  319. memcpy(Option, &MagicCookie, COOKIESIZE);
  320. Option = (LPOPTION)((PUCHAR)Option + COOKIESIZE);
  321. memcpy(Option, &RequestOption, REQUESTOPTIONSIZE);
  322. Option = (LPOPTION)((PUCHAR)Option + REQUESTOPTIONSIZE);
  323. memcpy(Option, &ClientOption, CLIENTOPTIONSIZE);
  324. Option = (LPOPTION)((PUCHAR)Option + CLIENTOPTIONSIZE);
  325. memcpy(Option, &NITOption, NITOPTIONSIZE);
  326. Option = (LPOPTION)((PUCHAR)Option + NITOPTIONSIZE);
  327. memcpy(Option, &SAOption, SAOPTIONSIZE);
  328. Option = (LPOPTION)((PUCHAR)Option + SAOPTIONSIZE);
  329. memcpy(Option, &EndOption, ENDOPTIONSIZE);
  330. Option = (LPOPTION)((PUCHAR)Option + ENDOPTIONSIZE);
  331. err = sendto ( sock,
  332. (PUCHAR)Message,
  333. (PUCHAR)Option - (PUCHAR)Message,
  334. 0,
  335. (SOCKADDR *) &saUdpServ,
  336. sizeof ( SOCKADDR_IN )
  337. );
  338. if ( SOCKET_ERROR == err )
  339. {
  340. PrintError ( "Udp", "sendto", WSAGetLastError ( ) );
  341. }
  342. fprintf ( stdout, "%d bytes of data sent\n", err );
  343. Sleep(1000); // Give server a few seconds to respond.
  344. do {
  345. err = ioctlsocket( sock, FIONREAD, &nSize);
  346. if ( SOCKET_ERROR == err )
  347. {
  348. PrintError ( "Udp", "recvfrom", WSAGetLastError ( ) );
  349. }
  350. if (!nSize) {
  351. goto sendagain; // we have processed all the DHCP/BINL responses
  352. }
  353. //
  354. // receive a datagram on the bound port number.
  355. //
  356. nSize = sizeof ( SOCKADDR_IN );
  357. err = recvfrom ( sock,
  358. (PUCHAR)Message,
  359. DHCP_MESSAGE_SIZE,
  360. 0,
  361. (SOCKADDR FAR *) &saUdpCli,
  362. &nSize
  363. );
  364. if ( SOCKET_ERROR == err )
  365. {
  366. PrintError ( "Udp", "recvfrom", WSAGetLastError ( ) );
  367. }
  368. if (Message->TransactionID == 0x56781234) {
  369. goto processit;
  370. }
  371. } while ( 1 ); // while there are datagrams queued
  372. } while (1);
  373. processit:
  374. //
  375. // print the sender's information.
  376. //
  377. fprintf ( stdout, "A Udp Datagram of length %d bytes received from ", err );
  378. fprintf ( stdout, "\n\tIP Adress->%s ", inet_ntoa ( saUdpCli.sin_addr ) );
  379. fprintf ( stdout, "\n\tPort Number->%d\n", ntohs ( saUdpCli.sin_port ) );
  380. DumpMessage(Message);
  381. }
  382. void __stdcall
  383. Udp(
  384. )
  385. {
  386. INT err;
  387. LPHOSTENT pServerHostEntry;
  388. char MyName[80];
  389. // IP address structures needed to fill the source and destination
  390. // addresses.
  391. SOCKADDR_IN saUdpServ, saUdpCli;
  392. //
  393. // Initialize the global socket descriptor.
  394. //
  395. sock = socket ( AF_INET, SOCK_DGRAM, 0 );
  396. if ( INVALID_SOCKET == sock)
  397. {
  398. PrintError ( "Udp", "socket", WSAGetLastError() );
  399. }
  400. if (fBroadcast) {
  401. err = setsockopt ( sock,
  402. SOL_SOCKET,
  403. SO_BROADCAST,
  404. (CHAR *) &fBroadcast,
  405. sizeof ( BOOL )
  406. );
  407. if ( SOCKET_ERROR == err )
  408. {
  409. PrintError ( "Udp", "setsockopt", WSAGetLastError ( ) );
  410. }
  411. } else {
  412. // Convert ServerName to an IP address
  413. ServerAddress = inet_addr(ServerName); // Dotted form of address
  414. if ((ServerAddress == INADDR_NONE) &&
  415. (memcmp(ServerName, "255.255.255.255", sizeof("255.255.255.255")))) {
  416. // must be a servername
  417. pServerHostEntry = gethostbyname(ServerName);
  418. if (pServerHostEntry) {
  419. ServerAddress = *((PULONG)(pServerHostEntry->h_addr));
  420. } else {
  421. PrintError ( "Udp", "gethostbyname", WSAGetLastError ( ) );
  422. return;
  423. }
  424. }
  425. }
  426. //
  427. // bind to a local socket and an interface.
  428. //
  429. saUdpCli.sin_family = AF_INET;
  430. saUdpCli.sin_addr.s_addr = htonl ( INADDR_ANY );
  431. saUdpCli.sin_port = htons ( DHCP_CLIENT_PORT );
  432. err = bind ( sock, (SOCKADDR *) &saUdpCli, sizeof (SOCKADDR_IN) );
  433. if ( SOCKET_ERROR == err )
  434. {
  435. PrintError ( "Udp", "bind", WSAGetLastError ( ) );
  436. }
  437. // Find my (clients) IP address.
  438. if (gethostname(MyName, sizeof(MyName)) != SOCKET_ERROR ){
  439. PHOSTENT Host;
  440. Host = gethostbyname(MyName);
  441. if (Host) {
  442. ClientAddress = *(PDHCP_IP_ADDRESS)Host->h_addr;
  443. }
  444. }
  445. Discover();
  446. Request();
  447. //
  448. // Call the cleanup routine.
  449. //
  450. DoCleanup ( );
  451. return;
  452. }
  453. //
  454. // Usage () lists the available command line options.
  455. //
  456. void __stdcall
  457. Usage (
  458. CHAR *pszProgramName
  459. )
  460. {
  461. fprintf ( stderr, "Usage: %s\n", pszProgramName );
  462. fprintf ( stderr, "\t-b Use broadcast to DHCP/BINL socket\n" );
  463. fprintf ( stderr,
  464. "\t-s <ServerName>, Use directed datagram to ServerName default - COLINW2)\n" );
  465. exit ( 1 );
  466. }
  467. //
  468. // PrintError () is a function available globally for printing the error and
  469. // doing the cleanup.
  470. //
  471. void __stdcall
  472. PrintError (
  473. LPSTR lpszRoutine,
  474. LPSTR lpszCallName,
  475. DWORD dwError
  476. )
  477. {
  478. fprintf ( stderr,
  479. "The Call to %s() in routine() %s failed with error %d\n",
  480. lpszCallName,
  481. lpszRoutine,
  482. dwError
  483. );
  484. DoCleanup ( );
  485. exit ( 1 );
  486. }
  487. //
  488. // DoStartup () initializes the Winsock DLL with Winsock version 1.1
  489. //
  490. void __stdcall
  491. DoStartup ( void )
  492. {
  493. WSADATA wsaData;
  494. INT iRetVal;
  495. iRetVal = WSAStartup ( MAKEWORD ( 1,1 ), &wsaData );
  496. if ( 0 != iRetVal)
  497. {
  498. PrintError ( "DoStartup", "WSAStartup", iRetVal );
  499. }
  500. //
  501. // Set the global flag.
  502. //
  503. fStarted = TRUE;
  504. return;
  505. }
  506. //
  507. // DoCleanup () will close the global socket which was opened successfully by
  508. // a call to socket (). Additionally, it will call WSACleanup (), if a call
  509. // to WSAStartup () was made successfully.
  510. //
  511. void __stdcall
  512. DoCleanup ( void )
  513. {
  514. if ( INVALID_SOCKET != sock )
  515. {
  516. closesocket ( sock );
  517. }
  518. if ( TRUE == fStarted )
  519. {
  520. WSACleanup ( );
  521. }
  522. fprintf ( stdout, "DONE\n" );
  523. return;
  524. }
  525. #define ClearNcb( PNCB ) { \
  526. ZeroMemory( PNCB , sizeof (NCB) ); \
  527. MoveMemory( (PNCB)->ncb_name, SPACES, sizeof(SPACES)-1 );\
  528. MoveMemory( (PNCB)->ncb_callname, SPACES, sizeof(SPACES)-1 );\
  529. }
  530. #define SPACES " "
  531. VOID
  532. GetHardwareAddress(
  533. PUCHAR Address
  534. ) {
  535. NCB myncb;
  536. ADAPTER_STATUS adapterstatus;
  537. UCHAR lanNumber;
  538. LANA_ENUM Enum;
  539. ClearNcb( &myncb );
  540. myncb.ncb_command = NCBENUM;
  541. myncb.ncb_lana_num = 0;
  542. myncb.ncb_length = sizeof(Enum);
  543. myncb.ncb_buffer = (PUCHAR)&Enum;
  544. Netbios( &myncb );
  545. if (( myncb.ncb_retcode != NRC_GOODRET ) ||
  546. ( !Enum.length )) {
  547. return;
  548. }
  549. lanNumber = Enum.lana[0];
  550. ClearNcb( &myncb );
  551. myncb.ncb_command = NCBRESET;
  552. myncb.ncb_lsn = 0; // Request resources
  553. myncb.ncb_lana_num = lanNumber;
  554. myncb.ncb_callname[0] = 0; // 16 sessions
  555. myncb.ncb_callname[1] = 0; // 16 commands
  556. myncb.ncb_callname[2] = 0; // 8 names
  557. Netbios( &myncb );
  558. if ( myncb.ncb_retcode != NRC_GOODRET ) return;
  559. ClearNcb( &myncb );
  560. myncb.ncb_command = NCBASTAT;
  561. myncb.ncb_lana_num = lanNumber;
  562. myncb.ncb_buffer = (PUCHAR)&adapterstatus;
  563. myncb.ncb_length = sizeof(adapterstatus);
  564. myncb.ncb_callname[0] = '*';
  565. Netbios( &myncb );
  566. if ( myncb.ncb_retcode != NRC_GOODRET ) return;
  567. CopyMemory(Address, &adapterstatus.adapter_address[0], 6);
  568. }
  569. VOID
  570. DumpMessage(
  571. LPDHCP_MESSAGE BinlMessage
  572. )
  573. /*++
  574. Routine Description:
  575. This function dumps a DHCP packet in human readable form.
  576. Arguments:
  577. BinlMessage - A pointer to a DHCP message.
  578. Return Value:
  579. None.
  580. --*/
  581. {
  582. LPOPTION option;
  583. BYTE i;
  584. fprintf ( stdout,"Binl message: \n\n");
  585. fprintf ( stdout,"Operation :");
  586. if ( BinlMessage->Operation == BOOT_REQUEST ) {
  587. fprintf ( stdout, "BootRequest\n");
  588. } else if ( BinlMessage->Operation == BOOT_REPLY ) {
  589. fprintf ( stdout, "BootReply\n");
  590. } else {
  591. fprintf ( stdout, "Unknown\n");
  592. }
  593. fprintf ( stdout,"Hardware Address type : %d\n", BinlMessage->HardwareAddressType);
  594. fprintf ( stdout,"Hardware Address Length: %d\n", BinlMessage->HardwareAddressLength);
  595. fprintf ( stdout,"Hop Count : %d\n", BinlMessage->HopCount );
  596. fprintf ( stdout,"Transaction ID : %lx\n", BinlMessage->TransactionID );
  597. fprintf ( stdout,"Seconds Since Boot : %d\n", BinlMessage->SecondsSinceBoot );
  598. fprintf ( stdout,"Client IP Address : " );
  599. fprintf ( stdout,"%s\n",
  600. inet_ntoa(*(struct in_addr *)&BinlMessage->ClientIpAddress ) );
  601. fprintf ( stdout,"Your IP Address : " );
  602. fprintf ( stdout,"%s\n",
  603. inet_ntoa(*(struct in_addr *)&BinlMessage->YourIpAddress ) );
  604. fprintf ( stdout,"Server IP Address : " );
  605. fprintf ( stdout,"%s\n",
  606. inet_ntoa(*(struct in_addr *)&BinlMessage->BootstrapServerAddress ) );
  607. fprintf ( stdout,"Relay Agent IP Address : " );
  608. fprintf ( stdout,"%s\n",
  609. inet_ntoa(*(struct in_addr *)&BinlMessage->RelayAgentIpAddress ) );
  610. fprintf ( stdout,"Hardware Address : ");
  611. for ( i = 0; i < BinlMessage->HardwareAddressLength; i++ ) {
  612. fprintf ( stdout,"%2.2x", BinlMessage->HardwareAddress[i] );
  613. }
  614. if (BinlMessage->HostName[0]) {
  615. fprintf( stdout, "\nHostName \"%s\"\n", BinlMessage->HostName);
  616. }
  617. if (BinlMessage->BootFileName[0]) {
  618. fprintf( stdout, "BootFileName \"%s\"\n", BinlMessage->BootFileName);
  619. }
  620. option = &BinlMessage->Option;
  621. fprintf ( stdout,"\nMagic Cookie: ");
  622. for ( i = 0; i < 4; i++ ) {
  623. fprintf ( stdout,"%d ", *((LPBYTE)option)++ );
  624. }
  625. fprintf ( stdout,"\n\n");
  626. fprintf ( stdout,"Options:\n");
  627. while ( option->OptionType != 255 ) {
  628. fprintf ( stdout,"\tType = %d ", option->OptionType );
  629. for ( i = 0; i < option->OptionLength; i++ ) {
  630. fprintf ( stdout,"%2.2x", option->OptionValue[i] );
  631. }
  632. fprintf ( stdout,"\n");
  633. if ( option->OptionType == OPTION_PAD ||
  634. option->OptionType == OPTION_END ) {
  635. option = (LPOPTION)( (LPBYTE)(option) + 1);
  636. } else {
  637. option = (LPOPTION)( (LPBYTE)(option) + option->OptionLength + 2);
  638. }
  639. if ( (LPBYTE)option - (LPBYTE)BinlMessage > DHCP_MESSAGE_SIZE ) {
  640. fprintf ( stdout,"End of message, but no trailer found!\n");
  641. break;
  642. }
  643. }
  644. }