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.

914 lines
28 KiB

  1. /*++
  2. Copyright (c) 1998, Microsoft Corporation
  3. Module Name:
  4. dnsmsg.c
  5. Abstract:
  6. This module contains code for the DNS proxy's message-processing.
  7. Author:
  8. Abolade Gbadegesin (aboladeg) 9-Mar-1998
  9. Revision History:
  10. Raghu Gatta (rgatta) 1-Dec-2000
  11. Rewrite + Cleanup + New Functions
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. //
  16. // EXTERNAL DECLARATIONS
  17. //
  18. extern "C" DWORD G_UseEdns;
  19. VOID
  20. DnsProcessQueryMessage(
  21. PDNS_INTERFACE Interfacep,
  22. PNH_BUFFER Bufferp
  23. )
  24. /*++
  25. Routine Description:
  26. This routine is invoked to process a DNS query message.
  27. Arguments:
  28. Interfacep - the interface on which the query was received
  29. Bufferp - the buffer containing the query
  30. Return Value:
  31. none.
  32. Environment:
  33. Invoked internally in the context of a worker-thread completion routine,
  34. with an outstanding reference to 'Interfacep' from the time the
  35. read-operation was begun.
  36. --*/
  37. {
  38. PVOID Context;
  39. PVOID Context2;
  40. ULONG Error;
  41. PDNS_QUERY Queryp;
  42. PDNS_HEADER Headerp;
  43. BOOLEAN Referenced = TRUE;
  44. SOCKET Socket;
  45. LPVOID lpMsgBuf;
  46. PROFILE("DnsProcessQueryMessage");
  47. #if DBG
  48. NhTrace(
  49. TRACE_FLAG_DNS,
  50. "DnsProcessQueryMessage: dumping %d bytes",
  51. Bufferp->BytesTransferred
  52. );
  53. NhDump(
  54. TRACE_FLAG_DNS,
  55. Bufferp->Buffer,
  56. Bufferp->BytesTransferred,
  57. 1
  58. );
  59. #endif
  60. InterlockedIncrement(
  61. reinterpret_cast<LPLONG>(&DnsStatistics.QueriesReceived)
  62. );
  63. Headerp = (PDNS_HEADER)Bufferp->Buffer;
  64. Socket = Bufferp->Socket;
  65. Context = Bufferp->Context;
  66. Context2 = Bufferp->Context2;
  67. //
  68. // if the Broadcast bit (9) was set, we leave it as is
  69. // instead of zeroing it
  70. //
  71. //if (Headerp->Broadcast) {
  72. // Headerp->Broadcast = 0;
  73. //}
  74. ASSERT(Headerp->Opcode != DNS_OPCODE_IQUERY);
  75. ASSERT(Headerp->Opcode != DNS_OPCODE_SERVER_STATUS);
  76. if (Headerp->Opcode == DNS_OPCODE_QUERY) {
  77. //
  78. // Query the local DNS Resolver cache before proxying
  79. //
  80. //
  81. // Unpack
  82. //
  83. DNS_STATUS dnsStatus;
  84. DNS_PARSED_MESSAGE dnsParsedMsg;
  85. PDNS_MESSAGE_BUFFER pDnsBuffer = NULL;
  86. PDNS_MSG_BUF pDnsMsgBuf = NULL;
  87. PDNS_RECORD pQueryResultsSet = NULL;
  88. WORD wMessageLength;
  89. DWORD dwFlags, dwQueryOptions;
  90. DNS_CHARSET CharSet;
  91. BOOL fQ4DefaultSuffix = FALSE;
  92. ZeroMemory(&dnsParsedMsg, sizeof(DNS_PARSED_MESSAGE));
  93. pDnsBuffer = (PDNS_MESSAGE_BUFFER) Headerp;
  94. wMessageLength = (WORD) Bufferp->BytesTransferred;
  95. dwFlags = DNS_PARSE_FLAG_ONLY_QUESTION;
  96. CharSet = DnsCharSetUtf8;
  97. //
  98. // Dns* functions require byte flipping
  99. //
  100. DNS_BYTE_FLIP_HEADER_COUNTS(&pDnsBuffer->MessageHead);
  101. dnsStatus = Dns_ParseMessage(
  102. &dnsParsedMsg,
  103. pDnsBuffer,
  104. wMessageLength,
  105. dwFlags,
  106. CharSet
  107. );
  108. if (NO_ERROR == dnsStatus)
  109. {
  110. NhTrace(
  111. TRACE_FLAG_DNS,
  112. "DnsProcessQueryMessage: Dns_ParseMessage succeeded!!"
  113. );
  114. //
  115. // Make a note of whether this question was for our private
  116. // default domain (ie mshome.net)
  117. //
  118. {
  119. //
  120. // the question name is in UTF_8 form
  121. //
  122. PWCHAR pszQName = NULL;
  123. DWORD dwSize;
  124. dwSize = DnsGetBufferLengthForStringCopy(
  125. (char *)dnsParsedMsg.pQuestionName,
  126. 0, // the function calculates it
  127. FALSE, // DnsCharSetUtf8
  128. TRUE // DnsCharSetUnicode
  129. );
  130. if (!dwSize)
  131. {
  132. //
  133. // invalid input string
  134. //
  135. DWORD dwRet = GetLastError();
  136. lpMsgBuf = NULL;
  137. FormatMessage(
  138. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  139. FORMAT_MESSAGE_FROM_SYSTEM |
  140. FORMAT_MESSAGE_IGNORE_INSERTS,
  141. NULL,
  142. dwRet,
  143. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  144. (LPTSTR) &lpMsgBuf,
  145. 0,
  146. NULL
  147. );
  148. NhTrace(
  149. TRACE_FLAG_DNS,
  150. "DnsProcessQueryMessage: DnsGetBufferLengthForStringCopy"
  151. " returned (0x%08x) %S",
  152. dwRet,
  153. lpMsgBuf
  154. );
  155. if (lpMsgBuf) LocalFree(lpMsgBuf);
  156. }
  157. else
  158. {
  159. pszQName = reinterpret_cast<PWCHAR>(NH_ALLOCATE(dwSize));
  160. if (!pszQName)
  161. {
  162. NhTrace(
  163. TRACE_FLAG_DNS,
  164. "DnsProcessQueryMessage: allocation "
  165. "failed for pszQName"
  166. );
  167. }
  168. else
  169. {
  170. DWORD dwUtf8Size = strlen((char *)dnsParsedMsg.pQuestionName);
  171. ZeroMemory(pszQName, dwSize);
  172. DnsUtf8ToUnicode(
  173. (char *)dnsParsedMsg.pQuestionName,
  174. dwUtf8Size,
  175. pszQName,
  176. dwSize
  177. );
  178. fQ4DefaultSuffix = IsSuffixValid(
  179. pszQName,
  180. DNS_HOMENET_SUFFIX
  181. );
  182. NhTrace(
  183. TRACE_FLAG_DNS,
  184. "DnsProcessQueryMessage: %S (%s)",
  185. pszQName,
  186. (fQ4DefaultSuffix?"TRUE":"FALSE")
  187. );
  188. NH_FREE(pszQName);
  189. }
  190. }
  191. }
  192. //
  193. // Query
  194. //
  195. dwQueryOptions = (
  196. DNS_QUERY_STANDARD |
  197. DNS_QUERY_CACHE_ONLY |
  198. DNS_QUERY_TREAT_AS_FQDN |
  199. //DNS_QUERY_ALLOW_EMPTY_AUTH_RESP |
  200. 0
  201. );
  202. dnsStatus = DnsQuery_UTF8(
  203. (LPSTR) dnsParsedMsg.pQuestionName,
  204. dnsParsedMsg.QuestionType,
  205. dwQueryOptions,
  206. NULL,
  207. &pQueryResultsSet,
  208. NULL
  209. );
  210. }
  211. if (dnsStatus)
  212. {
  213. lpMsgBuf = NULL;
  214. FormatMessage(
  215. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  216. FORMAT_MESSAGE_FROM_SYSTEM |
  217. FORMAT_MESSAGE_IGNORE_INSERTS,
  218. NULL,
  219. dnsStatus,
  220. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  221. (LPTSTR) &lpMsgBuf,
  222. 0,
  223. NULL
  224. );
  225. NhTrace(
  226. TRACE_FLAG_DNS,
  227. "DnsProcessQueryMessage: (0x%08x) %S",
  228. dnsStatus,
  229. lpMsgBuf
  230. );
  231. if (lpMsgBuf) LocalFree(lpMsgBuf);
  232. }
  233. if ((NO_ERROR == dnsStatus) &&
  234. (pQueryResultsSet) // ??? what do i check to see if
  235. // there was actually something useful
  236. // returned from the cache
  237. )
  238. {
  239. NhTrace(
  240. TRACE_FLAG_DNS,
  241. "DnsProcessQueryMessage: results found in the local DNS Resolver Cache"
  242. );
  243. //
  244. // Pack & Send back answer; return
  245. //
  246. // set response bit
  247. dnsParsedMsg.Header.IsResponse = 1;
  248. // set the section field of every DNS_RECORD given to us
  249. // *** NEED TO CHANGE THIS LATER ***
  250. PDNS_RECORD pRR = pQueryResultsSet;
  251. DWORD cnt = 0;
  252. while (pRR)
  253. {
  254. pRR->Flags.S.Section = 1;
  255. cnt++;
  256. pRR = pRR->pNext;
  257. }
  258. NhTrace(
  259. TRACE_FLAG_DNS,
  260. "DnsProcessQueryMessage: %d records",
  261. cnt
  262. );
  263. // set global EDNS OPT field to 0 every time
  264. // *** NEED TO CHANGE THIS LATER ***
  265. //G_UseEdns = 0;
  266. pDnsMsgBuf = Dns_BuildPacket(
  267. &dnsParsedMsg.Header, // ??? parsed message header should be OK
  268. TRUE, // ??? no header count copy - counts done automatically?
  269. dnsParsedMsg.pQuestionName,
  270. dnsParsedMsg.QuestionType,
  271. pQueryResultsSet,
  272. dwQueryOptions,
  273. TRUE // set to update because of G_UseEdns workaround
  274. );
  275. if (NULL == pDnsMsgBuf)
  276. {
  277. lpMsgBuf = NULL;
  278. FormatMessage(
  279. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  280. FORMAT_MESSAGE_FROM_SYSTEM |
  281. FORMAT_MESSAGE_IGNORE_INSERTS,
  282. NULL,
  283. GetLastError(),
  284. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  285. (LPTSTR) &lpMsgBuf,
  286. 0,
  287. NULL
  288. );
  289. NhTrace(
  290. TRACE_FLAG_DNS,
  291. "DnsProcessQueryMessage: Dns_BuildPacket failed (%S)",
  292. lpMsgBuf
  293. );
  294. if (lpMsgBuf) LocalFree(lpMsgBuf);
  295. }
  296. else
  297. {
  298. DWORD dwDnsPktSize = (DWORD)(sizeof(DNS_HEADER) +
  299. ((PCHAR)pDnsMsgBuf->pCurrent -
  300. (PCHAR)pDnsMsgBuf->MessageBody));
  301. NhTrace(
  302. TRACE_FLAG_DNS,
  303. "DnsProcessQueryMessage: Dns_BuildPacket returned pkt of size %d (%d) bytes",
  304. dwDnsPktSize,
  305. DNS_MESSAGE_OFFSET(pDnsMsgBuf, pDnsMsgBuf->pCurrent)
  306. );
  307. //
  308. // send back the answer retrieved from the cache
  309. //
  310. PNH_BUFFER NewBufferp = NhAcquireVariableLengthBuffer(
  311. dwDnsPktSize
  312. );
  313. if (!NewBufferp)
  314. {
  315. NhTrace(
  316. TRACE_FLAG_DNS,
  317. "DnsProcessQueryMessage: could not acquire buffer"
  318. );
  319. }
  320. else
  321. {
  322. //
  323. // Dns* functions return in host order ???
  324. //
  325. DNS_BYTE_FLIP_HEADER_COUNTS(&pDnsMsgBuf->MessageHead);
  326. //
  327. // Reference the interface now since we are replying
  328. // to the query
  329. //
  330. EnterCriticalSection(&DnsInterfaceLock);
  331. if (!DNS_REFERENCE_INTERFACE(Interfacep))
  332. {
  333. LeaveCriticalSection(&DnsInterfaceLock);
  334. Referenced = FALSE;
  335. }
  336. else
  337. {
  338. LeaveCriticalSection(&DnsInterfaceLock);
  339. ACQUIRE_LOCK(Interfacep);
  340. memcpy(
  341. NewBufferp->Buffer,
  342. &pDnsMsgBuf->MessageHead,
  343. dwDnsPktSize
  344. );
  345. Error =
  346. NhWriteDatagramSocket(
  347. &DnsComponentReference,
  348. Bufferp->Socket,
  349. Bufferp->ReadAddress.sin_addr.s_addr,
  350. Bufferp->ReadAddress.sin_port,
  351. NewBufferp,
  352. dwDnsPktSize,
  353. DnsWriteCompletionRoutine,
  354. Interfacep,
  355. NULL
  356. );
  357. RELEASE_LOCK(Interfacep);
  358. if (!Error)
  359. {
  360. InterlockedIncrement(
  361. reinterpret_cast<LPLONG>(&DnsStatistics.ResponsesSent)
  362. );
  363. }
  364. else
  365. {
  366. NhReleaseBuffer(NewBufferp);
  367. DNS_DEREFERENCE_INTERFACE(Interfacep);
  368. NhWarningLog(
  369. IP_DNS_PROXY_LOG_RESPONSE_FAILED,
  370. Error,
  371. "%I",
  372. NhQueryAddressSocket(Socket)
  373. );
  374. }
  375. }
  376. }
  377. DnsFree(pDnsMsgBuf, DnsFreeFlat);
  378. }
  379. // buffer is reposted below
  380. }
  381. else
  382. if (//(DNS_ERROR_RECORD_DOES_NOT_EXIST == dnsStatus) &&
  383. (fQ4DefaultSuffix))
  384. {
  385. //
  386. // this was a question for our default suffix
  387. // we send a name error reply back to the client
  388. // - note however that we dont publish an SOA
  389. // record for our default suffix domain
  390. //
  391. //
  392. // Undoing Flip above
  393. //
  394. DNS_BYTE_FLIP_HEADER_COUNTS(&pDnsBuffer->MessageHead);
  395. DWORD dwDnsPktSize = Bufferp->BytesTransferred;
  396. NhTrace(
  397. TRACE_FLAG_DNS,
  398. "DnsProcessQueryMessage: returning error message"
  399. );
  400. //
  401. // send back the negative answer
  402. //
  403. PNH_BUFFER NewBufferp = NhAcquireVariableLengthBuffer(
  404. dwDnsPktSize
  405. );
  406. if (!NewBufferp)
  407. {
  408. NhTrace(
  409. TRACE_FLAG_DNS,
  410. "DnsProcessQueryMessage: could not acquire buffer"
  411. );
  412. }
  413. else
  414. {
  415. //
  416. // Reference the interface now since we are replying
  417. // to the query
  418. //
  419. EnterCriticalSection(&DnsInterfaceLock);
  420. if (!DNS_REFERENCE_INTERFACE(Interfacep))
  421. {
  422. LeaveCriticalSection(&DnsInterfaceLock);
  423. Referenced = FALSE;
  424. }
  425. else
  426. {
  427. LeaveCriticalSection(&DnsInterfaceLock);
  428. ACQUIRE_LOCK(Interfacep);
  429. memcpy(
  430. NewBufferp->Buffer,
  431. Bufferp->Buffer,
  432. dwDnsPktSize
  433. );
  434. PDNS_HEADER NewHeaderp = (PDNS_HEADER)NewBufferp->Buffer;
  435. //
  436. // set response bit
  437. //
  438. NewHeaderp->IsResponse = 1;
  439. //
  440. // set "Name does not exist" error in the RCode field
  441. //
  442. NewHeaderp->ResponseCode = DNS_RCODE_NXDOMAIN;
  443. Error =
  444. NhWriteDatagramSocket(
  445. &DnsComponentReference,
  446. Bufferp->Socket,
  447. Bufferp->ReadAddress.sin_addr.s_addr,
  448. Bufferp->ReadAddress.sin_port,
  449. NewBufferp,
  450. dwDnsPktSize,
  451. DnsWriteCompletionRoutine,
  452. Interfacep,
  453. NULL
  454. );
  455. RELEASE_LOCK(Interfacep);
  456. if (!Error)
  457. {
  458. InterlockedIncrement(
  459. reinterpret_cast<LPLONG>(&DnsStatistics.ResponsesSent)
  460. );
  461. }
  462. else
  463. {
  464. NhReleaseBuffer(NewBufferp);
  465. DNS_DEREFERENCE_INTERFACE(Interfacep);
  466. NhWarningLog(
  467. IP_DNS_PROXY_LOG_RESPONSE_FAILED,
  468. Error,
  469. "%I",
  470. NhQueryAddressSocket(Socket)
  471. );
  472. }
  473. }
  474. }
  475. // buffer is reposted below
  476. }
  477. else
  478. {
  479. //
  480. // Undoing Flip above
  481. //
  482. DNS_BYTE_FLIP_HEADER_COUNTS(&pDnsBuffer->MessageHead);
  483. //
  484. // Reference the interface now in case we need to forward the query
  485. //
  486. EnterCriticalSection(&DnsInterfaceLock);
  487. if (DNS_REFERENCE_INTERFACE(Interfacep))
  488. {
  489. LeaveCriticalSection(&DnsInterfaceLock);
  490. }
  491. else
  492. {
  493. LeaveCriticalSection(&DnsInterfaceLock);
  494. Referenced = FALSE;
  495. }
  496. ACQUIRE_LOCK(Interfacep);
  497. //
  498. // See if this query is already pending;
  499. // if not, create a record for it on the receiving interface.
  500. //
  501. if (DnsIsPendingQuery(Interfacep, Bufferp))
  502. {
  503. RELEASE_LOCK(Interfacep);
  504. NhTrace(
  505. TRACE_FLAG_DNS,
  506. "DnsProcessQueryMessage: query already pending"
  507. );
  508. if (Referenced)
  509. {
  510. DNS_DEREFERENCE_INTERFACE(Interfacep);
  511. }
  512. }
  513. else
  514. if (!Referenced ||
  515. !(Queryp = DnsRecordQuery(Interfacep, Bufferp)))
  516. {
  517. RELEASE_LOCK(Interfacep);
  518. NhTrace(
  519. TRACE_FLAG_DNS,
  520. "DnsProcessQueryMessage: query could not be created"
  521. );
  522. if (Referenced)
  523. {
  524. DNS_DEREFERENCE_INTERFACE(Interfacep);
  525. }
  526. }
  527. else
  528. {
  529. //
  530. // Write the new ID in the query
  531. //
  532. Headerp->Xid = Queryp->QueryId;
  533. //
  534. // Send the query to our servers
  535. //
  536. Error =
  537. DnsSendQuery(
  538. Interfacep,
  539. Queryp,
  540. FALSE
  541. );
  542. //
  543. // This buffer is now associated with an outstanding query,
  544. // so don't repost it below.
  545. //
  546. if (!Error)
  547. {
  548. Bufferp = NULL;
  549. RELEASE_LOCK(Interfacep);
  550. }
  551. else
  552. {
  553. //
  554. // Delete the query, but not the buffer, which we repost below
  555. //
  556. Queryp->Bufferp = NULL;
  557. DnsDeleteQuery(Interfacep, Queryp);
  558. RELEASE_LOCK(Interfacep);
  559. DNS_DEREFERENCE_INTERFACE(Interfacep);
  560. }
  561. }
  562. }
  563. //
  564. // Cleanup
  565. //
  566. if (pQueryResultsSet)
  567. {
  568. DnsFree(pQueryResultsSet, DnsFreeRecordList);
  569. }
  570. if (dnsParsedMsg.pQuestionName)
  571. {
  572. DnsFree(dnsParsedMsg.pQuestionName, DnsFreeFlat);
  573. }
  574. }
  575. //
  576. // Post another read
  577. //
  578. EnterCriticalSection(&DnsInterfaceLock);
  579. if (!DNS_REFERENCE_INTERFACE(Interfacep)) {
  580. LeaveCriticalSection(&DnsInterfaceLock);
  581. if (Bufferp) { NhReleaseBuffer(Bufferp); }
  582. } else {
  583. LeaveCriticalSection(&DnsInterfaceLock);
  584. do {
  585. Error =
  586. NhReadDatagramSocket(
  587. &DnsComponentReference,
  588. Socket,
  589. Bufferp,
  590. DnsReadCompletionRoutine,
  591. Context,
  592. Context2
  593. );
  594. //
  595. // A connection-reset error indicates that our last *send*
  596. // could not be delivered at its destination.
  597. // We could hardly care less; so issue the read again,
  598. // immediately.
  599. //
  600. } while (Error == WSAECONNRESET);
  601. if (Error) {
  602. ACQUIRE_LOCK(Interfacep);
  603. DnsDeferReadInterface(Interfacep, Socket);
  604. RELEASE_LOCK(Interfacep);
  605. DNS_DEREFERENCE_INTERFACE(Interfacep);
  606. NhErrorLog(
  607. IP_DNS_PROXY_LOG_RECEIVE_FAILED,
  608. Error,
  609. "%I",
  610. NhQueryAddressSocket(Socket)
  611. );
  612. if (Bufferp) { NhReleaseBuffer(Bufferp); }
  613. }
  614. }
  615. } // DnsProcessQueryMessage
  616. VOID
  617. DnsProcessResponseMessage(
  618. PDNS_INTERFACE Interfacep,
  619. PNH_BUFFER Bufferp
  620. )
  621. /*++
  622. Routine Description:
  623. This routine is invoked to process a DNS response message.
  624. Arguments:
  625. Interfacep - the interface on which the query was received
  626. Bufferp - the buffer containing the query
  627. Return Value:
  628. none.
  629. Environment:
  630. Invoked internally in the context of a worker-thread completion routine,
  631. with an outstanding reference to 'Interfacep' from the time the
  632. read-operation was begun.
  633. --*/
  634. {
  635. PVOID Context;
  636. PVOID Context2;
  637. ULONG Error;
  638. PDNS_HEADER Headerp;
  639. PDNS_QUERY Queryp;
  640. SOCKET Socket;
  641. PROFILE("DnsProcessResponseMessage");
  642. #if DBG
  643. NhDump(
  644. TRACE_FLAG_DNS,
  645. Bufferp->Buffer,
  646. Bufferp->BytesTransferred,
  647. 1
  648. );
  649. #endif
  650. InterlockedIncrement(
  651. reinterpret_cast<LPLONG>(&DnsStatistics.ResponsesReceived)
  652. );
  653. Headerp = (PDNS_HEADER)Bufferp->Buffer;
  654. Socket = Bufferp->Socket;
  655. Context = Bufferp->Context;
  656. Context2 = Bufferp->Context2;
  657. //
  658. // Reference the interface and attempt to forward the response
  659. //
  660. EnterCriticalSection(&DnsInterfaceLock);
  661. if (!DNS_REFERENCE_INTERFACE(Interfacep)) {
  662. LeaveCriticalSection(&DnsInterfaceLock);
  663. } else {
  664. LeaveCriticalSection(&DnsInterfaceLock);
  665. ACQUIRE_LOCK(Interfacep);
  666. //
  667. // See if the response is for a pending query
  668. //
  669. if (!(Queryp = DnsMapResponseToQuery(Interfacep, Headerp->Xid))) {
  670. RELEASE_LOCK(Interfacep);
  671. DNS_DEREFERENCE_INTERFACE(Interfacep);
  672. InterlockedIncrement(
  673. reinterpret_cast<LPLONG>(&DnsStatistics.MessagesIgnored)
  674. );
  675. } else {
  676. //
  677. // We have the corresponding query.
  678. // Send the response back to the client.
  679. //
  680. Headerp->Xid = Queryp->SourceId;
  681. Error =
  682. NhWriteDatagramSocket(
  683. &DnsComponentReference,
  684. Bufferp->Socket,
  685. Queryp->SourceAddress,
  686. Queryp->SourcePort,
  687. Bufferp,
  688. Bufferp->BytesTransferred,
  689. DnsWriteCompletionRoutine,
  690. Interfacep,
  691. (PVOID)Queryp->QueryId
  692. );
  693. RELEASE_LOCK(Interfacep);
  694. //
  695. // This buffer is in use for a send-operation,
  696. // so don't repost it below.
  697. //
  698. if (!Error) {
  699. Bufferp = NULL;
  700. InterlockedIncrement(
  701. reinterpret_cast<LPLONG>(&DnsStatistics.ResponsesSent)
  702. );
  703. } else {
  704. DNS_DEREFERENCE_INTERFACE(Interfacep);
  705. NhWarningLog(
  706. IP_DNS_PROXY_LOG_RESPONSE_FAILED,
  707. Error,
  708. "%I",
  709. NhQueryAddressSocket(Socket)
  710. );
  711. }
  712. }
  713. }
  714. //
  715. // Post another read buffer
  716. //
  717. EnterCriticalSection(&DnsInterfaceLock);
  718. if (!DNS_REFERENCE_INTERFACE(Interfacep)) {
  719. LeaveCriticalSection(&DnsInterfaceLock);
  720. if (Bufferp) { NhReleaseBuffer(Bufferp); }
  721. } else {
  722. LeaveCriticalSection(&DnsInterfaceLock);
  723. do {
  724. Error =
  725. NhReadDatagramSocket(
  726. &DnsComponentReference,
  727. Socket,
  728. Bufferp,
  729. DnsReadCompletionRoutine,
  730. Context,
  731. Context2
  732. );
  733. //
  734. // A connection-reset error indicates that our last *send*
  735. // could not be delivered at its destination.
  736. // We could hardly care less; so issue the read again,
  737. // immediately.
  738. //
  739. } while (Error == WSAECONNRESET);
  740. if (Error) {
  741. ACQUIRE_LOCK(Interfacep);
  742. DnsDeferReadInterface(Interfacep, Socket);
  743. RELEASE_LOCK(Interfacep);
  744. DNS_DEREFERENCE_INTERFACE(Interfacep);
  745. if (Bufferp) { NhReleaseBuffer(Bufferp); }
  746. NhErrorLog(
  747. IP_DNS_PROXY_LOG_RECEIVE_FAILED,
  748. Error,
  749. "%I",
  750. NhQueryAddressSocket(Socket)
  751. );
  752. }
  753. }
  754. } // DnsProcessResponseMessage