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.

591 lines
16 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. // Now look at the message
  123. //
  124. Headerp = (PDHCP_HEADER)Bufferp->Buffer;
  125. switch (Headerp->Operation) {
  126. case BOOTP_OPERATION_REQUEST: {
  127. DhcpProcessMessage(
  128. Interfacep,
  129. Bufferp
  130. );
  131. break;
  132. }
  133. case BOOTP_OPERATION_REPLY: {
  134. InterlockedIncrement(
  135. reinterpret_cast<LPLONG>(&DhcpStatistics.MessagesIgnored)
  136. );
  137. NhTrace(
  138. TRACE_FLAG_IO,
  139. "DhcpReadCompletionRoutine: ignoring BOOTPREPLY"
  140. );
  141. //
  142. // Repost the buffer for another read operation.
  143. //
  144. EnterCriticalSection(&DhcpInterfaceLock);
  145. if (!DHCP_REFERENCE_INTERFACE(Interfacep)) {
  146. LeaveCriticalSection(&DhcpInterfaceLock);
  147. NhReleaseBuffer(Bufferp);
  148. }
  149. else {
  150. LeaveCriticalSection(&DhcpInterfaceLock);
  151. Error =
  152. NhReadDatagramSocket(
  153. &DhcpComponentReference,
  154. Bufferp->Socket,
  155. Bufferp,
  156. DhcpReadCompletionRoutine,
  157. Bufferp->Context,
  158. Bufferp->Context2
  159. );
  160. if (Error) {
  161. ACQUIRE_LOCK(Interfacep);
  162. DhcpDeferReadInterface(Interfacep, Bufferp->Socket);
  163. RELEASE_LOCK(Interfacep);
  164. DHCP_DEREFERENCE_INTERFACE(Interfacep);
  165. NhWarningLog(
  166. IP_AUTO_DHCP_LOG_RECEIVE_FAILED,
  167. Error,
  168. "%I",
  169. NhQueryAddressSocket(Bufferp->Socket)
  170. );
  171. NhReleaseBuffer(Bufferp);
  172. }
  173. }
  174. break;
  175. }
  176. default: {
  177. InterlockedIncrement(
  178. reinterpret_cast<LPLONG>(&DhcpStatistics.MessagesIgnored)
  179. )
  180. ;
  181. NhTrace(
  182. TRACE_FLAG_IO,
  183. "DhcpReadCompletionRoutine: ignoring invalid BOOTP operation %d",
  184. Headerp->Operation
  185. );
  186. NhInformationLog(
  187. IP_AUTO_DHCP_LOG_INVALID_BOOTP_OPERATION,
  188. 0,
  189. "%d",
  190. Headerp->Operation
  191. );
  192. //
  193. // Repost the buffer for another read operation.
  194. //
  195. EnterCriticalSection(&DhcpInterfaceLock);
  196. if (!DHCP_REFERENCE_INTERFACE(Interfacep)) {
  197. LeaveCriticalSection(&DhcpInterfaceLock);
  198. NhReleaseBuffer(Bufferp);
  199. }
  200. else {
  201. LeaveCriticalSection(&DhcpInterfaceLock);
  202. Error =
  203. NhReadDatagramSocket(
  204. &DhcpComponentReference,
  205. Bufferp->Socket,
  206. Bufferp,
  207. DhcpReadCompletionRoutine,
  208. Bufferp->Context,
  209. Bufferp->Context2
  210. );
  211. if (Error) {
  212. ACQUIRE_LOCK(Interfacep);
  213. DhcpDeferReadInterface(Interfacep, Bufferp->Socket);
  214. RELEASE_LOCK(Interfacep);
  215. DHCP_DEREFERENCE_INTERFACE(Interfacep);
  216. NhWarningLog(
  217. IP_AUTO_DHCP_LOG_RECEIVE_FAILED,
  218. Error,
  219. "%I",
  220. NhQueryAddressSocket(Bufferp->Socket)
  221. );
  222. NhReleaseBuffer(Bufferp);
  223. }
  224. }
  225. break;
  226. }
  227. }
  228. } while(FALSE);
  229. DHCP_DEREFERENCE_INTERFACE(Interfacep);
  230. DEREFERENCE_DHCP();
  231. } // DhcpReadCompletionRoutine
  232. VOID
  233. DhcpReadServerReplyCompletionRoutine(
  234. ULONG ErrorCode,
  235. ULONG BytesTransferred,
  236. PNH_BUFFER Bufferp
  237. )
  238. /*++
  239. Routine Description:
  240. This routine is invoked upon completion of a receive-operation
  241. on a socket bound to the DHCP client port, when the component
  242. is attempting to detect the presence of a DHCP server.
  243. Arguments:
  244. ErrorCode - system-supplied status code
  245. BytesTransferred - system-supplied byte count
  246. Bufferp - send buffer
  247. Return Value:
  248. none.
  249. Environment:
  250. Runs in the context of an RTUTILS.DLL worker thread upon removal
  251. of an I/O completion packet.
  252. A reference to the component will have been made on our behalf
  253. by 'NhReadDatagramSocket'.
  254. --*/
  255. {
  256. ULONG Address;
  257. ULONG Error;
  258. PDHCP_INTERFACE Interfacep;
  259. PROFILE("DhcpReadServerReplyCompletionRoutine");
  260. Interfacep = (PDHCP_INTERFACE)Bufferp->Context;
  261. if (ErrorCode) {
  262. NhTrace(
  263. TRACE_FLAG_IO,
  264. "DhcpReadServerReplyCompletionRoutine: error %d receiving %s",
  265. ErrorCode,
  266. INET_NTOA(Bufferp->Context2)
  267. );
  268. NhReleaseBuffer(Bufferp);
  269. DHCP_DEREFERENCE_INTERFACE(Interfacep);
  270. DEREFERENCE_DHCP();
  271. return;
  272. }
  273. ACQUIRE_LOCK(Interfacep);
  274. if (!DHCP_INTERFACE_ACTIVE(Interfacep)) {
  275. RELEASE_LOCK(Interfacep);
  276. NhReleaseBuffer(Bufferp);
  277. DHCP_DEREFERENCE_INTERFACE(Interfacep);
  278. DEREFERENCE_DHCP();
  279. return;
  280. }
  281. RELEASE_LOCK(Interfacep);
  282. //
  283. // Inspect the message read
  284. //
  285. Address = NhQueryAddressSocket(Bufferp->Socket);
  286. if (NhIsLocalAddress(Bufferp->ReadAddress.sin_addr.s_addr)) {
  287. NhTrace(
  288. TRACE_FLAG_IO,
  289. "DhcpReadServerReplyCompletionRoutine: ignoring, from self (%s)",
  290. INET_NTOA(Address)
  291. );
  292. } else {
  293. CHAR LocalAddress[16];
  294. lstrcpyA(LocalAddress, INET_NTOA(Address));
  295. NhTrace(
  296. TRACE_FLAG_IO,
  297. "DhcpReadServerReplyCompletionRoutine: %s found, disabling %d (%s)",
  298. INET_NTOA(Bufferp->ReadAddress.sin_addr),
  299. Interfacep->Index,
  300. LocalAddress
  301. );
  302. //
  303. // We received this from another server.
  304. // We'll need to disable this interface.
  305. //
  306. DhcpDisableInterface(Interfacep->Index);
  307. NhErrorLog(
  308. IP_AUTO_DHCP_LOG_DUPLICATE_SERVER,
  309. 0,
  310. "%I%I",
  311. Bufferp->ReadAddress.sin_addr.s_addr,
  312. Address
  313. );
  314. NhReleaseBuffer(Bufferp);
  315. DHCP_DEREFERENCE_INTERFACE(Interfacep);
  316. DEREFERENCE_DHCP();
  317. return;
  318. }
  319. //
  320. // We received it from ourselves.
  321. // Look for another server.
  322. //
  323. Error =
  324. NhReadDatagramSocket(
  325. &DhcpComponentReference,
  326. Bufferp->Socket,
  327. Bufferp,
  328. DhcpReadServerReplyCompletionRoutine,
  329. Bufferp->Context,
  330. Bufferp->Context2
  331. );
  332. if (Error) {
  333. NhTrace(
  334. TRACE_FLAG_IO,
  335. "DhcpReadServerReplyCompletionRoutine: error %d reposting %s",
  336. ErrorCode,
  337. INET_NTOA(Bufferp->Context2)
  338. );
  339. NhReleaseBuffer(Bufferp);
  340. NhWarningLog(
  341. IP_AUTO_DHCP_LOG_DETECTION_UNAVAILABLE,
  342. Error,
  343. "%I",
  344. Address
  345. );
  346. DHCP_DEREFERENCE_INTERFACE(Interfacep);
  347. DEREFERENCE_DHCP();
  348. return;
  349. }
  350. DEREFERENCE_DHCP();
  351. } // DhcpReadServerReplyCompletionRoutine
  352. VOID
  353. DhcpWriteClientRequestCompletionRoutine(
  354. ULONG ErrorCode,
  355. ULONG BytesTransferred,
  356. PNH_BUFFER Bufferp
  357. )
  358. /*++
  359. Routine Description:
  360. This routine is invoked upon completion of a send-operation
  361. on a socket bound to the DHCP client port, when the component
  362. is attempting to detect the presence of a DHCP server.
  363. Arguments:
  364. ErrorCode - system-supplied status code
  365. BytesTransferred - system-supplied byte count
  366. Bufferp - send buffer
  367. Return Value:
  368. none.
  369. Environment:
  370. Runs in the context of an RTUTILS.DLL worker thread upon removal
  371. of an I/O completion packet.
  372. A reference to the interface will have been made on our behalf
  373. by 'DhcpWriteClientRequestMessage'.
  374. A reference to the component will have been made on our behalf
  375. by 'NhWriteDatagramSocket'.
  376. --*/
  377. {
  378. PDHCP_INTERFACE Interfacep;
  379. ULONG Error;
  380. PROFILE("DhcpWriteClientRequestCompletionRoutine");
  381. Interfacep = (PDHCP_INTERFACE)Bufferp->Context;
  382. if (ErrorCode) {
  383. NhTrace(
  384. TRACE_FLAG_IO,
  385. "DhcpWriteClientRequestCompletionRoutine: error %d broadcast %s",
  386. ErrorCode,
  387. INET_NTOA(Bufferp->Context2)
  388. );
  389. NhWarningLog(
  390. IP_AUTO_DHCP_LOG_DETECTION_UNAVAILABLE,
  391. ErrorCode,
  392. "%I",
  393. NhQueryAddressSocket(Bufferp->Socket)
  394. );
  395. NhReleaseBuffer(Bufferp);
  396. DHCP_DEREFERENCE_INTERFACE(Interfacep);
  397. DEREFERENCE_DHCP();
  398. return;
  399. }
  400. ACQUIRE_LOCK(Interfacep);
  401. if (!DHCP_INTERFACE_ACTIVE(Interfacep)) {
  402. RELEASE_LOCK(Interfacep);
  403. NhReleaseBuffer(Bufferp);
  404. DHCP_DEREFERENCE_INTERFACE(Interfacep);
  405. DEREFERENCE_DHCP();
  406. return;
  407. }
  408. RELEASE_LOCK(Interfacep);
  409. //
  410. // Reuse the send buffer to listen for a response from the server
  411. //
  412. Error =
  413. NhReadDatagramSocket(
  414. &DhcpComponentReference,
  415. Bufferp->Socket,
  416. Bufferp,
  417. DhcpReadServerReplyCompletionRoutine,
  418. Bufferp->Context,
  419. Bufferp->Context2
  420. );
  421. if (Error) {
  422. NhTrace(
  423. TRACE_FLAG_IO,
  424. "DhcpWriteClientRequestCompletionRoutine: error %d receiving %s",
  425. ErrorCode,
  426. INET_NTOA(Bufferp->Context2)
  427. );
  428. NhWarningLog(
  429. IP_AUTO_DHCP_LOG_DETECTION_UNAVAILABLE,
  430. Error,
  431. "%I",
  432. NhQueryAddressSocket(Bufferp->Socket)
  433. );
  434. NhReleaseBuffer(Bufferp);
  435. DHCP_DEREFERENCE_INTERFACE(Interfacep);
  436. DEREFERENCE_DHCP();
  437. return;
  438. }
  439. DEREFERENCE_DHCP();
  440. } // DhcpWriteClientRequestCompletionRoutine
  441. VOID
  442. DhcpWriteCompletionRoutine(
  443. ULONG ErrorCode,
  444. ULONG BytesTransferred,
  445. PNH_BUFFER Bufferp
  446. )
  447. /*++
  448. Routine Description:
  449. This routine is invoked upon completion of a write-operation
  450. on a datagram socket bound to the DHCP server UDP port.
  451. Arguments:
  452. ErrorCode - Win32 status code for the I/O operation
  453. BytesTransferred - number of bytes in 'Bufferp'
  454. Bufferp - holds data read from the datagram socket
  455. Return Value:
  456. none.
  457. Environment:
  458. Runs in the context of an RTUTILS.DLL worker-thread which has just
  459. dequeued an I/O completion packet from the common I/O completion port
  460. with which our datagram sockets are associated.
  461. A reference to the interface will have been made on our behalf
  462. by the code which invoked 'NhWriteDatagramSocket'.
  463. A reference to the component will have been made on our behalf
  464. within 'NhWriteDatagramSocket'.
  465. --*/
  466. {
  467. PDHCP_INTERFACE Interfacep;
  468. PROFILE("DhcpWriteCompletionRoutine");
  469. Interfacep = (PDHCP_INTERFACE)Bufferp->Context;
  470. DHCP_DEREFERENCE_INTERFACE(Interfacep);
  471. NhReleaseBuffer(Bufferp);
  472. DEREFERENCE_DHCP();
  473. } // DhcpWriteCompletionRoutine