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.

409 lines
12 KiB

  1. /*++
  2. Copyright (c) 1998, Microsoft Corporation
  3. Module Name:
  4. dnsio.c
  5. Abstract:
  6. This module contains code for the DNS allocator's network I/O completion
  7. routines.
  8. Author:
  9. Abolade Gbadegesin (aboladeg) 9-Mar-1998
  10. Revision History:
  11. Raghu Gatta (rgatta) 28-Mar-2002
  12. Note: bunch of reposts - due to accumulated patching - need to cleanup.
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. #include "dnsmsg.h"
  17. VOID
  18. DnsReadCompletionRoutine(
  19. ULONG ErrorCode,
  20. ULONG BytesTransferred,
  21. PNH_BUFFER Bufferp
  22. )
  23. /*++
  24. Routine Description:
  25. This routine is invoked upon completion of a read operation
  26. on a datagram socket bound to the DNS server UDP port.
  27. The message read is validated and processed; the processing may involve
  28. creating a query-record and forwarding the query to a server, or
  29. matching a response to an existing query-record and forwarding the
  30. response to the appropriate client.
  31. Arguments:
  32. ErrorCode - Win32 status code for the I/O operation
  33. BytesTransferred - number of bytes in 'Bufferp'
  34. Bufferp - holds data read from the datagram socket
  35. Return Value:
  36. none.
  37. Environment:
  38. Runs in the context of an RTUTILS.DLL worker-thread which has just
  39. dequeued an I/O completion packet from the common I/O completion port
  40. with which our datagram sockets are associated.
  41. A reference to the component will have been made on our behalf
  42. by 'NhReadDatagramSocket'.
  43. --*/
  44. {
  45. ULONG Error;
  46. PDNS_HEADER Headerp;
  47. PDNS_INTERFACE Interfacep;
  48. PROFILE("DnsReadCompletionRoutine");
  49. do {
  50. //
  51. // There are two cases where we don't process the message;
  52. // (a) the I/O operation failed
  53. // (b) the interface is no longer active
  54. // In case (a), we repost the buffer; in case (b), we do not.
  55. //
  56. Interfacep = (PDNS_INTERFACE)Bufferp->Context;
  57. //
  58. // First look for an error code
  59. //
  60. if (ErrorCode) {
  61. NhTrace(
  62. TRACE_FLAG_IO,
  63. "DnsReadCompletionRoutine: error %d for read-context %x",
  64. ErrorCode,
  65. Bufferp->Context
  66. );
  67. //
  68. // See if the interface is still active
  69. //
  70. ACQUIRE_LOCK(Interfacep);
  71. if (!DNS_INTERFACE_ACTIVE(Interfacep)) {
  72. RELEASE_LOCK(Interfacep);
  73. NhReleaseBuffer(Bufferp);
  74. } else {
  75. RELEASE_LOCK(Interfacep);
  76. EnterCriticalSection(&DnsInterfaceLock);
  77. if (!DNS_REFERENCE_INTERFACE(Interfacep)) {
  78. LeaveCriticalSection(&DnsInterfaceLock);
  79. NhReleaseBuffer(Bufferp);
  80. } else {
  81. LeaveCriticalSection(&DnsInterfaceLock);
  82. //
  83. // Repost the buffer for another read operation
  84. //
  85. do {
  86. Error =
  87. NhReadDatagramSocket(
  88. &DnsComponentReference,
  89. Bufferp->Socket,
  90. Bufferp,
  91. DnsReadCompletionRoutine,
  92. Bufferp->Context,
  93. Bufferp->Context2
  94. );
  95. //
  96. // A connection-reset error indicates that our last
  97. // *send* could not be delivered at its destination.
  98. // We could hardly care less; so issue the read again,
  99. // immediately.
  100. //
  101. } while (Error == WSAECONNRESET);
  102. if (Error) {
  103. ACQUIRE_LOCK(Interfacep);
  104. DnsDeferReadInterface(Interfacep, Bufferp->Socket);
  105. RELEASE_LOCK(Interfacep);
  106. DNS_DEREFERENCE_INTERFACE(Interfacep);
  107. NhWarningLog(
  108. IP_DNS_PROXY_LOG_RECEIVE_FAILED,
  109. Error,
  110. "%I",
  111. NhQueryAddressSocket(Bufferp->Socket)
  112. );
  113. NhReleaseBuffer(Bufferp);
  114. }
  115. }
  116. }
  117. break;
  118. }
  119. //
  120. // Now see if the interface is operational
  121. //
  122. ACQUIRE_LOCK(Interfacep);
  123. if (!DNS_INTERFACE_ACTIVE(Interfacep)) {
  124. RELEASE_LOCK(Interfacep);
  125. NhReleaseBuffer(Bufferp);
  126. NhTrace(
  127. TRACE_FLAG_IO,
  128. "DnsReadCompletionRoutine: interface %d inactive",
  129. Interfacep->Index
  130. );
  131. break;
  132. }
  133. RELEASE_LOCK(Interfacep);
  134. //
  135. // Ensure minimum DNS_HEADER size
  136. //
  137. if (BytesTransferred < sizeof(DNS_HEADER)) {
  138. NhTrace(
  139. TRACE_FLAG_DNS,
  140. "DnsReadCompletionRoutine: message size %d too small",
  141. BytesTransferred
  142. );
  143. NhWarningLog(
  144. IP_DNS_PROXY_LOG_MESSAGE_TOO_SMALL,
  145. 0,
  146. ""
  147. );
  148. InterlockedIncrement(
  149. reinterpret_cast<LPLONG>(&DnsStatistics.MessagesIgnored)
  150. );
  151. //
  152. // Repost read
  153. //
  154. EnterCriticalSection(&DnsInterfaceLock);
  155. if (!DNS_REFERENCE_INTERFACE(Interfacep)) {
  156. LeaveCriticalSection(&DnsInterfaceLock);
  157. NhReleaseBuffer(Bufferp);
  158. } else {
  159. LeaveCriticalSection(&DnsInterfaceLock);
  160. do {
  161. Error =
  162. NhReadDatagramSocket(
  163. &DnsComponentReference,
  164. Bufferp->Socket,
  165. Bufferp,
  166. DnsReadCompletionRoutine,
  167. Bufferp->Context,
  168. Bufferp->Context2
  169. );
  170. //
  171. // A connection-reset error indicates that our last
  172. // *send* could not be delivered at its destination.
  173. // We could hardly care less; so issue the read again,
  174. // immediately.
  175. //
  176. } while (Error == WSAECONNRESET);
  177. if (Error) {
  178. ACQUIRE_LOCK(Interfacep);
  179. DnsDeferReadInterface(Interfacep, Bufferp->Socket);
  180. RELEASE_LOCK(Interfacep);
  181. DNS_DEREFERENCE_INTERFACE(Interfacep);
  182. NhWarningLog(
  183. IP_DNS_PROXY_LOG_RECEIVE_FAILED,
  184. Error,
  185. "%I",
  186. NhQueryAddressSocket(Bufferp->Socket)
  187. );
  188. NhReleaseBuffer(Bufferp);
  189. }
  190. }
  191. break;
  192. }
  193. //
  194. // Now look at the message
  195. //
  196. Headerp = (PDNS_HEADER)Bufferp->Buffer;
  197. if (Headerp->IsResponse == DNS_MESSAGE_QUERY) {
  198. DnsProcessQueryMessage(
  199. Interfacep,
  200. Bufferp
  201. );
  202. } else {
  203. DnsProcessResponseMessage(
  204. Interfacep,
  205. Bufferp
  206. );
  207. }
  208. } while(FALSE);
  209. DNS_DEREFERENCE_INTERFACE(Interfacep);
  210. DEREFERENCE_DNS();
  211. } // DnsReadCompletionRoutine
  212. VOID
  213. DnsWriteCompletionRoutine(
  214. ULONG ErrorCode,
  215. ULONG BytesTransferred,
  216. PNH_BUFFER Bufferp
  217. )
  218. /*++
  219. Routine Description:
  220. This routine is invoked upon completion of a write-operation
  221. on a datagram socket bound to the DNS server UDP port.
  222. The write-context for all writes is a 'DNS_QUERY'. Our handling
  223. is dependent on whether the message written was a query or a response.
  224. Upon completion of a query, we may need to do a resend if there was
  225. an error. Upon completion of a response, we delete the query-record.
  226. Arguments:
  227. ErrorCode - Win32 status code for the I/O operation
  228. BytesTransferred - number of bytes in 'Bufferp'
  229. Bufferp - holds data read from the datagram socket
  230. Return Value:
  231. none.
  232. Environment:
  233. Runs in the context of an RTUTILS.DLL worker-thread which has just
  234. dequeued an I/O completion packet from the common I/O completion port
  235. with which our datagram sockets are associated.
  236. A reference to the component will have been made on our behalf
  237. by 'NhReadDatagramSocket'.
  238. --*/
  239. {
  240. ULONG Error;
  241. PDNS_HEADER Headerp;
  242. PDNS_INTERFACE Interfacep;
  243. USHORT QueryId;
  244. PDNS_QUERY Queryp;
  245. PULONG Server;
  246. PROFILE("DnsWriteCompletionRoutine");
  247. Interfacep = (PDNS_INTERFACE)Bufferp->Context;
  248. QueryId = (USHORT)Bufferp->Context2;
  249. Headerp = (PDNS_HEADER)Bufferp->Buffer;
  250. ACQUIRE_LOCK(Interfacep);
  251. //
  252. // Obtain the query associated with the send.
  253. //
  254. Queryp = DnsMapResponseToQuery(Interfacep, QueryId);
  255. if (Headerp->IsResponse == DNS_MESSAGE_RESPONSE) {
  256. if (ErrorCode) {
  257. //
  258. // An error occurred sending the message to the client
  259. //
  260. NhTrace(
  261. TRACE_FLAG_DNS,
  262. "DnsWriteCompletionRoutine: error %d response %d interface %d",
  263. ErrorCode,
  264. Queryp ? Queryp->QueryId : -1,
  265. Interfacep->Index
  266. );
  267. NhWarningLog(
  268. IP_DNS_PROXY_LOG_RESPONSE_FAILED,
  269. ErrorCode,
  270. "%I",
  271. NhQueryAddressSocket(Bufferp->Socket)
  272. );
  273. } else if (Queryp && Headerp->ResponseCode == DNS_RCODE_NOERROR) {
  274. //
  275. // We're done with this query since it succeeded; remove it.
  276. //
  277. NhTrace(
  278. TRACE_FLAG_DNS,
  279. "DnsWriteCompletionRoutine: removing query %d interface %d",
  280. Queryp->QueryId,
  281. Interfacep->Index
  282. );
  283. DnsDeleteQuery(Interfacep, Queryp);
  284. }
  285. } else {
  286. if (!ErrorCode) {
  287. //
  288. // No errors, so just return.
  289. //
  290. NhTrace(
  291. TRACE_FLAG_DNS,
  292. "DnsWriteCompletionRoutine: sent query %d interface %d",
  293. Queryp ? Queryp->QueryId : -1,
  294. Interfacep->Index
  295. );
  296. } else {
  297. //
  298. // The query just went out and it failed.
  299. //
  300. NhTrace(
  301. TRACE_FLAG_DNS,
  302. "DnsWriteCompletionRoutine: error %d for query %d interface %d",
  303. ErrorCode,
  304. Queryp ? Queryp->QueryId : -1,
  305. Interfacep->Index
  306. );
  307. NhWarningLog(
  308. IP_DNS_PROXY_LOG_QUERY_FAILED,
  309. ErrorCode,
  310. "%I%I%I",
  311. Queryp ? Queryp->SourceAddress : -1,
  312. Bufferp->WriteAddress.sin_addr.s_addr,
  313. NhQueryAddressSocket(Bufferp->Socket)
  314. );
  315. }
  316. }
  317. RELEASE_LOCK(Interfacep);
  318. DNS_DEREFERENCE_INTERFACE(Interfacep);
  319. NhReleaseBuffer(Bufferp);
  320. DEREFERENCE_DNS();
  321. } // DnsWriteCompletionRoutine