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.

871 lines
21 KiB

  1. /*++
  2. Copyright (C) 1999-2002 Microsoft Corporation
  3. Module Name:
  4. isdhcp.c
  5. Abstract:
  6. test program to see if a DHCP server is around or not.
  7. Environment:
  8. Win2K+
  9. History:
  10. Code provided by JRuan on May 8, 2002 and integrated into
  11. CYS by JeffJon
  12. --*/
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <windows.h>
  17. #include <winsock2.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <time.h>
  21. #include <dhcpcapi.h>
  22. #include <iprtrmib.h>
  23. #include <iphlpapi.h>
  24. #include <stdio.h>
  25. #define OPTION_PAD 0
  26. #define OPTION_HOST_NAME 12
  27. #define OPTION_MESSAGE_TYPE 53
  28. #define OPTION_SERVER_IDENTIFIER 54
  29. #define OPTION_PARAMETER_REQUEST_LIST 55
  30. #define OPTION_CLIENT_ID 61
  31. #define OPTION_END 255
  32. #define DHCP_CLIENT_PORT 68
  33. #define DHCP_SERVR_PORT 67
  34. BYTE HardwareAddress[16];
  35. BYTE HardwareAddressLength = 6;
  36. #define SOCKET_RECEIVE_BUFFER_SIZE 1024 * 4 // 4K max.
  37. #define AUTH_SERVERS_MAX 64
  38. #define SMALL_BUFFER_SIZE 32
  39. #define ALERT_INTERVAL 5 * 60 // 5 mins
  40. #define ALERT_MESSAGE_LENGTH 256
  41. #define MAX_ALERT_NAMES 256
  42. #define BOOT_REQUEST 1
  43. #define DHCP_BROADCAST 0x8000
  44. #define DHCP_DISCOVER_MESSAGE 1
  45. #define DHCP_INFORM_MESSAGE 8
  46. #define DHCP_MESSAGE_SIZE 576
  47. #define DHCP_RECV_MESSAGE_SIZE 4096
  48. #define BOOT_FILE_SIZE 128
  49. #define BOOT_SERVER_SIZE 64
  50. #define DHCP_MAGIC_COOKIE_BYTE1 99
  51. #define DHCP_MAGIC_COOKIE_BYTE2 130
  52. #define DHCP_MAGIC_COOKIE_BYTE3 83
  53. #define DHCP_MAGIC_COOKIE_BYTE4 99
  54. #include <packon.h>
  55. typedef struct _OPTION {
  56. BYTE OptionType;
  57. BYTE OptionLength;
  58. BYTE OptionValue[1];
  59. } OPTION, *POPTION, *LPOPTION;
  60. typedef struct _DHCP_MESSAGE {
  61. BYTE Operation;
  62. BYTE HardwareAddressType;
  63. BYTE HardwareAddressLength;
  64. BYTE HopCount;
  65. DWORD TransactionID;
  66. WORD SecondsSinceBoot;
  67. WORD Reserved;
  68. ULONG ClientIpAddress;
  69. ULONG YourIpAddress;
  70. ULONG BootstrapServerAddress;
  71. ULONG RelayAgentIpAddress;
  72. BYTE HardwareAddress[16];
  73. BYTE HostName[ BOOT_SERVER_SIZE ];
  74. BYTE BootFileName[BOOT_FILE_SIZE];
  75. OPTION Option;
  76. } DHCP_MESSAGE, *PDHCP_MESSAGE, *LPDHCP_MESSAGE;
  77. #include <packoff.h>
  78. LPOPTION
  79. DhcpAppendOption(
  80. LPOPTION Option,
  81. BYTE OptionType,
  82. PVOID OptionValue,
  83. ULONG OptionLength,
  84. LPBYTE OptionEnd
  85. )
  86. /*++
  87. Routine Description:
  88. This function writes a DHCP option to message buffer.
  89. Arguments:
  90. Option - A pointer to a message buffer.
  91. OptionType - The option number to append.
  92. OptionValue - A pointer to the option data.
  93. OptionLength - The length, in bytes, of the option data.
  94. OptionEnd - End of Option Buffer.
  95. Return Value:
  96. A pointer to the end of the appended option.
  97. --*/
  98. {
  99. if (!Option)
  100. {
  101. return Option;
  102. }
  103. if ( OptionType == OPTION_END ) {
  104. //
  105. // we should alway have atleast one BYTE space in the buffer
  106. // to append this option.
  107. //
  108. Option->OptionType = OPTION_END;
  109. return( (LPOPTION) ((LPBYTE)(Option) + 1) );
  110. }
  111. if ( OptionType == OPTION_PAD ) {
  112. //
  113. // add this option only iff we have enough space in the buffer.
  114. //
  115. if(((LPBYTE)Option + 1) < (OptionEnd - 1) ) {
  116. Option->OptionType = OPTION_PAD;
  117. return( (LPOPTION) ((LPBYTE)(Option) + 1) );
  118. }
  119. return Option;
  120. }
  121. //
  122. // add this option only iff we have enough space in the buffer.
  123. //
  124. if(((LPBYTE)Option + 2 + OptionLength) >= (OptionEnd - 1) ) {
  125. return Option;
  126. }
  127. if( OptionLength <= 0xFF ) {
  128. // simple option.. no need to use OPTION_MSFT_CONTINUED
  129. Option->OptionType = OptionType;
  130. Option->OptionLength = (BYTE)OptionLength;
  131. memcpy( Option->OptionValue, OptionValue, OptionLength );
  132. return( (LPOPTION) ((LPBYTE)(Option) + Option->OptionLength + 2) );
  133. }
  134. // option size is > 0xFF --> need to continue it using multiple ones..
  135. // there are OptionLenght / 0xFF occurances using 0xFF+2 bytes + one
  136. // using 2 + (OptionLength % 0xFF ) space..
  137. // check to see if we have the space first..
  138. if( 2 + (OptionLength%0xFF) + 0x101*(OptionLength/0xFF)
  139. + (LPBYTE)Option >= (OptionEnd - 1) ) {
  140. return Option;
  141. }
  142. return Option;
  143. }
  144. LPBYTE
  145. DhcpAppendMagicCookie(
  146. LPBYTE Option,
  147. LPBYTE OptionEnd
  148. )
  149. /*++
  150. Routine Description:
  151. This routine appends magic cookie to a DHCP message.
  152. Arguments:
  153. Option - A pointer to the place to append the magic cookie.
  154. OptionEnd - End of Option buffer.
  155. Return Value:
  156. A pointer to the end of the appended cookie.
  157. Note : The magic cookie is :
  158. --------------------
  159. | 99 | 130 | 83 | 99 |
  160. --------------------
  161. --*/
  162. {
  163. if( (Option + 4) < (OptionEnd - 1) ) {
  164. *Option++ = (BYTE)DHCP_MAGIC_COOKIE_BYTE1;
  165. *Option++ = (BYTE)DHCP_MAGIC_COOKIE_BYTE2;
  166. *Option++ = (BYTE)DHCP_MAGIC_COOKIE_BYTE3;
  167. *Option++ = (BYTE)DHCP_MAGIC_COOKIE_BYTE4;
  168. }
  169. return( Option );
  170. }
  171. LPOPTION
  172. DhcpAppendClientIDOption(
  173. LPOPTION Option,
  174. BYTE ClientHWType,
  175. LPBYTE ClientHWAddr,
  176. BYTE ClientHWAddrLength,
  177. LPBYTE OptionEnd
  178. )
  179. /*++
  180. Routine Description:
  181. This routine appends client ID option to a DHCP message.
  182. History:
  183. 8/26/96 Frankbee Removed 16 byte limitation on the hardware
  184. address
  185. Arguments:
  186. Option - A pointer to the place to append the option request.
  187. ClientHWType - Client hardware type.
  188. ClientHWAddr - Client hardware address
  189. ClientHWAddrLength - Client hardware address length.
  190. OptionEnd - End of Option buffer.
  191. Return Value:
  192. A pointer to the end of the newly appended option.
  193. Note : The client ID option will look like as below in the message:
  194. -----------------------------------------------------------------
  195. | OpNum | Len | HWType | HWA1 | HWA2 | ..... | HWAn |
  196. -----------------------------------------------------------------
  197. --*/
  198. {
  199. struct _CLIENT_ID {
  200. BYTE bHardwareAddressType;
  201. BYTE pbHardwareAddress[1];
  202. } *pClientID;
  203. LPOPTION lpNewOption = 0;
  204. pClientID = LocalAlloc(LMEM_FIXED, sizeof( struct _CLIENT_ID ) + ClientHWAddrLength);
  205. //
  206. // currently there is no way to indicate failure. simply return unmodified option
  207. // list
  208. //
  209. if ( !pClientID )
  210. return Option;
  211. pClientID->bHardwareAddressType = ClientHWType;
  212. memcpy( pClientID->pbHardwareAddress, ClientHWAddr, ClientHWAddrLength );
  213. lpNewOption = DhcpAppendOption(
  214. Option,
  215. OPTION_CLIENT_ID,
  216. (LPBYTE)pClientID,
  217. (BYTE)(ClientHWAddrLength + sizeof(BYTE)),
  218. OptionEnd );
  219. LocalFree( pClientID );
  220. return lpNewOption;
  221. }
  222. DWORD
  223. OpenSocket(
  224. SOCKET *Socket,
  225. unsigned long IpAddress,
  226. unsigned short Port
  227. )
  228. {
  229. DWORD Error = 0;
  230. SOCKET Sock;
  231. DWORD OptValue = TRUE;
  232. struct sockaddr_in SocketName;
  233. //
  234. // Create a socket
  235. //
  236. Sock = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
  237. if ( Sock == INVALID_SOCKET ) {
  238. Error = WSAGetLastError();
  239. goto error;
  240. }
  241. //
  242. // Make the socket share-able
  243. //
  244. Error = setsockopt(
  245. Sock,
  246. SOL_SOCKET,
  247. SO_REUSEADDR,
  248. (char*)&OptValue,
  249. sizeof(OptValue) );
  250. if ( Error != ERROR_SUCCESS ) {
  251. Error = WSAGetLastError();
  252. goto error;
  253. }
  254. OptValue = TRUE;
  255. Error = setsockopt(
  256. Sock,
  257. SOL_SOCKET,
  258. SO_BROADCAST,
  259. (char*)&OptValue,
  260. sizeof(OptValue) );
  261. if ( Error != ERROR_SUCCESS ) {
  262. Error = WSAGetLastError();
  263. goto error;
  264. }
  265. OptValue = SOCKET_RECEIVE_BUFFER_SIZE;
  266. Error = setsockopt(
  267. Sock,
  268. SOL_SOCKET,
  269. SO_RCVBUF,
  270. (char*)&OptValue,
  271. sizeof(OptValue) );
  272. if ( Error != ERROR_SUCCESS ) {
  273. Error = WSAGetLastError();
  274. goto error;
  275. }
  276. SocketName.sin_family = PF_INET;
  277. SocketName.sin_port = Port;
  278. SocketName.sin_addr.s_addr = IpAddress;
  279. RtlZeroMemory( SocketName.sin_zero, 8);
  280. //
  281. // Bind this socket to the DHCP server port
  282. //
  283. Error = bind(
  284. Sock,
  285. (struct sockaddr FAR *)&SocketName,
  286. sizeof( SocketName )
  287. );
  288. if ( Error != ERROR_SUCCESS ) {
  289. Error = WSAGetLastError();
  290. goto error;
  291. }
  292. *Socket = Sock;
  293. Error = ERROR_SUCCESS;
  294. error:
  295. if( Error != ERROR_SUCCESS ) {
  296. //
  297. // if we aren't successful, close the socket if it is opened.
  298. //
  299. if( Sock != INVALID_SOCKET ) {
  300. closesocket( Sock );
  301. }
  302. }
  303. return( Error );
  304. }
  305. DWORD
  306. SendInformOrDiscover(
  307. SOCKET Sock,
  308. ULONG uClientIp,
  309. BYTE ucMessageType,
  310. PBYTE pMessageBuffer,
  311. ULONG uMessageBufferSize,
  312. ULONG DestIp,
  313. PULONG puXid
  314. )
  315. {
  316. DWORD Error = 0;
  317. PDHCP_MESSAGE dhcpMessage = (PDHCP_MESSAGE)pMessageBuffer;
  318. LPOPTION option = 0;
  319. LPBYTE OptionEnd = 0;
  320. BYTE value = 0;
  321. ULONG uXid = 0;
  322. LPSTR HostName = "detective";
  323. ULONG uNumOfRequestOptions = 0;
  324. UCHAR ucRequestOptions[256];
  325. struct sockaddr_in socketName;
  326. DWORD i;
  327. uXid = (rand() & 0xff);
  328. uXid <<= 8;
  329. uXid |= (rand() & 0xff);
  330. uXid <<= 8;
  331. uXid |= (rand() & 0xff);
  332. uXid <<= 8;
  333. uXid |= (rand() & 0xff);
  334. HardwareAddressLength = 6;
  335. for (i = 0; i < HardwareAddressLength; i++) {
  336. HardwareAddress[i] = (BYTE)(rand() & 0xff);
  337. }
  338. //
  339. // prepare message.
  340. //
  341. RtlZeroMemory( dhcpMessage, uMessageBufferSize );
  342. dhcpMessage->Operation = BOOT_REQUEST;
  343. dhcpMessage->ClientIpAddress = uClientIp;
  344. dhcpMessage->HardwareAddressType = 1;
  345. dhcpMessage->SecondsSinceBoot = 60; // random value ??
  346. dhcpMessage->Reserved = htons(DHCP_BROADCAST);
  347. dhcpMessage->TransactionID = uXid;
  348. *puXid = uXid;
  349. memcpy(
  350. dhcpMessage->HardwareAddress,
  351. HardwareAddress,
  352. HardwareAddressLength
  353. );
  354. dhcpMessage->HardwareAddressLength = (BYTE)HardwareAddressLength;
  355. option = &dhcpMessage->Option;
  356. OptionEnd = (LPBYTE)dhcpMessage + uMessageBufferSize;
  357. //
  358. // always add magic cookie first
  359. //
  360. option = (LPOPTION) DhcpAppendMagicCookie( (LPBYTE) option, OptionEnd );
  361. value = ucMessageType;
  362. option = DhcpAppendOption(
  363. option,
  364. OPTION_MESSAGE_TYPE,
  365. &value,
  366. 1,
  367. OptionEnd );
  368. //
  369. // Add client ID Option.
  370. //
  371. option = DhcpAppendClientIDOption(
  372. option,
  373. 1,
  374. HardwareAddress,
  375. HardwareAddressLength,
  376. OptionEnd );
  377. //
  378. // add Host name and comment options.
  379. //
  380. option = DhcpAppendOption(
  381. option,
  382. OPTION_HOST_NAME,
  383. (LPBYTE)HostName,
  384. (BYTE)((strlen(HostName) + 1) * sizeof(CHAR)),
  385. OptionEnd );
  386. //
  387. // Add requested option
  388. //
  389. uNumOfRequestOptions = 0;
  390. ucRequestOptions[uNumOfRequestOptions++] = 3;
  391. option = DhcpAppendOption(
  392. option,
  393. OPTION_PARAMETER_REQUEST_LIST,
  394. ucRequestOptions,
  395. uNumOfRequestOptions,
  396. OptionEnd
  397. );
  398. //
  399. // Add END option.
  400. //
  401. option = DhcpAppendOption( option, OPTION_END, NULL, 0, OptionEnd );
  402. //
  403. // Initialize the outgoing address.
  404. //
  405. socketName.sin_family = PF_INET;
  406. socketName.sin_port = htons( DHCP_SERVR_PORT );
  407. socketName.sin_addr.s_addr = DestIp;
  408. for ( i = 0; i < 8 ; i++ ) {
  409. socketName.sin_zero[i] = 0;
  410. }
  411. Error = sendto(
  412. Sock,
  413. (char*)pMessageBuffer,
  414. (int)(((PBYTE)option) - pMessageBuffer),
  415. 0,
  416. (struct sockaddr *)&socketName,
  417. sizeof( struct sockaddr )
  418. );
  419. if ( Error == SOCKET_ERROR ) {
  420. Error = WSAGetLastError();
  421. return( Error );
  422. }
  423. return( ERROR_SUCCESS );
  424. }
  425. DWORD
  426. GetSpecifiedMessage(
  427. SOCKET Sock,
  428. PBYTE pMessageBuffer,
  429. ULONG uMessageBufferSize,
  430. ULONG uXid,
  431. ULONG uTimeout,
  432. ULONG * pServerIpAddress
  433. )
  434. {
  435. DWORD Error = 0;
  436. fd_set readSocketSet;
  437. struct timeval timeout;
  438. struct sockaddr socketName;
  439. int socketNameSize = sizeof( socketName );
  440. PDHCP_MESSAGE dhcpMessage = (PDHCP_MESSAGE)pMessageBuffer;
  441. time_t start_time = 0, now = 0;
  442. PUCHAR pucOption = NULL;
  443. ULONG uBytesRemain = 0;
  444. ULONG uOptionSize = 0;
  445. BOOL bWellFormedPacket = FALSE;
  446. ULONG uRemainingTime = 0;
  447. BOOL continueLooping = TRUE;
  448. BOOL continueInternalLoop = TRUE;
  449. BOOL continueInternalLoop2 = FALSE;
  450. BYTE ReqdCookie[] = {
  451. (BYTE)DHCP_MAGIC_COOKIE_BYTE1,
  452. (BYTE)DHCP_MAGIC_COOKIE_BYTE2,
  453. (BYTE)DHCP_MAGIC_COOKIE_BYTE3,
  454. (BYTE)DHCP_MAGIC_COOKIE_BYTE4
  455. };
  456. time(&now);
  457. start_time = now;
  458. *pServerIpAddress = 0;
  459. while (continueLooping) {
  460. time(&now);
  461. uRemainingTime = uTimeout - (ULONG)(now - start_time);
  462. FD_ZERO( &readSocketSet );
  463. // FD_SET( Sock, &readSocketSet );
  464. // Had to inline the macro because the compiler was complaining
  465. // about the while(0) that was present in FD_SET
  466. do {
  467. u_int __i;
  468. for (__i = 0; __i < ((fd_set FAR *)(&readSocketSet))->fd_count; __i++) {
  469. if (((fd_set FAR *)(&readSocketSet))->fd_array[__i] == (Sock)) {
  470. continueInternalLoop2 = FALSE;
  471. break;
  472. }
  473. }
  474. if (__i == ((fd_set FAR *)(&readSocketSet))->fd_count) {
  475. if (((fd_set FAR *)(&readSocketSet))->fd_count < FD_SETSIZE) {
  476. ((fd_set FAR *)(&readSocketSet))->fd_array[__i] = (Sock);
  477. ((fd_set FAR *)(&readSocketSet))->fd_count++;
  478. }
  479. }
  480. } while(continueInternalLoop2);
  481. timeout.tv_sec = uRemainingTime;
  482. timeout.tv_usec = 0;
  483. Error = select(1, &readSocketSet, NULL, NULL, &timeout);
  484. if (Error == 0) {
  485. Error = ERROR_SEM_TIMEOUT;
  486. continueLooping = FALSE;
  487. break;
  488. }
  489. //
  490. // receive available message.
  491. //
  492. Error = recvfrom(
  493. Sock,
  494. (char*)pMessageBuffer,
  495. uMessageBufferSize,
  496. 0,
  497. &socketName,
  498. &socketNameSize
  499. );
  500. if ( Error == SOCKET_ERROR ) {
  501. Error = WSAGetLastError();
  502. //
  503. // Don't bail out here.
  504. //
  505. continue;
  506. }
  507. //
  508. // Some sanity check
  509. //
  510. if (Error < sizeof(DHCP_MESSAGE)) {
  511. continue;
  512. }
  513. if (dhcpMessage->HardwareAddressLength != HardwareAddressLength) {
  514. continue;
  515. }
  516. if (memcmp(dhcpMessage->HardwareAddress, HardwareAddress, HardwareAddressLength) != 0) {
  517. continue;
  518. }
  519. if (dhcpMessage->TransactionID != uXid) {
  520. continue;
  521. }
  522. //
  523. // Make sure the option part is well-formed
  524. // +--------------+----------+----------+-------------+
  525. // | magic cookie | Option 1 | Length 1 | Option Data 1 ...
  526. // +--------------+----------+----------+-------------+
  527. //
  528. pucOption = (PUCHAR)(&dhcpMessage->Option);
  529. uBytesRemain = Error - (ULONG)(pucOption - ((PUCHAR)dhcpMessage));
  530. if (uBytesRemain < sizeof(ReqdCookie)) {
  531. continue;
  532. }
  533. if (0 != memcmp(pucOption, ReqdCookie, sizeof(ReqdCookie))) {
  534. continue;
  535. }
  536. pucOption += sizeof(ReqdCookie);
  537. uBytesRemain -= sizeof(ReqdCookie);
  538. bWellFormedPacket = FALSE;
  539. while (continueInternalLoop) {
  540. //
  541. // Make sure pucOption[0] is readable
  542. //
  543. if (uBytesRemain < 1) {
  544. continueInternalLoop = FALSE;
  545. break;
  546. }
  547. if (pucOption[0] == OPTION_PAD) {
  548. pucOption++;
  549. uBytesRemain--;
  550. continue;
  551. }
  552. if (pucOption[0] == OPTION_END) {
  553. //
  554. // See the OPTION_END. This is a well-formed packet
  555. //
  556. bWellFormedPacket = TRUE;
  557. continueInternalLoop = FALSE;
  558. break;
  559. }
  560. //
  561. // Make sure pucOption[1] is readable
  562. //
  563. if (uBytesRemain < 2) {
  564. continueInternalLoop = FALSE;
  565. break;
  566. }
  567. uOptionSize = pucOption[1];
  568. //
  569. // Make sure there is enough bytes for the option data
  570. //
  571. if (uBytesRemain < uOptionSize) {
  572. continueInternalLoop = FALSE;
  573. break;
  574. }
  575. if (pucOption[0] == OPTION_SERVER_IDENTIFIER) {
  576. if (uOptionSize != sizeof(ULONG)) {
  577. continueInternalLoop = FALSE;
  578. break;
  579. }
  580. memcpy(pServerIpAddress, pucOption + 2, sizeof(ULONG));
  581. }
  582. //
  583. // Skip the option head and option data and move
  584. // to the next option
  585. //
  586. uBytesRemain -= uOptionSize + 2;
  587. pucOption += uOptionSize + 2;
  588. }
  589. if (bWellFormedPacket) {
  590. Error = ERROR_SUCCESS;
  591. continueLooping = FALSE;
  592. break;
  593. }
  594. }
  595. return( Error );
  596. }
  597. // This will first attempt a DHCP_INFORM to detect a DHCP server.
  598. // If that fails it will attempt a DHCP_DISCOVER.
  599. DWORD
  600. AnyDHCPServerRunning(
  601. ULONG uClientIp,
  602. ULONG * pServerIp
  603. )
  604. {
  605. CHAR MessageBuffer[DHCP_RECV_MESSAGE_SIZE];
  606. SOCKET Sock = INVALID_SOCKET;
  607. ULONG DestIp = htonl(INADDR_BROADCAST);
  608. DWORD dwError = ERROR_SUCCESS;
  609. ULONG uXid = 0;
  610. ULONG uMessageBufferSize = sizeof(MessageBuffer);
  611. ULONG uTimeout = 4;
  612. int retries = 0;
  613. if (!pServerIp)
  614. {
  615. dwError = ERROR_INVALID_PARAMETER;
  616. goto error;
  617. }
  618. dwError = OpenSocket(
  619. &Sock,
  620. uClientIp,
  621. htons(DHCP_CLIENT_PORT)
  622. );
  623. if( dwError != ERROR_SUCCESS ) {
  624. goto error;
  625. }
  626. for (retries = 0; retries < 3; retries++) {
  627. //
  628. // Try inform
  629. //
  630. dwError =
  631. SendInformOrDiscover(
  632. Sock,
  633. uClientIp,
  634. DHCP_INFORM_MESSAGE,
  635. (PBYTE)MessageBuffer,
  636. uMessageBufferSize,
  637. DestIp,
  638. &uXid);
  639. if (dwError != ERROR_SUCCESS) {
  640. goto error;
  641. }
  642. dwError = GetSpecifiedMessage(
  643. Sock,
  644. (PBYTE)MessageBuffer,
  645. uMessageBufferSize,
  646. uXid,
  647. uTimeout,
  648. pServerIp
  649. );
  650. if (dwError != ERROR_SEM_TIMEOUT && *pServerIp != htonl(INADDR_ANY) && *pServerIp != htonl(INADDR_BROADCAST)) {
  651. break;
  652. }
  653. //
  654. // Try discover
  655. //
  656. dwError =
  657. SendInformOrDiscover(
  658. Sock,
  659. uClientIp,
  660. DHCP_DISCOVER_MESSAGE,
  661. (PBYTE)MessageBuffer,
  662. uMessageBufferSize,
  663. DestIp,
  664. &uXid);
  665. if (dwError != ERROR_SUCCESS) {
  666. goto error;
  667. }
  668. dwError = GetSpecifiedMessage(
  669. Sock,
  670. (PBYTE)MessageBuffer,
  671. uMessageBufferSize,
  672. uXid,
  673. uTimeout,
  674. pServerIp
  675. );
  676. if (dwError != ERROR_SEM_TIMEOUT && *pServerIp != htonl(INADDR_ANY) && *pServerIp != htonl(INADDR_BROADCAST)) {
  677. break;
  678. }
  679. }
  680. error:
  681. if (Sock != INVALID_SOCKET) {
  682. closesocket(Sock);
  683. }
  684. return dwError;
  685. }