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.

648 lines
18 KiB

  1. /*++
  2. Copyright (c) 1998, Microsoft Corporation
  3. Module Name:
  4. dhcpio.c
  5. Abstract:
  6. This module contains code for the DHCP allocator's network I/O.
  7. Author:
  8. Abolade Gbadegesin (aboladeg) 5-Mar-1998
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. VOID
  14. DhcpReadCompletionRoutine(
  15. ULONG ErrorCode,
  16. ULONG BytesTransferred,
  17. PNH_BUFFER Bufferp
  18. )
  19. /*++
  20. Routine Description:
  21. This routine is invoked upon completion of a read operation
  22. on a datagram socket bound to the DHCP server UDP port.
  23. The message read is validated and processed, and if necessary,
  24. a reply is generated and sent to the client.
  25. Arguments:
  26. ErrorCode - Win32 status code for the I/O operation
  27. BytesTransferred - number of bytes in 'Bufferp'
  28. Bufferp - holds data read from the datagram socket
  29. Return Value:
  30. none.
  31. Environment:
  32. Runs in the context of an RTUTILS.DLL worker-thread which has just
  33. dequeued an I/O completion packet from the common I/O completion port
  34. with which our datagram sockets are associated.
  35. A reference to the component will have been made on our behalf
  36. by 'NhReadDatagramSocket'.
  37. --*/
  38. {
  39. ULONG Error;
  40. PDHCP_HEADER Headerp;
  41. PDHCP_INTERFACE Interfacep;
  42. PROFILE("DhcpReadCompletionRoutine");
  43. do {
  44. //
  45. // There are two cases where we don't process the message;
  46. // (a) the I/O operation failed
  47. // (b) the interface is no longer active
  48. // In cases (a) we repost the buffer; in case (b) we do not.
  49. //
  50. Interfacep = (PDHCP_INTERFACE)Bufferp->Context;
  51. //
  52. // First look for an error code
  53. //
  54. if (ErrorCode) {
  55. NhTrace(
  56. TRACE_FLAG_IO,
  57. "DhcpReadCompletionRoutine: error %d for read-context %x",
  58. ErrorCode,
  59. Bufferp->Context
  60. );
  61. //
  62. // See if the interface is still active
  63. //
  64. ACQUIRE_LOCK(Interfacep);
  65. if (!DHCP_INTERFACE_ACTIVE(Interfacep)) {
  66. RELEASE_LOCK(Interfacep);
  67. NhReleaseBuffer(Bufferp);
  68. }
  69. else {
  70. RELEASE_LOCK(Interfacep);
  71. EnterCriticalSection(&DhcpInterfaceLock);
  72. if (!DHCP_REFERENCE_INTERFACE(Interfacep)) {
  73. NhReleaseBuffer(Bufferp);
  74. }
  75. else {
  76. //
  77. // Repost the buffer for another read operation
  78. //
  79. Error =
  80. NhReadDatagramSocket(
  81. &DhcpComponentReference,
  82. Bufferp->Socket,
  83. Bufferp,
  84. DhcpReadCompletionRoutine,
  85. Bufferp->Context,
  86. Bufferp->Context2
  87. );
  88. if (Error) {
  89. ACQUIRE_LOCK(Interfacep);
  90. DhcpDeferReadInterface(Interfacep, Bufferp->Socket);
  91. RELEASE_LOCK(Interfacep);
  92. DHCP_DEREFERENCE_INTERFACE(Interfacep);
  93. NhWarningLog(
  94. IP_AUTO_DHCP_LOG_RECEIVE_FAILED,
  95. Error,
  96. "%I",
  97. NhQueryAddressSocket(Bufferp->Socket)
  98. );
  99. NhReleaseBuffer(Bufferp);
  100. }
  101. }
  102. LeaveCriticalSection(&DhcpInterfaceLock);
  103. }
  104. break;
  105. }
  106. //
  107. // Now see if the interface is operational
  108. //
  109. ACQUIRE_LOCK(Interfacep);
  110. if (!DHCP_INTERFACE_ACTIVE(Interfacep)) {
  111. RELEASE_LOCK(Interfacep);
  112. NhReleaseBuffer(Bufferp);
  113. NhTrace(
  114. TRACE_FLAG_IO,
  115. "DhcpReadCompletionRoutine: interface %x inactive",
  116. Interfacep
  117. );
  118. break;
  119. }
  120. RELEASE_LOCK(Interfacep);
  121. //
  122. // Ensure minimum DHCP_HEADER size
  123. //
  124. if (BytesTransferred < sizeof(DHCP_HEADER)) {
  125. NhTrace(
  126. TRACE_FLAG_DHCP,
  127. "DhcpReadCompletionRoutine: message size %d too small",
  128. BytesTransferred
  129. );
  130. NhWarningLog(
  131. IP_AUTO_DHCP_LOG_MESSAGE_TOO_SMALL,
  132. 0,
  133. ""
  134. );
  135. InterlockedIncrement(
  136. reinterpret_cast<LPLONG>(&DhcpStatistics.MessagesIgnored)
  137. );
  138. //
  139. // Repost read
  140. //
  141. EnterCriticalSection(&DhcpInterfaceLock);
  142. if (!DHCP_REFERENCE_INTERFACE(Interfacep)) {
  143. LeaveCriticalSection(&DhcpInterfaceLock);
  144. NhReleaseBuffer(Bufferp);
  145. }
  146. else {
  147. LeaveCriticalSection(&DhcpInterfaceLock);
  148. Error =
  149. NhReadDatagramSocket(
  150. &DhcpComponentReference,
  151. Bufferp->Socket,
  152. Bufferp,
  153. DhcpReadCompletionRoutine,
  154. Bufferp->Context,
  155. Bufferp->Context2
  156. );
  157. if (Error) {
  158. ACQUIRE_LOCK(Interfacep);
  159. DhcpDeferReadInterface(Interfacep, Bufferp->Socket);
  160. RELEASE_LOCK(Interfacep);
  161. DHCP_DEREFERENCE_INTERFACE(Interfacep);
  162. NhWarningLog(
  163. IP_AUTO_DHCP_LOG_RECEIVE_FAILED,
  164. Error,
  165. "%I",
  166. NhQueryAddressSocket(Bufferp->Socket)
  167. );
  168. NhReleaseBuffer(Bufferp);
  169. }
  170. }
  171. break;
  172. }
  173. //
  174. // Now look at the message
  175. //
  176. Headerp = (PDHCP_HEADER)Bufferp->Buffer;
  177. switch (Headerp->Operation) {
  178. case BOOTP_OPERATION_REQUEST: {
  179. DhcpProcessMessage(
  180. Interfacep,
  181. Bufferp
  182. );
  183. break;
  184. }
  185. case BOOTP_OPERATION_REPLY: {
  186. InterlockedIncrement(
  187. reinterpret_cast<LPLONG>(&DhcpStatistics.MessagesIgnored)
  188. );
  189. NhTrace(
  190. TRACE_FLAG_IO,
  191. "DhcpReadCompletionRoutine: ignoring BOOTPREPLY"
  192. );
  193. //
  194. // Repost the buffer for another read operation.
  195. //
  196. EnterCriticalSection(&DhcpInterfaceLock);
  197. if (!DHCP_REFERENCE_INTERFACE(Interfacep)) {
  198. LeaveCriticalSection(&DhcpInterfaceLock);
  199. NhReleaseBuffer(Bufferp);
  200. }
  201. else {
  202. LeaveCriticalSection(&DhcpInterfaceLock);
  203. Error =
  204. NhReadDatagramSocket(
  205. &DhcpComponentReference,
  206. Bufferp->Socket,
  207. Bufferp,
  208. DhcpReadCompletionRoutine,
  209. Bufferp->Context,
  210. Bufferp->Context2
  211. );
  212. if (Error) {
  213. ACQUIRE_LOCK(Interfacep);
  214. DhcpDeferReadInterface(Interfacep, Bufferp->Socket);
  215. RELEASE_LOCK(Interfacep);
  216. DHCP_DEREFERENCE_INTERFACE(Interfacep);
  217. NhWarningLog(
  218. IP_AUTO_DHCP_LOG_RECEIVE_FAILED,
  219. Error,
  220. "%I",
  221. NhQueryAddressSocket(Bufferp->Socket)
  222. );
  223. NhReleaseBuffer(Bufferp);
  224. }
  225. }
  226. break;
  227. }
  228. default: {
  229. InterlockedIncrement(
  230. reinterpret_cast<LPLONG>(&DhcpStatistics.MessagesIgnored)
  231. )
  232. ;
  233. NhTrace(
  234. TRACE_FLAG_IO,
  235. "DhcpReadCompletionRoutine: ignoring invalid BOOTP operation %d",
  236. Headerp->Operation
  237. );
  238. NhInformationLog(
  239. IP_AUTO_DHCP_LOG_INVALID_BOOTP_OPERATION,
  240. 0,
  241. "%d",
  242. Headerp->Operation
  243. );
  244. //
  245. // Repost the buffer for another read operation.
  246. //
  247. EnterCriticalSection(&DhcpInterfaceLock);
  248. if (!DHCP_REFERENCE_INTERFACE(Interfacep)) {
  249. LeaveCriticalSection(&DhcpInterfaceLock);
  250. NhReleaseBuffer(Bufferp);
  251. }
  252. else {
  253. LeaveCriticalSection(&DhcpInterfaceLock);
  254. Error =
  255. NhReadDatagramSocket(
  256. &DhcpComponentReference,
  257. Bufferp->Socket,
  258. Bufferp,
  259. DhcpReadCompletionRoutine,
  260. Bufferp->Context,
  261. Bufferp->Context2
  262. );
  263. if (Error) {
  264. ACQUIRE_LOCK(Interfacep);
  265. DhcpDeferReadInterface(Interfacep, Bufferp->Socket);
  266. RELEASE_LOCK(Interfacep);
  267. DHCP_DEREFERENCE_INTERFACE(Interfacep);
  268. NhWarningLog(
  269. IP_AUTO_DHCP_LOG_RECEIVE_FAILED,
  270. Error,
  271. "%I",
  272. NhQueryAddressSocket(Bufferp->Socket)
  273. );
  274. NhReleaseBuffer(Bufferp);
  275. }
  276. }
  277. break;
  278. }
  279. }
  280. } while(FALSE);
  281. DHCP_DEREFERENCE_INTERFACE(Interfacep);
  282. DEREFERENCE_DHCP();
  283. } // DhcpReadCompletionRoutine
  284. VOID
  285. DhcpReadServerReplyCompletionRoutine(
  286. ULONG ErrorCode,
  287. ULONG BytesTransferred,
  288. PNH_BUFFER Bufferp
  289. )
  290. /*++
  291. Routine Description:
  292. This routine is invoked upon completion of a receive-operation
  293. on a socket bound to the DHCP client port, when the component
  294. is attempting to detect the presence of a DHCP server.
  295. Arguments:
  296. ErrorCode - system-supplied status code
  297. BytesTransferred - system-supplied byte count
  298. Bufferp - send buffer
  299. Return Value:
  300. none.
  301. Environment:
  302. Runs in the context of an RTUTILS.DLL worker thread upon removal
  303. of an I/O completion packet.
  304. A reference to the component will have been made on our behalf
  305. by 'NhReadDatagramSocket'.
  306. --*/
  307. {
  308. ULONG Address;
  309. ULONG Error;
  310. PDHCP_INTERFACE Interfacep;
  311. PROFILE("DhcpReadServerReplyCompletionRoutine");
  312. Interfacep = (PDHCP_INTERFACE)Bufferp->Context;
  313. if (ErrorCode) {
  314. NhTrace(
  315. TRACE_FLAG_IO,
  316. "DhcpReadServerReplyCompletionRoutine: error %d receiving %s",
  317. ErrorCode,
  318. INET_NTOA(Bufferp->Context2)
  319. );
  320. NhReleaseBuffer(Bufferp);
  321. DHCP_DEREFERENCE_INTERFACE(Interfacep);
  322. DEREFERENCE_DHCP();
  323. return;
  324. }
  325. ACQUIRE_LOCK(Interfacep);
  326. if (!DHCP_INTERFACE_ACTIVE(Interfacep)) {
  327. RELEASE_LOCK(Interfacep);
  328. NhReleaseBuffer(Bufferp);
  329. DHCP_DEREFERENCE_INTERFACE(Interfacep);
  330. DEREFERENCE_DHCP();
  331. return;
  332. }
  333. RELEASE_LOCK(Interfacep);
  334. //
  335. // Inspect the message read
  336. //
  337. Address = NhQueryAddressSocket(Bufferp->Socket);
  338. if (NhIsLocalAddress(Bufferp->ReadAddress.sin_addr.s_addr)) {
  339. NhTrace(
  340. TRACE_FLAG_IO,
  341. "DhcpReadServerReplyCompletionRoutine: ignoring, from self (%s)",
  342. INET_NTOA(Address)
  343. );
  344. } else {
  345. CHAR LocalAddress[16];
  346. lstrcpyA(LocalAddress, INET_NTOA(Address));
  347. NhTrace(
  348. TRACE_FLAG_IO,
  349. "DhcpReadServerReplyCompletionRoutine: %s found, disabling %d (%s)",
  350. INET_NTOA(Bufferp->ReadAddress.sin_addr),
  351. Interfacep->Index,
  352. LocalAddress
  353. );
  354. //
  355. // We received this from another server.
  356. // We'll need to disable this interface.
  357. //
  358. DhcpDisableInterface(Interfacep->Index);
  359. NhErrorLog(
  360. IP_AUTO_DHCP_LOG_DUPLICATE_SERVER,
  361. 0,
  362. "%I%I",
  363. Bufferp->ReadAddress.sin_addr.s_addr,
  364. Address
  365. );
  366. NhReleaseBuffer(Bufferp);
  367. DHCP_DEREFERENCE_INTERFACE(Interfacep);
  368. DEREFERENCE_DHCP();
  369. return;
  370. }
  371. //
  372. // We received it from ourselves.
  373. // Look for another server.
  374. //
  375. Error =
  376. NhReadDatagramSocket(
  377. &DhcpComponentReference,
  378. Bufferp->Socket,
  379. Bufferp,
  380. DhcpReadServerReplyCompletionRoutine,
  381. Bufferp->Context,
  382. Bufferp->Context2
  383. );
  384. if (Error) {
  385. NhTrace(
  386. TRACE_FLAG_IO,
  387. "DhcpReadServerReplyCompletionRoutine: error %d reposting %s",
  388. ErrorCode,
  389. INET_NTOA(Bufferp->Context2)
  390. );
  391. NhReleaseBuffer(Bufferp);
  392. NhWarningLog(
  393. IP_AUTO_DHCP_LOG_DETECTION_UNAVAILABLE,
  394. Error,
  395. "%I",
  396. Address
  397. );
  398. DHCP_DEREFERENCE_INTERFACE(Interfacep);
  399. DEREFERENCE_DHCP();
  400. return;
  401. }
  402. DEREFERENCE_DHCP();
  403. } // DhcpReadServerReplyCompletionRoutine
  404. VOID
  405. DhcpWriteClientRequestCompletionRoutine(
  406. ULONG ErrorCode,
  407. ULONG BytesTransferred,
  408. PNH_BUFFER Bufferp
  409. )
  410. /*++
  411. Routine Description:
  412. This routine is invoked upon completion of a send-operation
  413. on a socket bound to the DHCP client port, when the component
  414. is attempting to detect the presence of a DHCP server.
  415. Arguments:
  416. ErrorCode - system-supplied status code
  417. BytesTransferred - system-supplied byte count
  418. Bufferp - send buffer
  419. Return Value:
  420. none.
  421. Environment:
  422. Runs in the context of an RTUTILS.DLL worker thread upon removal
  423. of an I/O completion packet.
  424. A reference to the interface will have been made on our behalf
  425. by 'DhcpWriteClientRequestMessage'.
  426. A reference to the component will have been made on our behalf
  427. by 'NhWriteDatagramSocket'.
  428. --*/
  429. {
  430. PDHCP_INTERFACE Interfacep;
  431. ULONG Error;
  432. PROFILE("DhcpWriteClientRequestCompletionRoutine");
  433. Interfacep = (PDHCP_INTERFACE)Bufferp->Context;
  434. if (ErrorCode) {
  435. NhTrace(
  436. TRACE_FLAG_IO,
  437. "DhcpWriteClientRequestCompletionRoutine: error %d broadcast %s",
  438. ErrorCode,
  439. INET_NTOA(Bufferp->Context2)
  440. );
  441. NhWarningLog(
  442. IP_AUTO_DHCP_LOG_DETECTION_UNAVAILABLE,
  443. ErrorCode,
  444. "%I",
  445. NhQueryAddressSocket(Bufferp->Socket)
  446. );
  447. NhReleaseBuffer(Bufferp);
  448. DHCP_DEREFERENCE_INTERFACE(Interfacep);
  449. DEREFERENCE_DHCP();
  450. return;
  451. }
  452. ACQUIRE_LOCK(Interfacep);
  453. if (!DHCP_INTERFACE_ACTIVE(Interfacep)) {
  454. RELEASE_LOCK(Interfacep);
  455. NhReleaseBuffer(Bufferp);
  456. DHCP_DEREFERENCE_INTERFACE(Interfacep);
  457. DEREFERENCE_DHCP();
  458. return;
  459. }
  460. RELEASE_LOCK(Interfacep);
  461. //
  462. // Reuse the send buffer to listen for a response from the server
  463. //
  464. Error =
  465. NhReadDatagramSocket(
  466. &DhcpComponentReference,
  467. Bufferp->Socket,
  468. Bufferp,
  469. DhcpReadServerReplyCompletionRoutine,
  470. Bufferp->Context,
  471. Bufferp->Context2
  472. );
  473. if (Error) {
  474. NhTrace(
  475. TRACE_FLAG_IO,
  476. "DhcpWriteClientRequestCompletionRoutine: error %d receiving %s",
  477. ErrorCode,
  478. INET_NTOA(Bufferp->Context2)
  479. );
  480. NhWarningLog(
  481. IP_AUTO_DHCP_LOG_DETECTION_UNAVAILABLE,
  482. Error,
  483. "%I",
  484. NhQueryAddressSocket(Bufferp->Socket)
  485. );
  486. NhReleaseBuffer(Bufferp);
  487. DHCP_DEREFERENCE_INTERFACE(Interfacep);
  488. DEREFERENCE_DHCP();
  489. return;
  490. }
  491. DEREFERENCE_DHCP();
  492. } // DhcpWriteClientRequestCompletionRoutine
  493. VOID
  494. DhcpWriteCompletionRoutine(
  495. ULONG ErrorCode,
  496. ULONG BytesTransferred,
  497. PNH_BUFFER Bufferp
  498. )
  499. /*++
  500. Routine Description:
  501. This routine is invoked upon completion of a write-operation
  502. on a datagram socket bound to the DHCP server UDP port.
  503. Arguments:
  504. ErrorCode - Win32 status code for the I/O operation
  505. BytesTransferred - number of bytes in 'Bufferp'
  506. Bufferp - holds data read from the datagram socket
  507. Return Value:
  508. none.
  509. Environment:
  510. Runs in the context of an RTUTILS.DLL worker-thread which has just
  511. dequeued an I/O completion packet from the common I/O completion port
  512. with which our datagram sockets are associated.
  513. A reference to the interface will have been made on our behalf
  514. by the code which invoked 'NhWriteDatagramSocket'.
  515. A reference to the component will have been made on our behalf
  516. within 'NhWriteDatagramSocket'.
  517. --*/
  518. {
  519. PDHCP_INTERFACE Interfacep;
  520. PROFILE("DhcpWriteCompletionRoutine");
  521. Interfacep = (PDHCP_INTERFACE)Bufferp->Context;
  522. DHCP_DEREFERENCE_INTERFACE(Interfacep);
  523. NhReleaseBuffer(Bufferp);
  524. DEREFERENCE_DHCP();
  525. } // DhcpWriteCompletionRoutine