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.

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