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.

914 lines
27 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. if (Headerp->Opcode == DNS_OPCODE_QUERY ||
  75. Headerp->Opcode == DNS_OPCODE_IQUERY ||
  76. Headerp->Opcode == DNS_OPCODE_SERVER_STATUS) {
  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 dwUtf8Size = 0,
  124. dwSize;
  125. dwUtf8Size = strlen((char *)dnsParsedMsg.pQuestionName);
  126. dwSize = DnsGetBufferLengthForStringCopy(
  127. (char *)dnsParsedMsg.pQuestionName,
  128. dwUtf8Size,
  129. DnsCharSetUtf8,
  130. DnsCharSetUnicode
  131. );
  132. if (!dwSize)
  133. {
  134. //
  135. // invalid input string
  136. //
  137. DWORD dwRet = GetLastError();
  138. lpMsgBuf = NULL;
  139. FormatMessage(
  140. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  141. FORMAT_MESSAGE_FROM_SYSTEM |
  142. FORMAT_MESSAGE_IGNORE_INSERTS,
  143. NULL,
  144. dwRet,
  145. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  146. (LPTSTR) &lpMsgBuf,
  147. 0,
  148. NULL
  149. );
  150. NhTrace(
  151. TRACE_FLAG_DNS,
  152. "DnsProcessQueryMessage: DnsGetBufferLengthForStringCopy"
  153. " returned (0x%08x) %S",
  154. dwRet,
  155. lpMsgBuf
  156. );
  157. if (lpMsgBuf) LocalFree(lpMsgBuf);
  158. }
  159. else
  160. {
  161. pszQName = reinterpret_cast<PWCHAR>(NH_ALLOCATE(dwSize));
  162. if (!pszQName)
  163. {
  164. NhTrace(
  165. TRACE_FLAG_DNS,
  166. "DnsProcessQueryMessage: allocation "
  167. "failed for pszQName"
  168. );
  169. }
  170. else
  171. {
  172. ZeroMemory(pszQName, dwSize);
  173. DnsUtf8ToUnicode(
  174. (char *)dnsParsedMsg.pQuestionName,
  175. dwUtf8Size,
  176. pszQName,
  177. dwSize
  178. );
  179. fQ4DefaultSuffix = IsSuffixValid(
  180. pszQName,
  181. DNS_HOMENET_SUFFIX
  182. );
  183. NhTrace(
  184. TRACE_FLAG_DNS,
  185. "DnsProcessQueryMessage: %S (%s)",
  186. pszQName,
  187. (fQ4DefaultSuffix?"TRUE":"FALSE")
  188. );
  189. NH_FREE(pszQName);
  190. }
  191. }
  192. }
  193. //
  194. // Query
  195. //
  196. dwQueryOptions = (
  197. DNS_QUERY_STANDARD |
  198. DNS_QUERY_CACHE_ONLY |
  199. DNS_QUERY_TREAT_AS_FQDN |
  200. //DNS_QUERY_ALLOW_EMPTY_AUTH_RESP |
  201. 0
  202. );
  203. dnsStatus = DnsQuery_UTF8(
  204. (LPSTR) dnsParsedMsg.pQuestionName,
  205. dnsParsedMsg.QuestionType,
  206. dwQueryOptions,
  207. NULL,
  208. &pQueryResultsSet,
  209. NULL
  210. );
  211. }
  212. if (dnsStatus)
  213. {
  214. lpMsgBuf = NULL;
  215. FormatMessage(
  216. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  217. FORMAT_MESSAGE_FROM_SYSTEM |
  218. FORMAT_MESSAGE_IGNORE_INSERTS,
  219. NULL,
  220. dnsStatus,
  221. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  222. (LPTSTR) &lpMsgBuf,
  223. 0,
  224. NULL
  225. );
  226. NhTrace(
  227. TRACE_FLAG_DNS,
  228. "DnsProcessQueryMessage: (0x%08x) %S",
  229. dnsStatus,
  230. lpMsgBuf
  231. );
  232. if (lpMsgBuf) LocalFree(lpMsgBuf);
  233. }
  234. if ((NO_ERROR == dnsStatus) &&
  235. (pQueryResultsSet) // ??? what do i check to see if
  236. // there was actually something useful
  237. // returned from the cache
  238. )
  239. {
  240. NhTrace(
  241. TRACE_FLAG_DNS,
  242. "DnsProcessQueryMessage: results found in the local DNS Resolver Cache"
  243. );
  244. //
  245. // Pack & Send back answer; return
  246. //
  247. // set response bit
  248. dnsParsedMsg.Header.IsResponse = 1;
  249. // set the section field of every DNS_RECORD given to us
  250. // *** NEED TO CHANGE THIS LATER ***
  251. PDNS_RECORD pRR = pQueryResultsSet;
  252. DWORD cnt = 0;
  253. while (pRR)
  254. {
  255. pRR->Flags.S.Section = 1;
  256. cnt++;
  257. pRR = pRR->pNext;
  258. }
  259. NhTrace(
  260. TRACE_FLAG_DNS,
  261. "DnsProcessQueryMessage: %d records",
  262. cnt
  263. );
  264. // set global EDNS OPT field to 0 every time
  265. // *** NEED TO CHANGE THIS LATER ***
  266. //G_UseEdns = 0;
  267. pDnsMsgBuf = Dns_BuildPacket(
  268. &dnsParsedMsg.Header, // ??? parsed message header should be OK
  269. TRUE, // ??? no header count copy - counts done automatically?
  270. dnsParsedMsg.pQuestionName,
  271. dnsParsedMsg.QuestionType,
  272. pQueryResultsSet,
  273. dwQueryOptions,
  274. TRUE // set to update because of G_UseEdns workaround
  275. );
  276. if (NULL == pDnsMsgBuf)
  277. {
  278. lpMsgBuf = NULL;
  279. FormatMessage(
  280. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  281. FORMAT_MESSAGE_FROM_SYSTEM |
  282. FORMAT_MESSAGE_IGNORE_INSERTS,
  283. NULL,
  284. GetLastError(),
  285. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  286. (LPTSTR) &lpMsgBuf,
  287. 0,
  288. NULL
  289. );
  290. NhTrace(
  291. TRACE_FLAG_DNS,
  292. "DnsProcessQueryMessage: Dns_BuildPacket failed (%S)",
  293. lpMsgBuf
  294. );
  295. if (lpMsgBuf) LocalFree(lpMsgBuf);
  296. }
  297. else
  298. {
  299. DWORD dwDnsPktSize = (DWORD)(sizeof(DNS_HEADER) +
  300. ((PCHAR)pDnsMsgBuf->pCurrent -
  301. (PCHAR)pDnsMsgBuf->MessageBody));
  302. NhTrace(
  303. TRACE_FLAG_DNS,
  304. "DnsProcessQueryMessage: Dns_BuildPacket returned pkt of size %d (%d) bytes",
  305. dwDnsPktSize,
  306. DNS_MESSAGE_OFFSET(pDnsMsgBuf, pDnsMsgBuf->pCurrent)
  307. );
  308. //
  309. // send back the answer retrieved from the cache
  310. //
  311. PNH_BUFFER NewBufferp = NhAcquireVariableLengthBuffer(
  312. dwDnsPktSize
  313. );
  314. if (!NewBufferp)
  315. {
  316. NhTrace(
  317. TRACE_FLAG_DNS,
  318. "DnsProcessQueryMessage: could not acquire buffer"
  319. );
  320. }
  321. else
  322. {
  323. //
  324. // Dns* functions return in host order ???
  325. //
  326. DNS_BYTE_FLIP_HEADER_COUNTS(&pDnsMsgBuf->MessageHead);
  327. //
  328. // Reference the interface now since we are replying
  329. // to the query
  330. //
  331. EnterCriticalSection(&DnsInterfaceLock);
  332. if (!DNS_REFERENCE_INTERFACE(Interfacep))
  333. {
  334. LeaveCriticalSection(&DnsInterfaceLock);
  335. Referenced = FALSE;
  336. }
  337. else
  338. {
  339. LeaveCriticalSection(&DnsInterfaceLock);
  340. ACQUIRE_LOCK(Interfacep);
  341. memcpy(
  342. NewBufferp->Buffer,
  343. &pDnsMsgBuf->MessageHead,
  344. dwDnsPktSize
  345. );
  346. Error =
  347. NhWriteDatagramSocket(
  348. &DnsComponentReference,
  349. Bufferp->Socket,
  350. Bufferp->ReadAddress.sin_addr.s_addr,
  351. Bufferp->ReadAddress.sin_port,
  352. NewBufferp,
  353. dwDnsPktSize,
  354. DnsWriteCompletionRoutine,
  355. Interfacep,
  356. NULL
  357. );
  358. RELEASE_LOCK(Interfacep);
  359. if (!Error)
  360. {
  361. InterlockedIncrement(
  362. reinterpret_cast<LPLONG>(&DnsStatistics.ResponsesSent)
  363. );
  364. }
  365. else
  366. {
  367. NhReleaseBuffer(NewBufferp);
  368. DNS_DEREFERENCE_INTERFACE(Interfacep);
  369. NhWarningLog(
  370. IP_DNS_PROXY_LOG_RESPONSE_FAILED,
  371. Error,
  372. "%I",
  373. NhQueryAddressSocket(Socket)
  374. );
  375. }
  376. }
  377. }
  378. LocalFree(pDnsMsgBuf);
  379. }
  380. //
  381. // CLEANUP
  382. //
  383. DnsRecordListFree(
  384. pQueryResultsSet,
  385. DnsFreeRecordListDeep
  386. );
  387. // buffer is reposted below
  388. }
  389. else
  390. if (//(DNS_ERROR_RECORD_DOES_NOT_EXIST == dnsStatus) &&
  391. (fQ4DefaultSuffix))
  392. {
  393. //
  394. // this was a question for our default suffix
  395. // we send a name error reply back to the client
  396. // - note however that we dont publish an SOA
  397. // record for our default suffix domain
  398. //
  399. //
  400. // Undoing Flip above
  401. //
  402. DNS_BYTE_FLIP_HEADER_COUNTS(&pDnsBuffer->MessageHead);
  403. DWORD dwDnsPktSize = Bufferp->BytesTransferred;
  404. NhTrace(
  405. TRACE_FLAG_DNS,
  406. "DnsProcessQueryMessage: returning error message"
  407. );
  408. //
  409. // send back the negative answer
  410. //
  411. PNH_BUFFER NewBufferp = NhAcquireVariableLengthBuffer(
  412. dwDnsPktSize
  413. );
  414. if (!NewBufferp)
  415. {
  416. NhTrace(
  417. TRACE_FLAG_DNS,
  418. "DnsProcessQueryMessage: could not acquire buffer"
  419. );
  420. }
  421. else
  422. {
  423. //
  424. // Reference the interface now since we are replying
  425. // to the query
  426. //
  427. EnterCriticalSection(&DnsInterfaceLock);
  428. if (!DNS_REFERENCE_INTERFACE(Interfacep))
  429. {
  430. LeaveCriticalSection(&DnsInterfaceLock);
  431. Referenced = FALSE;
  432. }
  433. else
  434. {
  435. LeaveCriticalSection(&DnsInterfaceLock);
  436. ACQUIRE_LOCK(Interfacep);
  437. memcpy(
  438. NewBufferp->Buffer,
  439. Bufferp->Buffer,
  440. dwDnsPktSize
  441. );
  442. PDNS_HEADER NewHeaderp = (PDNS_HEADER)NewBufferp->Buffer;
  443. //
  444. // set response bit
  445. //
  446. NewHeaderp->IsResponse = 1;
  447. //
  448. // set "Name does not exist" error in the RCode field
  449. //
  450. NewHeaderp->ResponseCode = DNS_RCODE_NXDOMAIN;
  451. Error =
  452. NhWriteDatagramSocket(
  453. &DnsComponentReference,
  454. Bufferp->Socket,
  455. Bufferp->ReadAddress.sin_addr.s_addr,
  456. Bufferp->ReadAddress.sin_port,
  457. NewBufferp,
  458. dwDnsPktSize,
  459. DnsWriteCompletionRoutine,
  460. Interfacep,
  461. NULL
  462. );
  463. RELEASE_LOCK(Interfacep);
  464. if (!Error)
  465. {
  466. InterlockedIncrement(
  467. reinterpret_cast<LPLONG>(&DnsStatistics.ResponsesSent)
  468. );
  469. }
  470. else
  471. {
  472. NhReleaseBuffer(NewBufferp);
  473. DNS_DEREFERENCE_INTERFACE(Interfacep);
  474. NhWarningLog(
  475. IP_DNS_PROXY_LOG_RESPONSE_FAILED,
  476. Error,
  477. "%I",
  478. NhQueryAddressSocket(Socket)
  479. );
  480. }
  481. }
  482. }
  483. // buffer is reposted below
  484. }
  485. else
  486. {
  487. //
  488. // Undoing Flip above
  489. //
  490. DNS_BYTE_FLIP_HEADER_COUNTS(&pDnsBuffer->MessageHead);
  491. //
  492. // Reference the interface now in case we need to forward the query
  493. //
  494. EnterCriticalSection(&DnsInterfaceLock);
  495. if (DNS_REFERENCE_INTERFACE(Interfacep))
  496. {
  497. LeaveCriticalSection(&DnsInterfaceLock);
  498. }
  499. else
  500. {
  501. LeaveCriticalSection(&DnsInterfaceLock);
  502. Referenced = FALSE;
  503. }
  504. ACQUIRE_LOCK(Interfacep);
  505. //
  506. // See if this query is already pending;
  507. // if not, create a record for it on the receiving interface.
  508. //
  509. if (DnsIsPendingQuery(Interfacep, Bufferp))
  510. {
  511. RELEASE_LOCK(Interfacep);
  512. NhTrace(
  513. TRACE_FLAG_DNS,
  514. "DnsProcessQueryMessage: query already pending"
  515. );
  516. if (Referenced)
  517. {
  518. DNS_DEREFERENCE_INTERFACE(Interfacep);
  519. }
  520. }
  521. else
  522. if (!Referenced ||
  523. !(Queryp = DnsRecordQuery(Interfacep, Bufferp)))
  524. {
  525. RELEASE_LOCK(Interfacep);
  526. NhTrace(
  527. TRACE_FLAG_DNS,
  528. "DnsProcessQueryMessage: query could not be created"
  529. );
  530. if (Referenced)
  531. {
  532. DNS_DEREFERENCE_INTERFACE(Interfacep);
  533. }
  534. }
  535. else
  536. {
  537. //
  538. // Write the new ID in the query
  539. //
  540. Headerp->Xid = Queryp->QueryId;
  541. //
  542. // Send the query to our servers
  543. //
  544. Error =
  545. DnsSendQuery(
  546. Interfacep,
  547. Queryp,
  548. FALSE
  549. );
  550. //
  551. // This buffer is now associated with an outstanding query,
  552. // so don't repost it below.
  553. //
  554. if (!Error)
  555. {
  556. Bufferp = NULL;
  557. RELEASE_LOCK(Interfacep);
  558. }
  559. else
  560. {
  561. //
  562. // Delete the query, but not the buffer, which we repost below
  563. //
  564. Queryp->Bufferp = NULL;
  565. DnsDeleteQuery(Interfacep, Queryp);
  566. RELEASE_LOCK(Interfacep);
  567. DNS_DEREFERENCE_INTERFACE(Interfacep);
  568. }
  569. }
  570. }
  571. //
  572. // cleanup question name
  573. //
  574. LocalFree(dnsParsedMsg.pQuestionName); // ??? is LocalFree OK?
  575. }
  576. //
  577. // Post another read
  578. //
  579. EnterCriticalSection(&DnsInterfaceLock);
  580. if (!DNS_REFERENCE_INTERFACE(Interfacep)) {
  581. LeaveCriticalSection(&DnsInterfaceLock);
  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