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.

1098 lines
24 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. dhcploc.c
  5. Abstract:
  6. This apps is used to detect the rogue DHCP server on a subnet.
  7. To build, 'nmake UMTEST=dhcpcli'
  8. Author:
  9. Madan Appiah (madana) 21-Oct-1993
  10. Environment:
  11. User Mode - Win32
  12. Revision History:
  13. Oct 1996, (a-martih) Martin Holladay
  14. Corrected AV bug when passed an unknown cmd-line parameter.
  15. --*/
  16. #include <dhcpcli.h>
  17. #include <conio.h>
  18. #include <locmsg.h>
  19. #include <time.h>
  20. #include <lmcons.h>
  21. #include <lmmsg.h>
  22. #define RECEIVE_TIMEOUT 5 // in secs. 5 secs
  23. #define THREAD_TERMINATION_TIMEOUT 10000 // in msecs. 10 secs
  24. #define SOCKET_RECEIVE_BUFFER_SIZE 1024 * 4 // 4K max.
  25. #define AUTH_SERVERS_MAX 64
  26. #define SMALL_BUFFER_SIZE 32
  27. #define ALERT_INTERVAL 5 * 60 // 5 mins
  28. #define ALERT_MESSAGE_LENGTH 256
  29. #define MAX_ALERT_NAMES 256
  30. DWORD GlobalAuthServers[AUTH_SERVERS_MAX];
  31. BOOL GlobalNoAuthPrint = FALSE;
  32. DWORD GlobalAuthServersCount = 0;
  33. HANDLE GlobalRecvThreadHandle = NULL;
  34. BOOL GlobalTerminate = FALSE;
  35. DWORD GlobalIpAddress = 0;
  36. time_t GlobalLastAlertTime = 0;
  37. DWORD GlobalAlertInterval = ALERT_INTERVAL;
  38. LPWSTR GlobalAlertNames[MAX_ALERT_NAMES];
  39. DWORD GlobalAlertNamesCount = 0;
  40. #if DBG
  41. VOID
  42. DhcpPrintRoutine(
  43. IN DWORD DebugFlag,
  44. IN LPSTR Format,
  45. ...
  46. )
  47. {
  48. #define MAX_PRINTF_LEN 1024 // Arbitrary.
  49. va_list arglist;
  50. char OutputBuffer[MAX_PRINTF_LEN];
  51. ULONG length = 0;
  52. //
  53. // Put a the information requested by the caller onto the line
  54. //
  55. va_start(arglist, Format);
  56. length += (ULONG) vsprintf(&OutputBuffer[length], Format, arglist);
  57. va_end(arglist);
  58. DhcpAssert(length <= MAX_PRINTF_LEN);
  59. //
  60. // Output to the debug terminal,
  61. //
  62. printf( "%s", OutputBuffer);
  63. }
  64. #endif // DBG
  65. DWORD
  66. OpenSocket(
  67. SOCKET *Socket,
  68. DWORD IpAddress,
  69. DWORD Port
  70. )
  71. {
  72. DWORD Error;
  73. SOCKET Sock;
  74. DWORD OptValue;
  75. struct sockaddr_in SocketName;
  76. //
  77. // Create a socket
  78. //
  79. Sock = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
  80. if ( Sock == INVALID_SOCKET ) {
  81. Error = WSAGetLastError();
  82. goto Cleanup;
  83. }
  84. //
  85. // Make the socket share-able
  86. //
  87. OptValue = TRUE;
  88. Error = setsockopt(
  89. Sock,
  90. SOL_SOCKET,
  91. SO_REUSEADDR,
  92. (LPBYTE)&OptValue,
  93. sizeof(OptValue) );
  94. if ( Error != ERROR_SUCCESS ) {
  95. Error = WSAGetLastError();
  96. goto Cleanup;
  97. }
  98. OptValue = TRUE;
  99. Error = setsockopt(
  100. Sock,
  101. SOL_SOCKET,
  102. SO_BROADCAST,
  103. (LPBYTE)&OptValue,
  104. sizeof(OptValue) );
  105. if ( Error != ERROR_SUCCESS ) {
  106. Error = WSAGetLastError();
  107. goto Cleanup;
  108. }
  109. OptValue = SOCKET_RECEIVE_BUFFER_SIZE;
  110. Error = setsockopt(
  111. Sock,
  112. SOL_SOCKET,
  113. SO_RCVBUF,
  114. (LPBYTE)&OptValue,
  115. sizeof(OptValue) );
  116. if ( Error != ERROR_SUCCESS ) {
  117. Error = WSAGetLastError();
  118. goto Cleanup;
  119. }
  120. SocketName.sin_family = PF_INET;
  121. SocketName.sin_port = htons( (unsigned short)Port );
  122. SocketName.sin_addr.s_addr = IpAddress;
  123. RtlZeroMemory( SocketName.sin_zero, 8);
  124. //
  125. // Bind this socket to the DHCP server port
  126. //
  127. Error = bind(
  128. Sock,
  129. (struct sockaddr FAR *)&SocketName,
  130. sizeof( SocketName )
  131. );
  132. if ( Error != ERROR_SUCCESS ) {
  133. Error = WSAGetLastError();
  134. goto Cleanup;
  135. }
  136. *Socket = Sock;
  137. Error = ERROR_SUCCESS;
  138. Cleanup:
  139. if( Error != ERROR_SUCCESS ) {
  140. //
  141. // if we aren't successful, close the socket if it is opened.
  142. //
  143. if( Sock != INVALID_SOCKET ) {
  144. closesocket( Sock );
  145. }
  146. }
  147. return( Error );
  148. }
  149. BOOL
  150. IsAuthServer(
  151. DWORD IpAddress
  152. )
  153. {
  154. DWORD i;
  155. for( i = 0; i < GlobalAuthServersCount; i++ ) {
  156. if( IpAddress == GlobalAuthServers[i] ){
  157. return( TRUE );
  158. }
  159. }
  160. return( FALSE );
  161. }
  162. VOID
  163. ExtractOptions1(
  164. POPTION Option,
  165. PDHCP_OPTIONS DhcpOptions,
  166. DWORD MessageSize
  167. )
  168. {
  169. POPTION start = Option;
  170. POPTION nextOption;
  171. LPBYTE MagicCookie;
  172. //
  173. // initialize option data.
  174. //
  175. RtlZeroMemory( DhcpOptions, sizeof( DHCP_OPTIONS ) );
  176. if ( MessageSize == 0 ) {
  177. return;
  178. }
  179. //
  180. // check magic cookie.
  181. //
  182. MagicCookie = (LPBYTE) Option;
  183. if( (*MagicCookie != (BYTE)DHCP_MAGIC_COOKIE_BYTE1) ||
  184. (*(MagicCookie+1) != (BYTE)DHCP_MAGIC_COOKIE_BYTE2) ||
  185. (*(MagicCookie+2) != (BYTE)DHCP_MAGIC_COOKIE_BYTE3) ||
  186. (*(MagicCookie+3) != (BYTE)DHCP_MAGIC_COOKIE_BYTE4)) {
  187. return;
  188. }
  189. Option = (LPOPTION) (MagicCookie + 4);
  190. while ( Option->OptionType != OPTION_END ) {
  191. if ( Option->OptionType == OPTION_PAD ||
  192. Option->OptionType == OPTION_END ) {
  193. nextOption = (LPOPTION)( (LPBYTE)(Option) + 1);
  194. } else {
  195. nextOption = (LPOPTION)( (LPBYTE)(Option) + Option->OptionLength + 2);
  196. }
  197. //
  198. // Make sure that we don't walk off the edge of the message, due
  199. // to a forgotten OPTION_END option.
  200. //
  201. if ((PCHAR)nextOption - (PCHAR)start > (long)MessageSize ) {
  202. return;
  203. }
  204. switch ( Option->OptionType ) {
  205. case OPTION_MESSAGE_TYPE:
  206. DhcpAssert( Option->OptionLength == sizeof(BYTE) );
  207. DhcpOptions->MessageType =
  208. (BYTE UNALIGNED *)&Option->OptionValue;
  209. break;
  210. case OPTION_SUBNET_MASK:
  211. DhcpAssert( Option->OptionLength == sizeof(DWORD) );
  212. DhcpOptions->SubnetMask =
  213. (DHCP_IP_ADDRESS UNALIGNED *)&Option->OptionValue;
  214. break;
  215. case OPTION_LEASE_TIME:
  216. DhcpAssert( Option->OptionLength == sizeof(DWORD) );
  217. DhcpOptions->LeaseTime =
  218. (DWORD UNALIGNED *)&Option->OptionValue;
  219. break;
  220. case OPTION_SERVER_IDENTIFIER:
  221. DhcpAssert( Option->OptionLength == sizeof(DWORD) );
  222. DhcpOptions->ServerIdentifier =
  223. (DHCP_IP_ADDRESS UNALIGNED *)&Option->OptionValue;
  224. break;
  225. case OPTION_RENEWAL_TIME:
  226. DhcpAssert( Option->OptionLength == sizeof(DWORD) );
  227. DhcpOptions->T1Time =
  228. (DWORD UNALIGNED *)&Option->OptionValue;
  229. break;
  230. case OPTION_REBIND_TIME:
  231. DhcpAssert( Option->OptionLength == sizeof(DWORD) );
  232. DhcpOptions->T2Time =
  233. (DWORD UNALIGNED *)&Option->OptionValue;
  234. break;
  235. default:
  236. break;
  237. }
  238. Option = nextOption;
  239. }
  240. return;
  241. }
  242. DWORD
  243. SendDiscovery(
  244. VOID
  245. )
  246. {
  247. DWORD Error;
  248. BYTE MessageBuffer[DHCP_SEND_MESSAGE_SIZE];
  249. PDHCP_MESSAGE dhcpMessage = (PDHCP_MESSAGE)MessageBuffer;
  250. LPOPTION option;
  251. LPBYTE OptionEnd;
  252. BYTE value;
  253. BYTE *HardwareAddress = "123456";
  254. BYTE HardwareAddressLength = 6;
  255. LPSTR HostName = "ROGUE";
  256. SOCKET Sock;
  257. struct sockaddr_in socketName;
  258. DWORD i;
  259. //
  260. // prepare message.
  261. //
  262. RtlZeroMemory( dhcpMessage, DHCP_SEND_MESSAGE_SIZE );
  263. dhcpMessage->Operation = BOOT_REQUEST;
  264. dhcpMessage->HardwareAddressType = 1;
  265. //
  266. // Transaction ID is filled in during send
  267. //
  268. dhcpMessage->SecondsSinceBoot = 60; // random value ??
  269. dhcpMessage->Reserved = htons(DHCP_BROADCAST);
  270. memcpy(
  271. dhcpMessage->HardwareAddress,
  272. HardwareAddress,
  273. HardwareAddressLength
  274. );
  275. dhcpMessage->HardwareAddressLength = (BYTE)HardwareAddressLength;
  276. option = &dhcpMessage->Option;
  277. OptionEnd = (LPBYTE)dhcpMessage + DHCP_SEND_MESSAGE_SIZE;
  278. //
  279. // always add magic cookie first
  280. //
  281. option = (LPOPTION) DhcpAppendMagicCookie( (LPBYTE) option, OptionEnd );
  282. value = DHCP_DISCOVER_MESSAGE;
  283. option = DhcpAppendOption(
  284. option,
  285. OPTION_MESSAGE_TYPE,
  286. &value,
  287. 1,
  288. OptionEnd );
  289. //
  290. // Add client ID Option.
  291. //
  292. option = DhcpAppendClientIDOption(
  293. option,
  294. 1,
  295. HardwareAddress,
  296. HardwareAddressLength,
  297. OptionEnd );
  298. //
  299. // add Host name and comment options.
  300. //
  301. option = DhcpAppendOption(
  302. option,
  303. OPTION_HOST_NAME,
  304. (LPBYTE)HostName,
  305. (BYTE)((strlen(HostName) + 1) * sizeof(CHAR)),
  306. OptionEnd );
  307. //
  308. // Add END option.
  309. //
  310. option = DhcpAppendOption( option, OPTION_END, NULL, 0, OptionEnd );
  311. //
  312. // Send the message
  313. //
  314. //
  315. // open socket.
  316. //
  317. Error = OpenSocket(
  318. &Sock,
  319. GlobalIpAddress,
  320. DHCP_SERVR_PORT );
  321. if( Error != ERROR_SUCCESS ) {
  322. printf("OpenReceiveSocket failed %ld.", Error );
  323. return( Error );
  324. }
  325. //
  326. // Initialize the outgoing address.
  327. //
  328. socketName.sin_family = PF_INET;
  329. socketName.sin_port = htons( DHCP_SERVR_PORT );
  330. socketName.sin_addr.s_addr = (DHCP_IP_ADDRESS)(INADDR_BROADCAST);
  331. for ( i = 0; i < 8 ; i++ ) {
  332. socketName.sin_zero[i] = 0;
  333. }
  334. Error = sendto(
  335. Sock,
  336. (PCHAR)MessageBuffer,
  337. DHCP_SEND_MESSAGE_SIZE,
  338. 0,
  339. (struct sockaddr *)&socketName,
  340. sizeof( struct sockaddr )
  341. );
  342. if ( Error == SOCKET_ERROR ) {
  343. Error = WSAGetLastError();
  344. printf("sendto failed %ld\n", Error );
  345. return( Error );
  346. }
  347. return( ERROR_SUCCESS );
  348. }
  349. VOID
  350. LogEvent(
  351. LPSTR MsgTypeString,
  352. LPSTR IpAddressString,
  353. LPSTR ServerAddressString
  354. )
  355. {
  356. HANDLE EventlogHandle;
  357. LPSTR Strings[3];
  358. //
  359. // open event registry.
  360. //
  361. EventlogHandle = RegisterEventSourceA(
  362. NULL,
  363. "DhcpTools" );
  364. if (EventlogHandle == NULL) {
  365. printf("RegisterEventSourceA failed %ld.", GetLastError() );
  366. return;
  367. }
  368. Strings[0] = MsgTypeString;
  369. Strings[1] = ServerAddressString;
  370. Strings[2] = IpAddressString;
  371. if( !ReportEventA(
  372. EventlogHandle,
  373. (WORD)EVENTLOG_INFORMATION_TYPE,
  374. 0, // event category
  375. DHCP_ROGUE_SERVER_MESSAGE,
  376. NULL,
  377. (WORD)3,
  378. 0,
  379. Strings,
  380. NULL
  381. ) ) {
  382. printf("ReportEventA failed %ld.", GetLastError() );
  383. }
  384. DeregisterEventSource(EventlogHandle);
  385. return;
  386. }
  387. VOID
  388. RaiseAlert(
  389. LPSTR MsgTypeString,
  390. LPSTR IpAddressString,
  391. LPSTR ServerAddressString
  392. )
  393. {
  394. time_t TimeNow;
  395. DWORD Error;
  396. TimeNow = time( NULL );
  397. if( TimeNow > (time_t)(GlobalLastAlertTime + GlobalAlertInterval) ) {
  398. WCHAR uIpAddressString[SMALL_BUFFER_SIZE];
  399. WCHAR uServerAddressString[SMALL_BUFFER_SIZE];
  400. WCHAR uMsgTypeString[SMALL_BUFFER_SIZE];
  401. DWORD i;
  402. LPWSTR MessageParams[3];
  403. WCHAR AlertMessage[ ALERT_MESSAGE_LENGTH ];
  404. DWORD MsgLength;
  405. MessageParams[0] =
  406. DhcpOemToUnicode( MsgTypeString, uMsgTypeString );
  407. MessageParams[1] =
  408. DhcpOemToUnicode( ServerAddressString, uServerAddressString );
  409. MessageParams[2] =
  410. DhcpOemToUnicode( IpAddressString, uIpAddressString );
  411. MsgLength = FormatMessage(
  412. FORMAT_MESSAGE_FROM_HMODULE |
  413. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  414. NULL,
  415. DHCP_ROGUE_SERVER_MESSAGE,
  416. 0, // language id.
  417. AlertMessage, // return buffer place holder.
  418. ALERT_MESSAGE_LENGTH, // minimum buffer size (in characters) to allocate.
  419. (va_list *)MessageParams // insert strings.
  420. );
  421. if( MsgLength == 0 ) {
  422. printf("FormatMessage failed %ld.", GetLastError() );
  423. }
  424. else {
  425. //
  426. // send alert message.
  427. //
  428. for( i = 0; i < GlobalAlertNamesCount; i++) {
  429. Error = NetMessageBufferSend(
  430. NULL,
  431. GlobalAlertNames[i],
  432. NULL,
  433. (LPBYTE)AlertMessage,
  434. MsgLength * sizeof(WCHAR) );
  435. if( Error != ERROR_SUCCESS ) {
  436. printf("NetMessageBufferSend failed %ld.", Error );
  437. break;
  438. }
  439. }
  440. }
  441. GlobalLastAlertTime = TimeNow;
  442. }
  443. }
  444. VOID
  445. DisplayMessage(
  446. LPSTR MessageBuffer,
  447. DWORD BufferLength,
  448. struct sockaddr_in *source
  449. )
  450. {
  451. DHCP_OPTIONS DhcpOptions;
  452. PDHCP_MESSAGE DhcpMessage;
  453. SYSTEMTIME SystemTime;
  454. DWORD MessageType;
  455. LPSTR MessageTypeString;
  456. BOOL AuthServer = FALSE;
  457. CHAR IpAddressString[SMALL_BUFFER_SIZE];
  458. CHAR ServerAddressString[SMALL_BUFFER_SIZE];
  459. //
  460. // check to see this is valid DHCP packet.
  461. //
  462. if( BufferLength < DHCP_MESSAGE_FIXED_PART_SIZE ) {
  463. return;
  464. }
  465. DhcpMessage = (LPDHCP_MESSAGE) MessageBuffer;
  466. if( (DhcpMessage->Operation != BOOT_REQUEST) &&
  467. (DhcpMessage->Operation != BOOT_REPLY) ) {
  468. return;
  469. }
  470. //
  471. // extract options.
  472. //
  473. ExtractOptions1(
  474. &DhcpMessage->Option,
  475. &DhcpOptions,
  476. BufferLength - DHCP_MESSAGE_FIXED_PART_SIZE );
  477. if( DhcpOptions.MessageType == NULL ) {
  478. return;
  479. }
  480. MessageType = *DhcpOptions.MessageType;
  481. if( (MessageType < DHCP_DISCOVER_MESSAGE ) ||
  482. (MessageType > DHCP_RELEASE_MESSAGE ) ) {
  483. return;
  484. }
  485. //
  486. // packet is valid dhcp packet, print info.
  487. //
  488. //
  489. // if this packet is from one of the auth server and we are asked
  490. // not to print auth servers packet, so so.
  491. //
  492. if( DhcpOptions.ServerIdentifier != NULL ) {
  493. AuthServer = IsAuthServer(*DhcpOptions.ServerIdentifier);
  494. }
  495. if( GlobalNoAuthPrint && AuthServer ) {
  496. return;
  497. }
  498. GetLocalTime( &SystemTime );
  499. printf("%02u:%02u:%02u ",
  500. SystemTime.wHour,
  501. SystemTime.wMinute,
  502. SystemTime.wSecond );
  503. switch ( MessageType ) {
  504. case DHCP_DISCOVER_MESSAGE:
  505. MessageTypeString = "DISCOVER";
  506. case DHCP_OFFER_MESSAGE:
  507. MessageTypeString = "OFFER";
  508. break;
  509. case DHCP_REQUEST_MESSAGE:
  510. MessageTypeString = "REQUEST";
  511. break;
  512. case DHCP_DECLINE_MESSAGE:
  513. MessageTypeString = "DECLINE";
  514. break;
  515. case DHCP_ACK_MESSAGE:
  516. MessageTypeString = "ACK";
  517. break;
  518. case DHCP_NACK_MESSAGE:
  519. MessageTypeString = "NACK";
  520. break;
  521. case DHCP_RELEASE_MESSAGE:
  522. MessageTypeString = "RELEASE";
  523. break;
  524. default:
  525. MessageTypeString = "UNKNOWN";
  526. break;
  527. }
  528. printf("%8s ", MessageTypeString);
  529. strcpy(
  530. IpAddressString,
  531. inet_ntoa(*(struct in_addr *)&DhcpMessage->YourIpAddress) );
  532. printf("(IP)%-15s ", IpAddressString );
  533. if(DhcpOptions.ServerIdentifier != NULL ) {
  534. DWORD ServerId;
  535. ServerId = *DhcpOptions.ServerIdentifier;
  536. strcpy( ServerAddressString, inet_ntoa(*(struct in_addr *)&ServerId) );
  537. printf("(S)%-15s ", ServerAddressString );
  538. if( source->sin_addr.s_addr != ServerId ) {
  539. printf("(S1)%-15s ",
  540. inet_ntoa(*(struct in_addr *)&source->sin_addr.s_addr) );
  541. }
  542. }
  543. //
  544. // beep if this it is a non-auth server.
  545. //
  546. if( AuthServer == FALSE ) {
  547. printf("***");
  548. MessageBeep( MB_ICONASTERISK );
  549. //
  550. // log an event.
  551. //
  552. LogEvent(
  553. MessageTypeString,
  554. IpAddressString,
  555. ServerAddressString );
  556. RaiseAlert(
  557. MessageTypeString,
  558. IpAddressString,
  559. ServerAddressString );
  560. }
  561. printf("\n");
  562. }
  563. DWORD
  564. ReceiveDatagram(
  565. VOID
  566. )
  567. {
  568. DWORD Error;
  569. SOCKET Sock;
  570. BOOL SocketOpened = FALSE;
  571. fd_set readSocketSet;
  572. struct timeval timeout;
  573. struct sockaddr socketName;
  574. int socketNameSize = sizeof( socketName );
  575. CHAR MessageBuffer[DHCP_MESSAGE_SIZE];
  576. Error = OpenSocket(
  577. &Sock,
  578. GlobalIpAddress,
  579. DHCP_CLIENT_PORT );
  580. if( Error != ERROR_SUCCESS ) {
  581. printf("OpenReceiveSocket failed %ld.", Error );
  582. goto Cleanup;
  583. }
  584. SocketOpened = TRUE;
  585. //
  586. // receive message.
  587. //
  588. while( GlobalTerminate != TRUE ) {
  589. FD_ZERO( &readSocketSet );
  590. FD_SET( Sock, &readSocketSet );
  591. timeout.tv_sec = RECEIVE_TIMEOUT;
  592. timeout.tv_usec = 0;
  593. Error = select( 0, &readSocketSet, NULL, NULL, &timeout);
  594. if ( Error == 0 ) {
  595. //
  596. // Timeout before read data is available.
  597. //
  598. // printf("Receive timeout.\n");
  599. }
  600. else {
  601. //
  602. // receive available message.
  603. //
  604. Error = recvfrom(
  605. Sock,
  606. MessageBuffer,
  607. sizeof(MessageBuffer),
  608. 0,
  609. &socketName,
  610. &socketNameSize
  611. );
  612. if ( Error == SOCKET_ERROR ) {
  613. Error = WSAGetLastError();
  614. printf("recvfrom failed %ld\n", Error );
  615. goto Cleanup;
  616. }
  617. if( GlobalTerminate == TRUE ) {
  618. break;
  619. }
  620. DisplayMessage(
  621. MessageBuffer,
  622. Error, // buffer length returned.
  623. (struct sockaddr_in *)&socketName );
  624. }
  625. }
  626. Cleanup:
  627. if( SocketOpened == TRUE ) {
  628. //
  629. // close socket.
  630. //
  631. closesocket( Sock );
  632. }
  633. GlobalTerminate = TRUE;
  634. return( Error );
  635. }
  636. DWORD __cdecl
  637. main(
  638. int argc,
  639. char **argv
  640. )
  641. {
  642. DWORD Error;
  643. LPSTR AppName = NULL;
  644. WSADATA wsaData;
  645. DWORD ThreadId;
  646. //
  647. // parse input parameters.
  648. //
  649. if( argc < 1 ) {
  650. goto Usage;
  651. }
  652. AppName = argv[0];
  653. argv++;
  654. argc--;
  655. if( argc < 1 ) {
  656. goto Usage;
  657. }
  658. //
  659. // parse flag parameter.
  660. //
  661. while( (argv[0][0] == '-') || (argv[0][0] == '/') ) {
  662. switch (argv[0][1] ) {
  663. case 'p':
  664. GlobalNoAuthPrint = TRUE;
  665. break;
  666. case 'i':
  667. GlobalAlertInterval = atoi( &argv[0][3] ) * 60;
  668. break;
  669. case 'a': {
  670. LPSTR NextName;
  671. LPSTR Ptr;
  672. Ptr = &argv[0][3];
  673. //
  674. // skip blanks.
  675. //
  676. while( *Ptr == ' ' ) {
  677. Ptr++;
  678. }
  679. NextName = Ptr;
  680. while( *Ptr != '\0' ) {
  681. if( *Ptr == ' ' ) {
  682. //
  683. // found another name.
  684. //
  685. *Ptr++ = '\0';
  686. GlobalAlertNames[GlobalAlertNamesCount] =
  687. DhcpOemToUnicode( NextName, NULL );
  688. GlobalAlertNamesCount++;
  689. if( GlobalAlertNamesCount >= MAX_ALERT_NAMES ) {
  690. break;
  691. }
  692. //
  693. // skip blanks.
  694. //
  695. while( *Ptr == ' ' ) {
  696. Ptr++;
  697. }
  698. NextName = Ptr;
  699. }
  700. else {
  701. Ptr++;
  702. }
  703. }
  704. if( GlobalAlertNamesCount < MAX_ALERT_NAMES ) {
  705. if( NextName != Ptr ) {
  706. GlobalAlertNames[GlobalAlertNamesCount] =
  707. DhcpOemToUnicode( NextName, NULL );
  708. GlobalAlertNamesCount++;
  709. }
  710. }
  711. break;
  712. }
  713. //
  714. // (a-martih) - Bug Fix
  715. //
  716. default:
  717. if ((_stricmp(argv[0], "/?")) &&
  718. (_stricmp(argv[0], "-?")) &&
  719. (_stricmp(argv[0], "/h")) &&
  720. (_stricmp(argv[0], "-h")) ) {
  721. printf( "\nunknown flag, %s \n", argv[0] );
  722. }
  723. goto Usage;
  724. break;
  725. }
  726. argv++;
  727. argc--;
  728. }
  729. if( argc < 1 ) {
  730. goto Usage;
  731. }
  732. //
  733. // read ipaddress parameter.
  734. //
  735. GlobalIpAddress = inet_addr( argv[0] );
  736. argv++;
  737. argc--;
  738. //
  739. // now read auth dhcp servers ipaddresses.
  740. //
  741. while( (argc > 0) && (GlobalAuthServersCount < AUTH_SERVERS_MAX) ) {
  742. GlobalAuthServers[GlobalAuthServersCount++] =
  743. inet_addr( argv[0] );
  744. argv++;
  745. argc--;
  746. }
  747. //
  748. // init socket.
  749. //
  750. Error = WSAStartup( WS_VERSION_REQUIRED, &wsaData);
  751. if( Error != ERROR_SUCCESS ) {
  752. printf( "WSAStartup failed %ld.\n", Error );
  753. return(1);
  754. }
  755. //
  756. // create receive datagrams thread.
  757. //
  758. GlobalRecvThreadHandle =
  759. CreateThread(
  760. NULL,
  761. 0,
  762. (LPTHREAD_START_ROUTINE)ReceiveDatagram,
  763. NULL,
  764. 0,
  765. &ThreadId );
  766. if( GlobalRecvThreadHandle == NULL ) {
  767. printf("CreateThread failed %ld.\n", GetLastError() );
  768. return(1);
  769. }
  770. //
  771. // read input.
  772. //
  773. while ( GlobalTerminate != TRUE ) {
  774. CHAR ch;
  775. ch = (CHAR)_getch();
  776. switch( ch ) {
  777. case 'q':
  778. case 'Q':
  779. // case '\c':
  780. GlobalTerminate = TRUE;
  781. break;
  782. case 'd':
  783. case 'D':
  784. //
  785. // send out discover message.
  786. //
  787. Error = SendDiscovery();
  788. if(Error != ERROR_SUCCESS ) {
  789. printf("SendDiscover failed %ld.\n", Error );
  790. }
  791. break;
  792. case 'h':
  793. case 'H':
  794. default:
  795. printf("Type d - to discover; q - to quit; h - for help.\n");
  796. //
  797. // print out help message.
  798. //
  799. break;
  800. }
  801. }
  802. //
  803. // terminate receive thread.
  804. //
  805. WaitForSingleObject(
  806. GlobalRecvThreadHandle,
  807. THREAD_TERMINATION_TIMEOUT );
  808. CloseHandle( GlobalRecvThreadHandle );
  809. // Cleanup:
  810. return(0);
  811. Usage:
  812. printf("\nUSAGE:\n\n");
  813. printf("%s [-p] [-a:\"list-of-alertnames\"] [-i:alertinterval] "
  814. "machine-ip-address "
  815. "[list of valid dhcp servers ip addresses]", AppName );
  816. return(1);
  817. }