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.

4861 lines
118 KiB

  1. /*++
  2. Copyright (c) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. send.c
  5. Abstract:
  6. Domain Name System (DNS) API
  7. Send response routines.
  8. Author:
  9. Jim Gilroy (jamesg) October, 1996
  10. Revision History:
  11. --*/
  12. #include "local.h"
  13. //
  14. // Disjoint name space
  15. //
  16. // If DNS name space is disjoint then NAME_ERROR response from one
  17. // adapter does NOT necessarily mean that name does not exist. Rather
  18. // must continue on other adapters.
  19. //
  20. // This flag should be set if name space is disjoint, off otherwise.
  21. //
  22. // DCR_PERF: auto-detect disjoint name space (really cool)
  23. // DCR_ENHANCE: auto-detect disjoint name space (really cool)
  24. // initially continue trying on other adapters and if they always
  25. // coincide, then conclude non-disjoint (and turn off)
  26. //
  27. // DCR_ENHANCE: registry turn off of disjoint name space
  28. //
  29. // Note: should consider that name spaces often disjoint in that
  30. // Intranet is hidden from Internet
  31. //
  32. BOOL fDisjointNameSpace = TRUE;
  33. //
  34. // Query \ response IP matching.
  35. //
  36. // Some resolvers (Win95) have required matching between DNS server IP
  37. // queried and response. This flag allows this matching to be turned on.
  38. // Better now than requiring SP later.
  39. //
  40. // DCR_ENHANCE: registry enable query\response IP matching.
  41. //
  42. BOOL fQueryIpMatching = FALSE;
  43. //
  44. // Timeouts
  45. //
  46. #define HARD_TIMEOUT_LIMIT 16 // 16 seconds, total of 31 seconds
  47. #define INITIAL_UPDATE_TIMEOUT 2 // 3 seconds
  48. #define MAX_UPDATE_TIMEOUT 24 // 24 seconds
  49. #define DNS_MAX_QUERY_TIMEOUTS 10 // 10
  50. #define ONE_HOUR_TIMEOUT 60*60 // One hour
  51. // TCP timeout 10 seconds to come back
  52. #define DEFAULT_TCP_TIMEOUT 10
  53. // Retry limits
  54. #define MAX_SINGLE_SERVER_RETRY (3)
  55. #define NT_TCPIP_REG_LOCATION "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"
  56. #define DNS_QUERY_TIMEOUTS "DnsQueryTimeouts"
  57. #define DNS_QUICK_QUERY_TIMEOUTS "DnsQuickQueryTimeouts"
  58. #define DNS_MULTICAST_QUERY_TIMEOUTS "DnsMulticastQueryTimeouts"
  59. //
  60. // Timeouts
  61. // MUST have terminating 0, this signals end of timeouts.
  62. // This is better than a timeout limit as different query types can
  63. // have different total retries.
  64. //
  65. DWORD QueryTimeouts[] =
  66. {
  67. 1, // NT5 1,
  68. 1, // 2,
  69. 2, // 2,
  70. 4, // 4,
  71. 7, // 8,
  72. 0
  73. };
  74. DWORD RegistryQueryTimeouts[DNS_MAX_QUERY_TIMEOUTS + 1];
  75. LPDWORD g_QueryTimeouts = QueryTimeouts;
  76. DWORD QuickQueryTimeouts[] =
  77. {
  78. 1,
  79. 2,
  80. 2,
  81. 0
  82. };
  83. DWORD RegistryQuickQueryTimeouts[DNS_MAX_QUERY_TIMEOUTS + 1];
  84. LPDWORD g_QuickQueryTimeouts = QuickQueryTimeouts;
  85. //
  86. // Update timeouts.
  87. // Must be long enough to handle zone lock on primary for XFR
  88. // or time required for DS write.
  89. //
  90. DWORD UpdateTimeouts[] =
  91. {
  92. 5,
  93. 10,
  94. 20,
  95. 0
  96. };
  97. //
  98. // Multicast Query timeouts.
  99. // Local only. 1sec timeout, three retries.
  100. //
  101. DWORD MulticastQueryTimeouts[] =
  102. {
  103. 1,
  104. 1,
  105. 1,
  106. 0
  107. };
  108. DWORD RegistryMulticastQueryTimeouts[DNS_MAX_QUERY_TIMEOUTS + 1];
  109. LPDWORD g_MulticastQueryTimeouts = MulticastQueryTimeouts;
  110. //
  111. // Query flag
  112. //
  113. // Flags that terminate query on adapter
  114. #define RUN_FLAG_COMBINED_IGNORE_ADAPTER \
  115. (RUN_FLAG_IGNORE_ADAPTER | RUN_FLAG_STOP_QUERY_ON_ADAPTER)
  116. //
  117. // Authoritative empty response
  118. // - map to NXRRSET for tracking in send code
  119. //
  120. #define DNS_RCODE_AUTH_EMPTY_RESPONSE (DNS_RCODE_NXRRSET)
  121. //
  122. // Dummy no-send-to-this-server error code
  123. //
  124. #define DNS_ERROR_NO_SEND ((DWORD)(-100))
  125. //
  126. // OPT failure tracking
  127. //
  128. BOOL
  129. Send_IsServerOptExclude(
  130. IN PDNS_ADDR pAddr
  131. );
  132. VOID
  133. Send_SetServerOptExclude(
  134. IN PDNS_ADDR pAddr
  135. );
  136. //
  137. // Netinfo send\recv utils
  138. //
  139. VOID
  140. serverPriorityChange(
  141. IN OUT PDNS_NETINFO pNetInfo,
  142. IN OUT PDNS_ADAPTER pAdapter,
  143. IN OUT PDNS_ADDR pServer,
  144. IN DWORD NewPriority
  145. )
  146. /*++
  147. Routine Description:
  148. Changing server priority.
  149. Arguments:
  150. pNetInfo -- netinfo
  151. pAdapter -- server's adapter
  152. pServer -- server
  153. NewPriority -- new priority
  154. Return Value:
  155. None.
  156. --*/
  157. {
  158. //
  159. // priority change
  160. // - no change if loopback
  161. // - otherwise
  162. // - set priority
  163. // - mark netinfo\adapter to save change
  164. //
  165. if ( !DnsAddr_IsLoopback( pServer, 0 ) )
  166. {
  167. pServer->Priority = NewPriority;
  168. pAdapter->RunFlags |= RUN_FLAG_RESET_SERVER_PRIORITY;
  169. pNetInfo->ReturnFlags |= RUN_FLAG_RESET_SERVER_PRIORITY;
  170. }
  171. }
  172. VOID
  173. timeoutDnsServers(
  174. IN PDNS_NETINFO pNetInfo,
  175. IN DWORD dwTimeout
  176. )
  177. /*++
  178. Routine Description:
  179. Mark a DNS server that timed out.
  180. Arguments:
  181. pNetInfo -- struct with list of DNS servers
  182. dwTimeout -- timeout in seconds
  183. Return Value:
  184. None.
  185. --*/
  186. {
  187. PDNS_ADAPTER padapter;
  188. PDNS_ADDR_ARRAY pserverArray;
  189. PDNS_ADDR pserver;
  190. DWORD lastSendIndex;
  191. DWORD i;
  192. DWORD j;
  193. DNSDBG( SEND, (
  194. "Enter timeoutDnsServers( %p, timeout=%d )\n",
  195. pNetInfo,
  196. dwTimeout ));
  197. DNS_ASSERT( pNetInfo );
  198. //
  199. // find DNS server in list,
  200. // -- drop its priority based on timeout
  201. // -- if already has RCODE, then did not time out
  202. //
  203. // if change a priority, then set flag at top of adapter list, so
  204. // that global copy may be updated
  205. //
  206. for ( i=0; i<pNetInfo->AdapterCount; i++ )
  207. {
  208. padapter = NetInfo_GetAdapterByIndex( pNetInfo, i );
  209. // no sends on this adapter?
  210. if ( !(padapter->RunFlags & RUN_FLAG_SENT_THIS_RETRY) )
  211. {
  212. DNSDBG( SEND, (
  213. "No sends this retry on adapter %d\n",
  214. padapter->InterfaceIndex ));
  215. continue;
  216. }
  217. pserverArray = padapter->pDnsAddrs;
  218. if ( !pserverArray )
  219. {
  220. DNSDBG( SEND, (
  221. "WARNING: Adapter %d -- no DNS servers!\n",
  222. padapter->InterfaceIndex ));
  223. continue;
  224. }
  225. //
  226. // find DNS servers sent to
  227. //
  228. // - if it responded with status, then it didn't timeout
  229. // (if responded with success, then query completed and
  230. // we wouldn't be in this function)
  231. //
  232. // - go "easy" on OPT sends;
  233. // don't drop priority, just note timeout
  234. //
  235. for ( j=0; j<pserverArray->AddrCount; j++ )
  236. {
  237. pserver = &pserverArray->AddrArray[j];
  238. if ( TEST_SERVER_STATE(pserver, SRVFLAG_SENT_THIS_RETRY) )
  239. {
  240. DNSDBG( SEND, (
  241. "Timeout on server %p (padapter=%p)\n",
  242. pserver,
  243. padapter ));
  244. if ( TEST_SERVER_STATE(pserver, SRVFLAG_SENT_NON_OPT) )
  245. {
  246. SET_SERVER_STATE( pserver, SRVFLAG_TIMEOUT_NON_OPT );
  247. serverPriorityChange(
  248. pNetInfo,
  249. padapter,
  250. pserver,
  251. pserver->Priority - dwTimeout - SRVPRI_TIMEOUT_DROP );
  252. }
  253. else
  254. {
  255. DNSDBG( SEND, (
  256. "Timeout on server %p OPT only\n",
  257. pserver ));
  258. SET_SERVER_STATE( pserver, SRVFLAG_TIMEOUT_OPT );
  259. }
  260. }
  261. }
  262. }
  263. }
  264. VOID
  265. resetOnFinalTimeout(
  266. IN PDNS_NETINFO pNetInfo
  267. )
  268. /*++
  269. Routine Description:
  270. Markup network info on final timeout.
  271. Arguments:
  272. pNetInfo -- struct with list of DNS servers
  273. dwTimeout -- timeout in seconds
  274. Return Value:
  275. None.
  276. --*/
  277. {
  278. DWORD i;
  279. PDNS_ADAPTER padapter;
  280. //
  281. // We've timed out against all DNS server for a least
  282. // one of the adapters. Update adapter status to show
  283. // time out error.
  284. //
  285. // DCR: is final timeout correct
  286. // - worried about timeout on some but not all servers
  287. // case; adapter shouldn't show timeout should it?
  288. //
  289. for ( i=0; i<pNetInfo->AdapterCount; i++ )
  290. {
  291. padapter = NetInfo_GetAdapterByIndex( pNetInfo, i );
  292. if ( padapter->Status == NO_ERROR &&
  293. padapter->RunFlags & (RUN_FLAG_RESET_SERVER_PRIORITY | RUN_FLAG_SENT) )
  294. {
  295. padapter->Status = ERROR_TIMEOUT;
  296. }
  297. }
  298. }
  299. BOOL
  300. verifyValidServer(
  301. IN PDNS_NETINFO pNetInfo,
  302. IN PDNS_ADDR pAddr
  303. )
  304. /*++
  305. Routine Description:
  306. Verify valid server IP.
  307. DCR: we have no way to do this for IP6 yet.
  308. Arguments:
  309. pNetInfo -- struct with list of DNS servers
  310. pAddr -- address of responding server
  311. Return Value:
  312. TRUE -- valid server.
  313. FALSE -- bad \ unknown server.
  314. --*/
  315. {
  316. PDNS_ADAPTER padapter;
  317. DWORD i;
  318. DNSDBG( SEND, (
  319. "Enter verifyValidServer( %p, %s )\n",
  320. pNetInfo,
  321. DNSADDR_STRING(pAddr) ));
  322. DNS_ASSERT( pNetInfo );
  323. //
  324. // accept any IP6 response
  325. //
  326. // DCR: IP6 server validity
  327. // will need to determine
  328. // - when we have fixed (global) IP6 address only
  329. // - or have locked down default addresses already
  330. // - otherwise will have to accept reponses to default
  331. // query ... but even there could screen on interface
  332. //
  333. if ( DnsAddr_IsIp6(pAddr) )
  334. {
  335. DNSDBG( SEND, ( "Accepting IP6 address as valid server address.\n" ));
  336. return TRUE;
  337. }
  338. //
  339. // find DNS server in list
  340. //
  341. for ( i=0; i<pNetInfo->AdapterCount; i++ )
  342. {
  343. padapter = NetInfo_GetAdapterByIndex( pNetInfo, i );
  344. if ( DnsAddrArray_ContainsAddr(
  345. padapter->pDnsAddrs,
  346. pAddr,
  347. DNSADDR_MATCH_ADDR ) )
  348. {
  349. return TRUE;
  350. }
  351. }
  352. DNSDBG( SEND, (
  353. "WARNING: address %s NOT found in network info!!!\n",
  354. DNSADDR_STRING(pAddr) ));
  355. return FALSE;
  356. }
  357. DNS_STATUS
  358. resetServerAfterRecv(
  359. IN PDNS_NETINFO pNetInfo,
  360. IN PDNS_ADDR pAddr,
  361. IN DNS_STATUS Status
  362. )
  363. /*++
  364. Routine Description:
  365. Reset priority on DNS server that sent response.
  366. Arguments:
  367. pNetInfo -- struct with list of DNS servers
  368. pAddr -- address of responding server
  369. Status -- RCODE of response
  370. Return Value:
  371. ERROR_SUCCESS if continue query.
  372. DNS_ERROR_RCODE_NAME_ERROR if all (valid) adapters have name-error or auth-empty response.
  373. --*/
  374. {
  375. DWORD i;
  376. DNS_STATUS result = DNS_ERROR_RCODE_NAME_ERROR;
  377. BOOL fterminalNameError = FALSE;
  378. #if DBG
  379. BOOL freset = FALSE;
  380. #endif
  381. DNSDBG( SEND, (
  382. "Enter resetServerAfterRecv( %p, %s rcode=%d)\n",
  383. pNetInfo,
  384. DNSADDR_STRING(pAddr),
  385. Status ));
  386. DNS_ASSERT( pNetInfo );
  387. //
  388. // find DNS server in list, clear its priority field
  389. //
  390. // note: going through full list here after found DNS
  391. // as no guarantee that lists do not overlap (IP6 default
  392. // servers almost certainly do);
  393. //
  394. // this avoids
  395. // - starving DNS by failing to update priority
  396. // - avoids unnecessary sends when NAME_ERROR would terminate
  397. // send on adapter with duplicate DNS
  398. //
  399. for ( i=0; i<pNetInfo->AdapterCount; i++ )
  400. {
  401. PDNS_ADAPTER padapter;
  402. PDNS_ADDR_ARRAY pserverArray;
  403. DWORD j;
  404. PDNS_ADDR pserver;
  405. DWORD newPriority;
  406. BOOL fpriReset = FALSE;
  407. padapter = NetInfo_GetAdapterByIndex( pNetInfo, i );
  408. pserverArray = padapter->pDnsAddrs;
  409. if ( !pserverArray )
  410. {
  411. DNSDBG( SEND, (
  412. "WARNING: Adapter %d -- no DNS servers!\n",
  413. padapter->InterfaceIndex ));
  414. continue;
  415. }
  416. for ( j=0; j<pserverArray->AddrCount; j++ )
  417. {
  418. pserver = &pserverArray->AddrArray[j];
  419. if ( !DnsAddr_IsEqual( pAddr, pserver, DNSADDR_MATCH_ADDR ) )
  420. {
  421. continue;
  422. }
  423. pserver->Status = Status;
  424. #if DBG
  425. freset = TRUE;
  426. #endif
  427. //
  428. // no DNS running
  429. //
  430. // WSAECONNRESET reported for reception of ICMP unreachable, so
  431. // no DNS is currently running on the IP; that's a severe
  432. // priority drop, worse than just TIMEOUT
  433. //
  434. if ( Status == WSAECONNRESET )
  435. {
  436. newPriority = pserver->Priority - SRVPRI_NO_DNS_DROP;
  437. fpriReset = TRUE;
  438. break;
  439. }
  440. // if SERVER_FAILURE rcode, may or may not indicate problem,
  441. // (may be simply unable to contact remote DNS)
  442. // but it certainly suggests trying other DNS servers in
  443. // the list first
  444. //
  445. // DCR_FIX: SEVRFAIL response priority reset
  446. // the explicitly correct approach would be to flag the
  447. // SERVER_FAILURE error, but NOT reset the priority unless
  448. // at the end of the query, we find another server in the list
  449. // got a useful response
  450. if ( Status == DNS_ERROR_RCODE_SERVER_FAILURE )
  451. {
  452. newPriority = pserver->Priority - SRVPRI_SERVFAIL_DROP;
  453. fpriReset = TRUE;
  454. break;
  455. }
  456. //
  457. // other status code indicates functioning DNS server,
  458. // - reset the server's priority
  459. if ( (LONG)pserver->Priority < SRVPRI_RESPONSE )
  460. {
  461. newPriority = SRVPRI_RESPONSE;
  462. fpriReset = TRUE;
  463. }
  464. //
  465. // NAME_ERROR or AUTH-EMPTY response
  466. // - save to server list for adapter to eliminate all
  467. // further retries on this adapter's list
  468. // - if not waiting for all adapters, then
  469. // NAME_ERROR or no-records is terminal
  470. if ( Status == DNS_ERROR_RCODE_NAME_ERROR ||
  471. Status == DNS_INFO_NO_RECORDS )
  472. {
  473. padapter->Status = Status;
  474. padapter->RunFlags |= RUN_FLAG_STOP_QUERY_ON_ADAPTER;
  475. pNetInfo->ReturnFlags |= RUN_FLAG_HAVE_VALID_RESPONSE;
  476. if ( !g_WaitForNameErrorOnAll )
  477. {
  478. fterminalNameError = TRUE;
  479. }
  480. }
  481. break;
  482. }
  483. //
  484. // priority reset?
  485. // - never reset loopback -- this keeps this first
  486. // - other
  487. if ( fpriReset )
  488. {
  489. serverPriorityChange(
  490. pNetInfo,
  491. padapter,
  492. pserver,
  493. newPriority );
  494. }
  495. //
  496. // end immediately on terminal NAME_ERROR
  497. // - jumping here rather than above only to simplify
  498. // handling of pri-rest (special casing of loopback, etc.)
  499. //
  500. if ( fterminalNameError )
  501. {
  502. goto Done;
  503. }
  504. //
  505. // do running check that still adapter worth querying
  506. // - not ignoring in first place
  507. // - hasn't received NAME_ERROR or AUTH_EMPTY response
  508. //
  509. // this is "at recv" check -- only trying to determine if we
  510. // should stop query RIGHT NOW as a result of this receive;
  511. // this does NOT check on whether there are any other servers
  512. // worth querying as that is done when go back for next send
  513. //
  514. // note how this works -- result starts as NAME_ERROR, when find
  515. // ANY adapter that hasn't gotten terminal response, then
  516. // result shifts (and stays) at ERROR_SUCCESS
  517. //
  518. // note, if we fix the twice through list issue above, then have to
  519. // change this so don't skip adapter lists after IP is found
  520. //
  521. if ( !(padapter->RunFlags & RUN_FLAG_COMBINED_IGNORE_ADAPTER) )
  522. {
  523. result = ERROR_SUCCESS;
  524. }
  525. }
  526. Done:
  527. #if DBG
  528. if ( !freset )
  529. {
  530. DNSDBG( ANY, (
  531. "ERROR: DNS server %s not in list.\n",
  532. DNSADDR_STRING( pAddr ) ));
  533. DNS_ASSERT( FALSE );
  534. }
  535. #endif
  536. return( result );
  537. }
  538. PDNS_ADDR
  539. bestDnsServerForNextSend(
  540. IN PDNS_ADAPTER pAdapter
  541. )
  542. /*++
  543. Routine Description:
  544. Get best DNS server IP address from list.
  545. Arguments:
  546. pAdapter -- struct with list of DNS servers
  547. Return Value:
  548. Ptr to server info of best send.
  549. NULL if no server on adapter is worth sending to; this is
  550. the case if all servers have received a response.
  551. --*/
  552. {
  553. PDNS_ADDR pserver;
  554. PDNS_ADDR_ARRAY pserverArray;
  555. PDNS_ADDR pbestServer = NULL;
  556. DWORD j;
  557. DWORD status;
  558. LONG priority;
  559. LONG priorityBest = MINLONG;
  560. DWORD sent;
  561. DWORD sentBest = MAXDWORD;
  562. DNSDBG( SEND, (
  563. "Enter bestDnsServerForNextSend( %p )\n",
  564. pAdapter ));
  565. if ( !pAdapter || !(pserverArray = pAdapter->pDnsAddrs) )
  566. {
  567. DNSDBG( SEND, (
  568. "WARNING: Leaving bestDnsServerForNextSend, no server list\n" ));
  569. return( NULL );
  570. }
  571. //
  572. // if already received name error on server in this list, done
  573. //
  574. // DCR: single flag test for no further query on this adapter
  575. //
  576. if ( pAdapter->Status == DNS_ERROR_RCODE_NAME_ERROR ||
  577. pAdapter->Status == DNS_INFO_NO_RECORDS )
  578. {
  579. DNSDBG( SEND, (
  580. "Leaving bestDnsServerForNextSend, NAME_ERROR already received\n"
  581. "\ton server in server list %p\n",
  582. pAdapter ));
  583. return( NULL );
  584. }
  585. //
  586. // check each server in list
  587. //
  588. for ( j=0; j<pserverArray->AddrCount; j++ )
  589. {
  590. pserver = &pserverArray->AddrArray[j];
  591. //
  592. // skip server?
  593. // - already recieved a response
  594. // - or failed in send
  595. // - or already sent in current retry
  596. //
  597. if ( TEST_SERVER_VALID_RECV(pserver) )
  598. {
  599. // NAME_ERROR or EMPTY_AUTH then adapter should have been
  600. // marked as "done" and we shouldn't be here
  601. // NO_ERROR should have exited immediately
  602. DNS_ASSERT( pserver->Status != NO_ERROR &&
  603. pserver->Status != DNS_ERROR_RCODE_NAME_ERROR &&
  604. pserver->Status != DNS_INFO_NO_RECORDS );
  605. continue;
  606. }
  607. if ( TEST_SERVER_STATE( pserver, SRVFLAG_SENT_THIS_RETRY ) )
  608. {
  609. continue;
  610. }
  611. //
  612. // check for best priority
  613. // - ideal is unsent, high priority server
  614. //
  615. // DCR: skip NO_DNS server for a while
  616. // skip timeout server for a little while
  617. // perhaps this should be done be ignoring these
  618. // when list is sent down?
  619. //
  620. // three cases based on sent\not:
  621. // - server not sent, best has been sent
  622. // => become best unless priority at NO_DNS level
  623. // - sent levels equal
  624. // => become best based on best priority
  625. // - server has sent, best has not
  626. // => become best only if current best at NO_DNS level, and
  627. // we're higher
  628. //
  629. priority = (LONG) pserver->Priority;
  630. sent = TEST_SERVER_STATE( pserver, SRVFLAG_SENT );
  631. if ( !pbestServer )
  632. {
  633. // no-op, we become the best
  634. }
  635. else if ( sent < sentBest )
  636. {
  637. if ( priority < SRVPRI_NO_DNS )
  638. {
  639. continue;
  640. }
  641. }
  642. else if ( sent == sentBest )
  643. {
  644. if ( priority < priorityBest )
  645. {
  646. continue;
  647. }
  648. }
  649. else // sent already, best has not
  650. {
  651. if ( priority < priorityBest ||
  652. priorityBest > SRVPRI_NO_DNS )
  653. {
  654. continue;
  655. }
  656. }
  657. // found new best server
  658. // - save "best" info for comparison
  659. // - declare immediate victory if unsent and high priority
  660. pbestServer = pserver;
  661. priorityBest = priority;
  662. sentBest = sent;
  663. if ( priority >= 0 && !sent )
  664. {
  665. break;
  666. }
  667. }
  668. return( pbestServer );
  669. }
  670. VOID
  671. markDuplicateSends(
  672. IN OUT PDNS_NETINFO pNetInfo,
  673. IN PDNS_ADDR pSendServer
  674. )
  675. /*++
  676. Routine Description:
  677. Mark any matching servers to avoid duplicate sends.
  678. Arguments:
  679. pNetInfo -- network info blob for send
  680. pSendServer -- DNS server being sent to
  681. Return Value:
  682. None
  683. --*/
  684. {
  685. DWORD i;
  686. DNSDBG( SEND, (
  687. "Enter markDuplicateSends( %p, %p )\n",
  688. pNetInfo,
  689. pSendServer ));
  690. if ( !pNetInfo )
  691. {
  692. DNS_ASSERT( FALSE );
  693. return;
  694. }
  695. //
  696. // find matching DNS servers
  697. // - note check MUST include scope as different scope
  698. // is different DNS
  699. //
  700. // mark matches as sent, sent this pass
  701. // note: currently there is no reason that flags should not
  702. // exactly match, so just copy flags
  703. //
  704. for ( i=0; i<pNetInfo->AdapterCount; i++ )
  705. {
  706. PDNS_ADAPTER padapter;
  707. PDNS_ADDR_ARRAY pserverArray;
  708. DWORD j;
  709. padapter = NetInfo_GetAdapterByIndex( pNetInfo, i );
  710. pserverArray = padapter->pDnsAddrs;
  711. if ( !pserverArray )
  712. {
  713. continue;
  714. }
  715. for ( j=0; j<pserverArray->AddrCount; j++ )
  716. {
  717. PDNS_ADDR pserver = &pserverArray->AddrArray[j];
  718. if ( DnsAddr_IsEqual(
  719. pserver,
  720. pSendServer,
  721. DNSADDR_MATCH_ADDR ) )
  722. {
  723. if ( pserver != pSendServer )
  724. {
  725. DNSDBG( SEND, (
  726. "Marking duplicate server %p on adapter %d\n",
  727. pserver,
  728. padapter->InterfaceIndex ));
  729. pserver->Flags = pSendServer->Flags;
  730. DNS_ASSERT( pserver->Status == pSendServer->Status );
  731. }
  732. padapter->RunFlags |= (RUN_FLAG_SENT | RUN_FLAG_SENT_THIS_RETRY);
  733. }
  734. }
  735. }
  736. }
  737. DNS_STATUS
  738. sendUsingServerInfo(
  739. IN OUT PDNS_MSG_BUF pMsg,
  740. IN OUT PDNS_NETINFO pNetInfo,
  741. IN OUT PDNS_ADDR pServInfo
  742. )
  743. /*++
  744. Routine Description:
  745. Send DNS message using server info.
  746. This function encapsulates the process of checking
  747. server info for validity, sending (as appropriate)
  748. and marking server, netinfo info.
  749. Note: right now this is UDP only
  750. Arguments:
  751. pMsg - message info for message to send
  752. pNetInfo - netinfo blob for send
  753. pServInfo - info of server to send to
  754. Return Value:
  755. ERROR_SUCCESS if successful.
  756. ErrorCode on send failure.
  757. --*/
  758. {
  759. DNS_STATUS status;
  760. BOOL fnoOpt;
  761. DNSDBG( SEND, (
  762. "sendUsingServerInfo( msg=%p, ni=%p, servinfo=%p )\n",
  763. pMsg,
  764. pNetInfo,
  765. pServInfo ));
  766. //
  767. // check that haven't
  768. // - already completed send\recv
  769. // - sent this pass
  770. //
  771. if ( TEST_SERVER_VALID_RECV( pServInfo ) ||
  772. TEST_SERVER_STATE( pServInfo, SRVFLAG_SENT_THIS_RETRY ) )
  773. {
  774. DNSDBG( SEND, (
  775. "Skipping send on server %p -- %s.\n",
  776. pServInfo,
  777. ( TEST_SERVER_VALID_RECV( pServInfo ) )
  778. ? "has valid recv"
  779. : "already sent this retry" ));
  780. return DNS_ERROR_NO_SEND;
  781. }
  782. //
  783. // check OPT status
  784. // - previous OPT send that timed OUT, then send non-OPT
  785. //
  786. // DCR: known OPT-ok list could screen wasted send
  787. fnoOpt = TEST_SERVER_STATE( pServInfo, SRVFLAG_SENT_OPT );
  788. //
  789. // send
  790. //
  791. status = Send_MessagePrivate(
  792. pMsg,
  793. pServInfo,
  794. fnoOpt );
  795. if ( status == ERROR_SUCCESS )
  796. {
  797. DNS_ASSERT( !fnoOpt || !pMsg->fLastSendOpt );
  798. SET_SERVER_STATE(
  799. pServInfo,
  800. pMsg->fLastSendOpt
  801. ? (SRVFLAG_SENT_OPT | SRVFLAG_SENT_THIS_RETRY)
  802. : (SRVFLAG_SENT_NON_OPT | SRVFLAG_SENT_THIS_RETRY)
  803. );
  804. // screen out duplicate sends
  805. markDuplicateSends( pNetInfo, pServInfo );
  806. }
  807. else
  808. {
  809. pServInfo->Status = status;
  810. }
  811. return status;
  812. }
  813. DNS_STATUS
  814. SendUdpToNextDnsServers(
  815. IN OUT PDNS_MSG_BUF pMsgSend,
  816. IN OUT PDNS_NETINFO pNetInfo,
  817. IN DWORD cRetryCount,
  818. IN DWORD dwTimeout,
  819. OUT PDWORD pSendCount
  820. )
  821. /*++
  822. Routine Description:
  823. Sends to next DNS servers in list.
  824. Arguments:
  825. pMsgSend -- message to send
  826. pNetInfo -- per adapter DNS info
  827. cRetryCount -- retry for this send
  828. dwTimeout -- timeout on last send, if timed out
  829. pSendCount -- addr to receive send count
  830. Return Value:
  831. ERROR_SUCCESS if successful send.
  832. ERROR_TIMEOUT if no DNS servers left to send to.
  833. Winsock error code on send failure.
  834. --*/
  835. {
  836. DWORD i;
  837. DWORD j;
  838. DWORD sendCount = 0;
  839. BOOL fignoredAdapter = FALSE;
  840. PDNS_ADAPTER padapter;
  841. PDNS_ADDR_ARRAY pserverArray;
  842. PDNS_ADDR pserver;
  843. DNS_STATUS status = ERROR_TIMEOUT;
  844. DNSDBG( SEND, (
  845. "Enter SendUdpToNextDnsServers()\n"
  846. "\tretry = %d\n",
  847. cRetryCount ));
  848. //
  849. // if netinfo not initialized for send, init
  850. //
  851. if ( !(pNetInfo->ReturnFlags & RUN_FLAG_NETINFO_PREPARED) )
  852. {
  853. DNSDBG( SEND, ( "Netinfo not prepared for send -- preparing now.\n" ));
  854. NetInfo_Clean(
  855. pNetInfo,
  856. CLEAR_LEVEL_QUERY );
  857. }
  858. #if DBG
  859. //
  860. // verify i'm getting a clean list on start
  861. //
  862. if ( cRetryCount == 0 )
  863. {
  864. for ( i=0; i<pNetInfo->AdapterCount; i++ )
  865. {
  866. padapter = NetInfo_GetAdapterByIndex( pNetInfo, i );
  867. // ignore this adapter because there are no DNS
  868. // servers configured?
  869. if ( padapter->InfoFlags & AINFO_FLAG_IGNORE_ADAPTER )
  870. {
  871. continue;
  872. }
  873. DNS_ASSERT( !(padapter->RunFlags &
  874. ( RUN_FLAG_SENT_THIS_RETRY |
  875. RUN_FLAG_SENT |
  876. RUN_FLAG_HAVE_VALID_RESPONSE ) ) );
  877. DNS_ASSERT( padapter->Status == 0 );
  878. pserverArray = padapter->pDnsAddrs;
  879. if ( !pserverArray )
  880. {
  881. continue;
  882. }
  883. for ( j=0; j<pserverArray->AddrCount; j++ )
  884. {
  885. DNS_ASSERT( pserverArray->AddrArray[j].Status == SRVSTATUS_NEW );
  886. DNS_ASSERT( pserverArray->AddrArray[j].Flags == SRVFLAG_NEW );
  887. }
  888. }
  889. }
  890. #endif
  891. //
  892. // if previous send timed out, update adapter list
  893. // - but ONLY do this when sending to individual servers in list
  894. // - timeout on all servers just produces an unnecessary copy and
  895. // can only change ordering relative to servers which have already
  896. // responded with RCODE; since its a timeout, this isn't going to
  897. // lower these server's priority so no point
  898. //
  899. if ( dwTimeout && cRetryCount && cRetryCount < MAX_SINGLE_SERVER_RETRY )
  900. {
  901. timeoutDnsServers( pNetInfo, dwTimeout );
  902. }
  903. //
  904. // clean "sent this retry" bit on all servers
  905. //
  906. // this allows us to track when server has already been
  907. // sent to on this pass and avoid duplicate send
  908. //
  909. for ( i=0; i<pNetInfo->AdapterCount; i++ )
  910. {
  911. padapter = NetInfo_GetAdapterByIndex( pNetInfo, i );
  912. padapter->RunFlags &= CLEAR_LEVEL_RETRY;
  913. pserverArray = padapter->pDnsAddrs;
  914. if ( !pserverArray )
  915. {
  916. continue;
  917. }
  918. for ( j=0; j<pserverArray->AddrCount; j++ )
  919. {
  920. CLEAR_SERVER_RETRY_STATE( & pserverArray->AddrArray[j] );
  921. }
  922. }
  923. //
  924. // send on DNS server(s) for adapter(s)
  925. //
  926. for ( i=0; i<pNetInfo->AdapterCount; i++ )
  927. {
  928. padapter = NetInfo_GetAdapterByIndex( pNetInfo, i );
  929. //
  930. // skip this adapter
  931. // - no servers
  932. // - not querying this adapter name
  933. // - already responded to this name
  934. // or
  935. // - unreachable DNS servers and either of
  936. // - have at least some response (NAME_ERROR) from another
  937. // adapter's DNS server
  938. // - first try on this query; in this case, note skipping the
  939. // adapter so we can use it, if no valid DNS are found
  940. //
  941. // note, the goal here is to keep adapters with "unreachable" DNS servers
  942. // around to resolve, but NOT wait for timeouts on them if other adapter's
  943. // servers have already NAME_ERROR'd
  944. //
  945. // DCR: go back to simple IGNORE check on unreachable adapter IF
  946. // - could verify unreachability of DNS server
  947. // but want to do this at run time, when other DNS servers are
  948. // not coming through, rather than when we build netinfo list itself
  949. //
  950. pserverArray = padapter->pDnsAddrs;
  951. if ( !pserverArray )
  952. {
  953. continue;
  954. }
  955. if ( padapter->RunFlags & RUN_FLAG_STOP_QUERY_ON_ADAPTER )
  956. {
  957. continue;
  958. }
  959. if ( padapter->InfoFlags &
  960. (AINFO_FLAG_IGNORE_ADAPTER |
  961. AINFO_FLAG_SERVERS_IP6_DEFAULT |
  962. AINFO_FLAG_SERVERS_AUTO_LOOPBACK ) )
  963. {
  964. if ( pNetInfo->ReturnFlags & RUN_FLAG_HAVE_VALID_RESPONSE )
  965. {
  966. continue;
  967. }
  968. if ( cRetryCount == 0 )
  969. {
  970. fignoredAdapter = TRUE;
  971. continue;
  972. }
  973. }
  974. //
  975. // first three attempts, we only go to one DNS on a given adapter
  976. //
  977. // - first time through ONLY to first server in first adapter list
  978. // - on subsequent tries go to best server in all lists
  979. //
  980. if ( cRetryCount < MAX_SINGLE_SERVER_RETRY )
  981. {
  982. //
  983. // do this in loop, in case send to "best" server fails
  984. //
  985. while ( 1 )
  986. {
  987. pserver = bestDnsServerForNextSend( padapter );
  988. if ( !pserver )
  989. {
  990. break; // no more unsent servers
  991. }
  992. status = sendUsingServerInfo(
  993. pMsgSend,
  994. pNetInfo,
  995. pserver );
  996. if ( status == ERROR_SUCCESS )
  997. {
  998. sendCount++;
  999. if ( cRetryCount == 0 )
  1000. {
  1001. goto Done;
  1002. }
  1003. break; // continue with next adapter
  1004. }
  1005. // send failed on server, try another
  1006. }
  1007. }
  1008. //
  1009. // after first three tries, send to all servers that
  1010. // have not already responded (have RCODE, as if NO_ERROR) we
  1011. // already finished
  1012. //
  1013. else
  1014. {
  1015. for ( j=0; j<pserverArray->AddrCount; j++ )
  1016. {
  1017. status = sendUsingServerInfo(
  1018. pMsgSend,
  1019. pNetInfo,
  1020. &pserverArray->AddrArray[j] );
  1021. if ( status == ERROR_SUCCESS )
  1022. {
  1023. sendCount++;
  1024. }
  1025. }
  1026. }
  1027. }
  1028. //
  1029. // no reachable DNS servers -- but possibly reachable ones?
  1030. //
  1031. // if first pass and we found NO reachable DNS servers, BUT
  1032. // we skipped over some unreachable ones -- use them
  1033. //
  1034. // note that fignoreAdapter is sufficient test, because it can
  1035. // only be set on cRetryCount == 0, which will jump directly to
  1036. // Done: label on a successful send
  1037. //
  1038. // note that we are doing this by tail recursion (just to keep it
  1039. // simple) and the recursion termination is guaranteed by bumping
  1040. // the retry count
  1041. //
  1042. if ( fignoredAdapter )
  1043. {
  1044. return SendUdpToNextDnsServers(
  1045. pMsgSend,
  1046. pNetInfo,
  1047. 1, // bump retry count to 1
  1048. dwTimeout,
  1049. pSendCount );
  1050. }
  1051. Done:
  1052. //
  1053. // if sent packet, success
  1054. //
  1055. *pSendCount = sendCount;
  1056. DNSDBG( SEND, (
  1057. "Leave SendUdpToNextDnsServers()\n"
  1058. "\tsends = %d\n",
  1059. sendCount ));
  1060. if ( sendCount )
  1061. {
  1062. return( ERROR_SUCCESS );
  1063. }
  1064. // if no packets sent, alert caller we're done
  1065. // - this is possible if servers have responded uselessly
  1066. // (NAME_ERROR, SERVER_FAILURE)
  1067. if ( status == ERROR_SUCCESS )
  1068. {
  1069. status = ERROR_TIMEOUT;
  1070. }
  1071. return( status );
  1072. }
  1073. //
  1074. // Message addressing routines
  1075. //
  1076. VOID
  1077. Send_SetMsgRemoteSockaddr(
  1078. IN OUT PDNS_MSG_BUF pMsg,
  1079. IN PDNS_ADDR pAddr
  1080. )
  1081. /*++
  1082. Routine Description:
  1083. Initialize remote sockaddr.
  1084. Arguments:
  1085. pMsg - message to send
  1086. pAddr - IP address to send
  1087. Return Value:
  1088. None.
  1089. --*/
  1090. {
  1091. //
  1092. // fill in sockaddr for IP4 or IP6
  1093. //
  1094. DnsAddr_Copy(
  1095. & pMsg->RemoteAddress,
  1096. pAddr );
  1097. pMsg->RemoteAddress.SockaddrIn.sin_port = DNS_PORT_NET_ORDER;
  1098. }
  1099. VOID
  1100. Send_SetMessageForRecv(
  1101. IN OUT PDNS_MSG_BUF pMsgRecv,
  1102. IN PDNS_MSG_BUF pMsgSend
  1103. )
  1104. /*++
  1105. Routine Description:
  1106. Set message for recv.
  1107. Arguments:
  1108. pMsgRecv - ptr message to recv
  1109. pMsgSend - ptr to message sent
  1110. Return Value:
  1111. None
  1112. --*/
  1113. {
  1114. DNSDBG( SOCKET, (
  1115. "Send_SetMessageForRecv( %p, %p )\n", pMsgRecv, pMsgSend ));
  1116. //
  1117. // TCP -- single connection at a time
  1118. // -- sockaddr not filled in during recv(), so fill it in now
  1119. //
  1120. if ( pMsgSend->fTcp )
  1121. {
  1122. pMsgRecv->fTcp;
  1123. pMsgRecv->Socket = pMsgSend->Socket;
  1124. RtlCopyMemory(
  1125. & pMsgRecv->RemoteAddress,
  1126. & pMsgSend->RemoteAddress,
  1127. sizeof(DNS_ADDR) );
  1128. }
  1129. //
  1130. // UDP -- can recv on either 4 or 6 socket
  1131. // -- sockaddr buffer must accomodate either
  1132. //
  1133. else
  1134. {
  1135. pMsgRecv->Socket = 0;
  1136. pMsgRecv->Socket4 = pMsgSend->Socket4;
  1137. pMsgRecv->Socket6 = pMsgSend->Socket6;
  1138. pMsgRecv->RemoteAddress.SockaddrLength = DNS_ADDR_MAX_SOCKADDR_LENGTH;
  1139. }
  1140. }
  1141. PDNS_ADDR
  1142. Send_CopyRecvIp(
  1143. OUT PDNS_ADDR pAddr,
  1144. IN PDNS_MSG_BUF pMsg
  1145. )
  1146. /*++
  1147. Routine Description:
  1148. Copy address from recv.
  1149. Arguments:
  1150. pAddr - addr of IP address to recv copy
  1151. pMsg - message to send
  1152. Return Value:
  1153. Ptr to addr written -- if successful.
  1154. NULL on bad recv addr.
  1155. --*/
  1156. {
  1157. INT family;
  1158. DnsAddr_Copy(
  1159. pAddr,
  1160. & pMsg->RemoteAddress );
  1161. if ( DnsAddr_Family(pAddr) )
  1162. {
  1163. return pAddr;
  1164. }
  1165. else
  1166. {
  1167. DnsAddr_Clear( pAddr );
  1168. DNSDBG( ANY, (
  1169. "ERROR: invalid recv sockaddr (family %d) for message %p!\n",
  1170. pMsg->RemoteAddress.Sockaddr.sa_family,
  1171. pMsg ));
  1172. return NULL;
  1173. }
  1174. }
  1175. //
  1176. // Send routines
  1177. //
  1178. DNS_STATUS
  1179. Send_MessagePrivate(
  1180. IN OUT PDNS_MSG_BUF pMsg,
  1181. IN PDNS_ADDR pSendAddr,
  1182. IN BOOL fNoOpt
  1183. )
  1184. /*++
  1185. Routine Description:
  1186. Send a DNS packet.
  1187. This is the generic send routine used for ANY send of a DNS message.
  1188. It assumes nothing about the message type, but does assume:
  1189. - pCurrent points at byte following end of desired data
  1190. - RR count bytes are in HOST byte order
  1191. Arguments:
  1192. pMsg - message info for message to send
  1193. pSendAddr - ptr to IP address to send to
  1194. OPTIONAL, required only if UDP and message sockaddr not set
  1195. fIp4 -- TRUE if IP4, FALSE for IP6
  1196. fNoOpt - TRUE if OPT send is forbidden
  1197. Return Value:
  1198. TRUE if successful.
  1199. FALSE on send error.
  1200. --*/
  1201. {
  1202. PDNS_HEADER pmsgHead;
  1203. INT err;
  1204. WORD sendLength;
  1205. BOOL fexcludedOpt = FALSE;
  1206. DNSDBG( SEND, (
  1207. "Send_MessagePrivate()\n"
  1208. "\tpMsg = %p\n"
  1209. "\tpSendAddr = %p\n"
  1210. "\tNo OPT = %d\n",
  1211. pMsg,
  1212. pSendAddr,
  1213. fNoOpt ));
  1214. //
  1215. // set header flags
  1216. //
  1217. // note: since route sends both queries and responses
  1218. // caller must set these flags
  1219. //
  1220. pmsgHead = &pMsg->MessageHead;
  1221. pmsgHead->Reserved = 0;
  1222. //
  1223. // set send IP (if given)
  1224. //
  1225. if ( pSendAddr )
  1226. {
  1227. Send_SetMsgRemoteSockaddr(
  1228. pMsg,
  1229. pSendAddr );
  1230. }
  1231. //
  1232. // set message length and OPT inclusion
  1233. //
  1234. // OPT approach is
  1235. // - write to pCurrent packet end
  1236. // - handles NO OPT written and using OPT
  1237. // - unless HAVE written OPT, and specifically excluding
  1238. // note, that zero IP (TCP previously connected) gets
  1239. // excluded
  1240. //
  1241. // DCR: we haven't handled OPT for TCP connected and not-aware of IP
  1242. // case here
  1243. //
  1244. // DCR: for now excluding OPT on updates, because harder to detect on
  1245. // the recv end why the reason for the failure
  1246. //
  1247. {
  1248. PCHAR pend = pMsg->pCurrent;
  1249. if ( pMsg->pPreOptEnd
  1250. &&
  1251. ( fNoOpt
  1252. ||
  1253. g_UseEdns == 0
  1254. ||
  1255. pMsg->MessageHead.Opcode == DNS_OPCODE_UPDATE
  1256. ||
  1257. //Send_IsServerOptExclude( &pMsg->RemoteIp ) ) )
  1258. ( pSendAddr && Send_IsServerOptExclude( pSendAddr ) ) ) )
  1259. {
  1260. ASSERT( pMsg->pPreOptEnd > (PCHAR)pmsgHead );
  1261. ASSERT( pMsg->pPreOptEnd < pend );
  1262. pend = pMsg->pPreOptEnd;
  1263. pmsgHead->AdditionalCount--;
  1264. fexcludedOpt = TRUE;
  1265. }
  1266. sendLength = (WORD)(pend - (PCHAR)pmsgHead);
  1267. pMsg->fLastSendOpt = (pMsg->pPreOptEnd && (pend != pMsg->pPreOptEnd));
  1268. }
  1269. IF_DNSDBG( SEND )
  1270. {
  1271. pMsg->MessageLength = sendLength;
  1272. DnsDbg_Message(
  1273. "Sending packet",
  1274. pMsg );
  1275. }
  1276. //
  1277. // flip header count bytes
  1278. //
  1279. DNS_BYTE_FLIP_HEADER_COUNTS( pmsgHead );
  1280. //
  1281. // TCP -- send until all info transmitted
  1282. //
  1283. if ( pMsg->fTcp )
  1284. {
  1285. PCHAR psend;
  1286. //
  1287. // TCP message always begins with bytes being sent
  1288. //
  1289. // - send length = message length plus two byte size
  1290. // - flip bytes in message length
  1291. // - send starting at message length
  1292. //
  1293. pMsg->MessageLength = htons( sendLength );
  1294. sendLength += sizeof(WORD);
  1295. psend = (PCHAR) &pMsg->MessageLength;
  1296. while ( sendLength )
  1297. {
  1298. err = send(
  1299. pMsg->Socket,
  1300. psend,
  1301. (INT) sendLength,
  1302. 0 );
  1303. if ( err == 0 || err == SOCKET_ERROR )
  1304. {
  1305. err = GetLastError();
  1306. //
  1307. // WSAESHUTDOWN is ok, client got timed out connection and
  1308. // closed
  1309. //
  1310. // WSAENOTSOCK may also occur if FIN recv'd and connection
  1311. // closed by TCP receive thread before the send
  1312. //
  1313. if ( err == WSAESHUTDOWN )
  1314. {
  1315. IF_DNSDBG( ANY )
  1316. {
  1317. DNS_PRINT((
  1318. "WARNING: send() failed on shutdown socket %d.\n"
  1319. "\tpMsgInfo at %p\n",
  1320. pMsg->Socket,
  1321. pMsg ));
  1322. }
  1323. }
  1324. else if ( err == WSAENOTSOCK )
  1325. {
  1326. IF_DNSDBG( ANY )
  1327. {
  1328. DNS_PRINT((
  1329. "ERROR: send() on closed socket %d.\n"
  1330. "\tpMsgInfo at %p\n",
  1331. pMsg->Socket,
  1332. pMsg ));
  1333. }
  1334. }
  1335. else
  1336. {
  1337. DNS_LOG_EVENT(
  1338. DNS_EVENT_SEND_CALL_FAILED,
  1339. 0,
  1340. NULL,
  1341. err );
  1342. IF_DNSDBG( ANY )
  1343. {
  1344. DNS_PRINT(( "ERROR: TCP send() failed, err = %d.\n" ));
  1345. }
  1346. }
  1347. goto Done;
  1348. }
  1349. sendLength -= (WORD)err;
  1350. psend += err;
  1351. }
  1352. }
  1353. //
  1354. // UDP
  1355. //
  1356. else
  1357. {
  1358. //
  1359. // get socket for send
  1360. //
  1361. // note UDP sockets may or may not be open before send as
  1362. // don't know whether we need to do send on specific protocols
  1363. // until sending to address of given protocol
  1364. //
  1365. if ( !Socket_CreateMessageSocket(pMsg) )
  1366. {
  1367. err = GetLastError();
  1368. if ( err == NO_ERROR )
  1369. {
  1370. DNS_ASSERT( err != NO_ERROR );
  1371. err = WSAEPROTONOSUPPORT;
  1372. }
  1373. goto Done;
  1374. }
  1375. DNS_ASSERT( pMsg->Socket != 0 );
  1376. DNS_ASSERT( sendLength <= DNS_RFC_MAX_UDP_PACKET_LENGTH );
  1377. err = sendto(
  1378. pMsg->Socket,
  1379. (PCHAR) pmsgHead,
  1380. sendLength,
  1381. 0,
  1382. (PSOCKADDR) &pMsg->RemoteAddress.Sockaddr,
  1383. pMsg->RemoteAddress.SockaddrLength
  1384. );
  1385. if ( err == SOCKET_ERROR )
  1386. {
  1387. err = GetLastError();
  1388. DNS_LOG_EVENT(
  1389. DNS_EVENT_SENDTO_CALL_FAILED,
  1390. 0,
  1391. NULL,
  1392. err );
  1393. IF_DNSDBG( ANY )
  1394. {
  1395. DNS_PRINT((
  1396. "ERROR: UDP sendto() failed => %d.\n",
  1397. err ));
  1398. DnsDbg_DnsAddr(
  1399. "sendto() failed sockaddr",
  1400. &pMsg->RemoteAddress );
  1401. DnsDbg_Message(
  1402. "sendto() failed message",
  1403. pMsg );
  1404. }
  1405. goto Done;
  1406. }
  1407. }
  1408. err = ERROR_SUCCESS;
  1409. Done:
  1410. DNS_BYTE_FLIP_HEADER_COUNTS( pmsgHead );
  1411. // restore OPT in count if required
  1412. if ( fexcludedOpt )
  1413. {
  1414. pmsgHead->AdditionalCount++;
  1415. }
  1416. Trace_LogSendEvent( pMsg, err );
  1417. return( (DNS_STATUS)err );
  1418. }
  1419. //
  1420. // UDP
  1421. //
  1422. DNS_STATUS
  1423. Recv_Udp(
  1424. IN OUT PDNS_MSG_BUF pMsg
  1425. )
  1426. /*++
  1427. Routine Description:
  1428. Receives DNS message
  1429. Arguments:
  1430. pMsg - message buffer for recv
  1431. Return Value:
  1432. ERROR_SUCCESS if successful.
  1433. Error status on failure.
  1434. --*/
  1435. {
  1436. PDNS_HEADER pdnsHeader;
  1437. LONG err = ERROR_SUCCESS;
  1438. struct timeval selectTimeout;
  1439. struct fd_set fdset;
  1440. DNSDBG( RECV, (
  1441. "Enter Recv_Udp( %p )\n",
  1442. pMsg ));
  1443. DNS_ASSERT( !pMsg->fTcp );
  1444. //
  1445. // setup recv set
  1446. //
  1447. FD_ZERO( &fdset );
  1448. if ( pMsg->Socket6 )
  1449. {
  1450. FD_SET( pMsg->Socket6, &fdset );
  1451. }
  1452. if ( pMsg->Socket4 )
  1453. {
  1454. FD_SET( pMsg->Socket4, &fdset );
  1455. }
  1456. if ( fdset.fd_count == 0 )
  1457. {
  1458. DNSDBG( ANY, (
  1459. "ERROR: UDP recv on msg %p with no sockets!\n",
  1460. pMsg ));
  1461. return( ERROR_INVALID_PARAMETER );
  1462. }
  1463. // set timeout
  1464. if ( pMsg->Timeout > HARD_TIMEOUT_LIMIT &&
  1465. pMsg->Timeout != ONE_HOUR_TIMEOUT )
  1466. {
  1467. DNSDBG( RECV, (
  1468. "ERROR: timeout %d, exceeded hard limit.\n",
  1469. pMsg->Timeout ));
  1470. return( ERROR_TIMEOUT );
  1471. }
  1472. selectTimeout.tv_usec = 0;
  1473. selectTimeout.tv_sec = pMsg->Timeout;
  1474. pdnsHeader = &pMsg->MessageHead;
  1475. //
  1476. // wait for stack to indicate packet reception
  1477. //
  1478. err = select( 0, &fdset, NULL, NULL, &selectTimeout );
  1479. if ( err <= 0 )
  1480. {
  1481. if ( err < 0 )
  1482. {
  1483. // select error
  1484. err = WSAGetLastError();
  1485. DNS_PRINT(( "ERROR: select() error = %d\n", err ));
  1486. return( err );
  1487. }
  1488. else
  1489. {
  1490. DNS_PRINT(( "ERROR: timeout on response %p\n", pMsg ));
  1491. return( ERROR_TIMEOUT );
  1492. }
  1493. }
  1494. //
  1495. // receive
  1496. //
  1497. if ( fdset.fd_count != 1 )
  1498. {
  1499. if ( fdset.fd_count == 0 )
  1500. {
  1501. DNS_ASSERT( FALSE );
  1502. return( ERROR_TIMEOUT );
  1503. }
  1504. DNS_PRINT((
  1505. "WARNING: Recv_Udp on multiple sockets!\n" ));
  1506. }
  1507. pMsg->Socket = fdset.fd_array[0];
  1508. err = recvfrom(
  1509. pMsg->Socket,
  1510. (PCHAR) pdnsHeader,
  1511. DNS_MAX_UDP_PACKET_BUFFER_LENGTH,
  1512. 0,
  1513. &pMsg->RemoteAddress.Sockaddr,
  1514. &pMsg->RemoteAddress.SockaddrLength );
  1515. if ( err == SOCKET_ERROR )
  1516. {
  1517. err = GetLastError();
  1518. Trace_LogRecvEvent(
  1519. pMsg,
  1520. err,
  1521. FALSE // UDP
  1522. );
  1523. if ( err == WSAECONNRESET )
  1524. {
  1525. DNSDBG( RECV, (
  1526. "Leave Recv_Udp( %p ) with CONNRESET\n",
  1527. pMsg ));
  1528. return( err );
  1529. }
  1530. // message sent was too big
  1531. // sender was in error -- should have sent TCP
  1532. if ( err == WSAEMSGSIZE )
  1533. {
  1534. pMsg->MessageLength = DNS_MAX_UDP_PACKET_BUFFER_LENGTH;
  1535. DnsDbg_Message(
  1536. "ERROR: Recv UDP packet over 512 bytes.\n",
  1537. pMsg );
  1538. }
  1539. IF_DNSDBG( ANY )
  1540. {
  1541. DnsDbg_Lock();
  1542. DNS_PRINT((
  1543. "ERROR: recvfrom(sock=%d) of UDP request failed.\n"
  1544. "\tGetLastError() = 0x%08lx.\n",
  1545. socket,
  1546. err ));
  1547. DnsDbg_DnsAddr(
  1548. "recvfrom failed sockaddr\n",
  1549. & pMsg->RemoteAddress );
  1550. DnsDbg_Unlock();
  1551. }
  1552. return( err );
  1553. }
  1554. //
  1555. // successful receive
  1556. // - save remote IP
  1557. // - set message length
  1558. // - flip header fields
  1559. //
  1560. DNS_ASSERT( err <= DNS_MAX_UDP_PACKET_BUFFER_LENGTH );
  1561. pMsg->MessageLength = (WORD)err;
  1562. DNS_BYTE_FLIP_HEADER_COUNTS( &pMsg->MessageHead );
  1563. err = ERROR_SUCCESS;
  1564. Trace_LogRecvEvent(
  1565. pMsg,
  1566. 0,
  1567. FALSE // UDP
  1568. );
  1569. IF_DNSDBG( RECV )
  1570. {
  1571. DnsDbg_Message(
  1572. "Received message",
  1573. pMsg );
  1574. }
  1575. return( err );
  1576. }
  1577. DNS_STATUS
  1578. Send_AndRecvUdpWithParam(
  1579. IN OUT PDNS_MSG_BUF pMsgSend,
  1580. OUT PDNS_MSG_BUF pMsgRecv,
  1581. IN DWORD dwFlags,
  1582. IN PADDR_ARRAY pServerList,
  1583. IN OUT PDNS_NETINFO pNetInfo
  1584. )
  1585. /*++
  1586. Routine Description:
  1587. Sends to and waits to recv from remote DNS.
  1588. DCR: move to use send blob
  1589. Arguments:
  1590. pMsgSend - message to send
  1591. ppMsgRecv - and reuse
  1592. dwFlags -- query flags
  1593. pServerList -- list of server to use; overrides adapter info
  1594. pNetInfo -- adapter list DNS server info
  1595. Return Value:
  1596. ERROR_SUCCESS if successful response.
  1597. Error status for "best RCODE" response if rcode.
  1598. ERROR_TIMEOUT on timeout.
  1599. Error status on send\recv failure.
  1600. --*/
  1601. {
  1602. INT retry;
  1603. DWORD timeout;
  1604. DNS_STATUS status = ERROR_TIMEOUT;
  1605. DNS_ADDR recvIp;
  1606. PDNS_ADDR precvIp = NULL;
  1607. DWORD rcode = 0;
  1608. DWORD ignoredRcode = 0;
  1609. DWORD sendCount;
  1610. DWORD sentCount;
  1611. DWORD sendTime;
  1612. BOOL frecvRetry;
  1613. BOOL fupdate = FALSE; // prefix
  1614. PDNS_NETINFO ptempNetInfo = NULL;
  1615. DNSDBG( SEND, (
  1616. "Enter Send_AndRecvUdpWithParam()\n"
  1617. "\ttime %d\n"
  1618. "\tsend msg at %p\n"
  1619. "\tsocket %d\n"
  1620. "\trecv msg at %p\n"
  1621. "\tflags %08x\n"
  1622. "\tserver IP array %p\n"
  1623. "\tadapter info at %p\n",
  1624. Dns_GetCurrentTimeInSeconds(),
  1625. pMsgSend,
  1626. pMsgSend->Socket,
  1627. pMsgRecv,
  1628. dwFlags,
  1629. pServerList,
  1630. pNetInfo ));
  1631. // verify params
  1632. if ( !pMsgSend || !pMsgRecv || (!pNetInfo && !pServerList) )
  1633. {
  1634. return( ERROR_INVALID_PARAMETER );
  1635. }
  1636. //
  1637. // server IP array?
  1638. // - if given overrides netinfo
  1639. //
  1640. // should be able to just use update netinfo
  1641. //if ( aipServers && !pNetInfo )
  1642. if ( pServerList )
  1643. {
  1644. ptempNetInfo = NetInfo_CreateFromAddrArray(
  1645. pServerList,
  1646. 0, // no single IP
  1647. FALSE, // no search info
  1648. NULL );
  1649. if ( !ptempNetInfo )
  1650. {
  1651. return( DNS_ERROR_NO_MEMORY );
  1652. }
  1653. pNetInfo = ptempNetInfo;
  1654. }
  1655. //
  1656. // DCR: allow sockets sent into send functions
  1657. // - then must know initial state to avoid close
  1658. //
  1659. //
  1660. // if already have TCP socket -- invalid
  1661. //
  1662. if ( pMsgSend->fTcp && pMsgSend->Socket )
  1663. {
  1664. status = ERROR_INVALID_PARAMETER;
  1665. goto Done;
  1666. }
  1667. pMsgSend->fTcp = FALSE;
  1668. pMsgRecv->Socket = 0;
  1669. pMsgRecv->fTcp = FALSE;
  1670. // determine UPDATE or standard QUERY
  1671. fupdate = ( pMsgSend->MessageHead.Opcode == DNS_OPCODE_UPDATE );
  1672. //
  1673. // loop sending until
  1674. // - receive successful response
  1675. // or
  1676. // - receive errors response from all servers
  1677. // or
  1678. // - reach final timeout on all servers
  1679. //
  1680. //
  1681. // DCR: should support setting of timeouts on individual queries
  1682. //
  1683. retry = 0;
  1684. sendCount = 0;
  1685. while ( 1 )
  1686. {
  1687. if ( fupdate )
  1688. {
  1689. timeout = UpdateTimeouts[retry];
  1690. }
  1691. else
  1692. {
  1693. if ( dwFlags & DNS_QUERY_USE_QUICK_TIMEOUTS )
  1694. {
  1695. timeout = g_QuickQueryTimeouts[retry];
  1696. }
  1697. else
  1698. {
  1699. timeout = g_QueryTimeouts[retry];
  1700. }
  1701. }
  1702. //
  1703. // zero timeout indicates end of retries for this query type
  1704. //
  1705. if ( timeout == 0 )
  1706. {
  1707. // save timeout for adapter?
  1708. //
  1709. // if multiple adapters and some timed out and some
  1710. // didn't then saving timeout is relevant
  1711. //
  1712. // DCR: this doesn't make much sense
  1713. // the actual test i moved inside the function
  1714. if ( pNetInfo &&
  1715. pNetInfo->AdapterCount > 1 &&
  1716. ignoredRcode &&
  1717. status == ERROR_TIMEOUT )
  1718. {
  1719. resetOnFinalTimeout( pNetInfo );
  1720. }
  1721. break;
  1722. }
  1723. //
  1724. // send to best DNS servers in adapter list
  1725. // - servers sent to varies according to retry
  1726. // - send in previous timeout, if some servers did not respond
  1727. //
  1728. status = SendUdpToNextDnsServers(
  1729. pMsgSend,
  1730. pNetInfo,
  1731. retry,
  1732. sendCount ? pMsgRecv->Timeout : 0,
  1733. & sendCount );
  1734. sentCount = sendCount;
  1735. if ( status != ERROR_SUCCESS )
  1736. {
  1737. // if no more servers to send to, done
  1738. DNSDBG( RECV, (
  1739. "No more DNS servers to send message %p\n"
  1740. "\tprevious RCODE = %d\n",
  1741. pMsgSend,
  1742. ignoredRcode ));
  1743. goto ErrorReturn;
  1744. }
  1745. retry++;
  1746. precvIp = NULL;
  1747. rcode = DNS_RCODE_NO_ERROR;
  1748. pMsgRecv->Timeout = timeout;
  1749. DNS_ASSERT( sendCount != 0 );
  1750. frecvRetry = FALSE;
  1751. sendTime = GetCurrentTimeInSeconds();
  1752. //
  1753. // receive response
  1754. //
  1755. // note: the loop is strictly to allow us to drop back into
  1756. // receive if one server is misbehaving;
  1757. // in that case we go back into the receive without resending
  1758. // to allow other servers to respond
  1759. //
  1760. while ( sendCount )
  1761. {
  1762. //
  1763. // if have to retry recv, adjust down timeout
  1764. // - note, one second granularity is handled by
  1765. // rounding up at zero so we wait 0-1s beyond official
  1766. // timeout value
  1767. //
  1768. // DCR: calculate timeouts in ms?
  1769. //
  1770. if ( frecvRetry )
  1771. {
  1772. DWORD timeLeft;
  1773. timeLeft = timeout + sendTime - GetCurrentTimeInSeconds();
  1774. if ( (LONG)timeLeft < 0 )
  1775. {
  1776. status = ERROR_TIMEOUT;
  1777. break;
  1778. }
  1779. else if ( timeLeft == 0 )
  1780. {
  1781. timeLeft = 1;
  1782. }
  1783. pMsgRecv->Timeout = timeLeft;
  1784. }
  1785. frecvRetry = TRUE;
  1786. Send_SetMessageForRecv( pMsgRecv, pMsgSend );
  1787. status = Recv_Udp( pMsgRecv );
  1788. precvIp = Send_CopyRecvIp( &recvIp, pMsgRecv );
  1789. // recv wait completed
  1790. // - if timeout, commence next retry
  1791. // - if CONNRESET
  1792. // - indicate NO server on IP
  1793. // - back to recv if more DNS servers outstanding,
  1794. // - if success, verify packet
  1795. if ( status != ERROR_SUCCESS )
  1796. {
  1797. if ( status == ERROR_TIMEOUT )
  1798. {
  1799. break;
  1800. }
  1801. if ( status == WSAECONNRESET )
  1802. {
  1803. resetServerAfterRecv(
  1804. pNetInfo,
  1805. precvIp,
  1806. status );
  1807. sendCount--;
  1808. continue;
  1809. }
  1810. }
  1811. // no recv
  1812. // - unexpected winsock errors not handled above
  1813. // - should always have remote IP on success recv
  1814. if ( !precvIp )
  1815. {
  1816. DNSDBG( ANY, (
  1817. "Recv error %d -- no recv IP\n",
  1818. status ));
  1819. DNS_ASSERT( status != ERROR_SUCCESS );
  1820. continue;
  1821. }
  1822. // check XID match
  1823. if ( pMsgRecv->MessageHead.Xid != pMsgSend->MessageHead.Xid )
  1824. {
  1825. DNS_PRINT(( "WARNING: Incorrect XID in response. Ignoring.\n" ));
  1826. continue;
  1827. }
  1828. //
  1829. // check DNS server IP match
  1830. //
  1831. if ( g_QueryIpMatching &&
  1832. !verifyValidServer( pNetInfo, precvIp ) )
  1833. {
  1834. DNS_PRINT((
  1835. "WARNING: Ignoring response from %s to query %p\n"
  1836. "\tIP does not match valid server\n",
  1837. DNSADDR_STRING(precvIp),
  1838. pMsgSend ));
  1839. continue;
  1840. }
  1841. // valid receive, drop outstanding send count
  1842. sendCount--;
  1843. //
  1844. // check question match
  1845. // - this is "Maggs Bug" check
  1846. // - ASSERT here just to investigate issue locally
  1847. // and make sure check is not bogus
  1848. // - specifically doing after sendCount decrement
  1849. // as this server will NOT send us a valid response
  1850. // - some servers don't reply with question so ignore
  1851. // if QuestionCount == 0
  1852. //
  1853. if ( pMsgRecv->MessageHead.QuestionCount != 0
  1854. &&
  1855. !Dns_IsSamePacketQuestion(
  1856. pMsgRecv,
  1857. pMsgSend ))
  1858. {
  1859. DNS_PRINT((
  1860. "ERROR: Bad question response from server %08x!\n"
  1861. "\tXID match, but question does not match question sent!\n",
  1862. recvIp ));
  1863. DNS_ASSERT( FALSE );
  1864. continue;
  1865. }
  1866. // suck out RCODE
  1867. rcode = pMsgRecv->MessageHead.ResponseCode;
  1868. //
  1869. // good response?
  1870. //
  1871. // special case AUTH-EMPTY and delegations
  1872. //
  1873. // - AUTH-EMPTY gets similar treatment to name error
  1874. // (this adapter can be considered to be finished)
  1875. //
  1876. // - referrals can be treated like SERVER_FAILURE
  1877. // (avoid this server for rest of query; server may
  1878. // be fine for direct lookup, so don't drop priority)
  1879. //
  1880. //
  1881. // DCR_CLEANUP: functionalize packet-categorization
  1882. // this would be standard errors
  1883. // plus AUTH-EMPTY versus referral
  1884. // plus OPT issues, etc
  1885. // could be called from TCP side also
  1886. //
  1887. // then would have separate determination about whether
  1888. // packet was terminal (below)
  1889. //
  1890. if ( rcode == DNS_RCODE_NO_ERROR )
  1891. {
  1892. if ( pMsgRecv->MessageHead.AnswerCount != 0 || fupdate )
  1893. {
  1894. goto GoodRecv;
  1895. }
  1896. //
  1897. // auth-empty
  1898. // - authoritative
  1899. // - or from cache, recursive response (hence not delegation)
  1900. //
  1901. // note: using dummy RCODE here as "ignored RCODE" serves
  1902. // the role of "best saved status" and roughly
  1903. // prioritizes in the way we want
  1904. //
  1905. // DCR: could change to "best saved status" as mapping is
  1906. // pretty much the same; would explicitly have to
  1907. // check
  1908. if ( pMsgRecv->MessageHead.Authoritative == 1 ||
  1909. ( pMsgRecv->MessageHead.RecursionAvailable == 1 &&
  1910. pMsgRecv->MessageHead.RecursionDesired ) )
  1911. {
  1912. DNSDBG( RECV, (
  1913. "Recv AUTH-EMPTY response from %s\n",
  1914. DNSADDR_STRING(precvIp) ));
  1915. rcode = DNS_RCODE_AUTH_EMPTY_RESPONSE;
  1916. status = DNS_INFO_NO_RECORDS;
  1917. }
  1918. // referral
  1919. else if ( pMsgRecv->MessageHead.RecursionAvailable == 0 )
  1920. {
  1921. DNSDBG( RECV, (
  1922. "Recv referral response from %s\n",
  1923. DNSADDR_STRING(precvIp) ));
  1924. rcode = DNS_RCODE_SERVER_FAILURE;
  1925. status = DNS_ERROR_REFERRAL_RESPONSE;
  1926. }
  1927. // bogus (bad packet) response
  1928. else
  1929. {
  1930. rcode = DNS_RCODE_SERVER_FAILURE;
  1931. status = DNS_ERROR_BAD_PACKET;
  1932. }
  1933. }
  1934. else
  1935. {
  1936. status = Dns_MapRcodeToStatus( (UCHAR)rcode );
  1937. }
  1938. //
  1939. // OPT failure screening
  1940. //
  1941. // DCR: FORMERR overload on OPT for update
  1942. // unless we read result to see if OPT, no way
  1943. // to determine if this is update problem or
  1944. // OPT problem
  1945. //
  1946. // - note, that checking if in list doesn't work because
  1947. // of MT issue (another query adds setting)
  1948. //
  1949. // - could be fixed by setting flag in network info
  1950. //
  1951. if ( rcode == DNS_RCODE_FORMAT_ERROR &&
  1952. !fupdate )
  1953. {
  1954. Send_SetServerOptExclude( precvIp );
  1955. // redo send but explicitly force OPT excluse
  1956. Send_MessagePrivate(
  1957. pMsgSend,
  1958. precvIp,
  1959. TRUE // exclude OPT
  1960. );
  1961. sendCount++;
  1962. continue;
  1963. }
  1964. //
  1965. // error RCODE do NOT terminate query
  1966. // - SERVER_FAILUREs
  1967. // - malfunctioning server
  1968. // - disjoint nets \ DNS namespace issues
  1969. //
  1970. // RCODE error removes particular server from further consideration
  1971. // during THIS query
  1972. //
  1973. // generally the higher RCODEs are more interesting
  1974. // NAME_ERROR > SERVER_FAILURE
  1975. // and
  1976. // update RCODEs > NAME_ERROR
  1977. // save the highest as return when no ERROR_SUCCESS response
  1978. //
  1979. // however for query NAME_ERROR is the highest RCODE,
  1980. // IF it is received on all adapters (if not REFUSED on one
  1981. // adapter may indicate that there really is a name)
  1982. //
  1983. // for UPDATE, REFUSED and higher are terminal RCODEs.
  1984. // downlevel servers (non-UPDATE-aware) servers would give
  1985. // FORMERR or NOTIMPL, so these are either valid responses or
  1986. // the zone has a completely busted server which must be detected
  1987. // and removed
  1988. //
  1989. //
  1990. // DCR_CLEANUP: functionalize packet-termination
  1991. // essentially is this type of packet terminal for
  1992. // this query;
  1993. // could be called from TCP side also
  1994. //
  1995. if ( rcode > ignoredRcode )
  1996. {
  1997. ignoredRcode = rcode;
  1998. }
  1999. //
  2000. // reset server priority for good recv
  2001. // - return ERROR_SUCCESS unless all adapters
  2002. // are
  2003. //
  2004. status = resetServerAfterRecv(
  2005. pNetInfo,
  2006. precvIp,
  2007. status );
  2008. //
  2009. // if all adapters are done (NAME_ERROR or NO_RECORDS)
  2010. // - return NAME_ERROR\NO_RECORDS rcode
  2011. // NO_RECORDS highest priority
  2012. // then NAME_ERROR
  2013. // then anything else
  2014. if ( status == DNS_ERROR_RCODE_NAME_ERROR )
  2015. {
  2016. if ( !fupdate && ignoredRcode != DNS_RCODE_AUTH_EMPTY_RESPONSE )
  2017. {
  2018. ignoredRcode = DNS_RCODE_NAME_ERROR;
  2019. }
  2020. goto ErrorReturn;
  2021. }
  2022. //
  2023. // update RCODEs are terminal
  2024. //
  2025. if ( fupdate && rcode >= DNS_RCODE_REFUSED )
  2026. {
  2027. goto ErrorReturn;
  2028. }
  2029. // continue wait for any other outstanding servers
  2030. }
  2031. DNSDBG( RECV, (
  2032. "Failed retry = %d for message %p\n"
  2033. "\tstatus = %d\n"
  2034. "\ttimeout = %d\n"
  2035. "\tservers out = %d\n"
  2036. "\tlast rcode = %d\n"
  2037. "\tignored RCODE = %d\n\n",
  2038. (retry - 1),
  2039. pMsgSend,
  2040. status,
  2041. timeout,
  2042. sendCount,
  2043. rcode,
  2044. ignoredRcode ));
  2045. continue;
  2046. } // end loop sending/recving packets
  2047. //
  2048. // falls here on retry exhausted
  2049. //
  2050. // note that any ignored RCODE takes precendence over failing
  2051. // status (which may be winsock error, timeout, or bogus
  2052. // NAME_ERROR from resetServerPriorities())
  2053. //
  2054. ErrorReturn:
  2055. // this can also hit on winsock error in DnsSend()
  2056. //
  2057. //DNS_ASSERT( ignoredRcode || status == ERROR_TIMEOUT );
  2058. //
  2059. // error responses from all servers or timeouts
  2060. //
  2061. DNSDBG( RECV, (
  2062. "Error or timeouts from all servers for message %p\n"
  2063. "\treturning RCODE = %d\n",
  2064. pMsgSend,
  2065. ignoredRcode ));
  2066. if ( ignoredRcode )
  2067. {
  2068. // empty-auth reponse is tracked with bogus RCODE,
  2069. // switch to status code -- DNS_INFO_NO_RECORDS
  2070. if ( !fupdate && ignoredRcode == DNS_RCODE_AUTH_EMPTY_RESPONSE )
  2071. {
  2072. status = DNS_INFO_NO_RECORDS;
  2073. }
  2074. else
  2075. {
  2076. status = Dns_MapRcodeToStatus( (UCHAR)ignoredRcode );
  2077. }
  2078. }
  2079. goto Done;
  2080. GoodRecv:
  2081. resetServerAfterRecv(
  2082. pNetInfo,
  2083. precvIp,
  2084. rcode );
  2085. DNSDBG( RECV, (
  2086. "Recv'd response for query at %p from DNS %s\n",
  2087. pMsgSend,
  2088. DNSADDR_STRING(precvIp) ));
  2089. Done:
  2090. //
  2091. // close UDP sockets
  2092. //
  2093. // DCR_ENHANCE: allow for possibility of keeping socket alive
  2094. //
  2095. Socket_CloseMessageSockets( pMsgSend );
  2096. Socket_ClearMessageSockets( pMsgRecv );
  2097. IF_DNSDBG( RECV )
  2098. {
  2099. DNSDBG( SEND, (
  2100. "Leave Send_AndRecvUdp()\n"
  2101. "\tstatus = %d\n"
  2102. "\ttime = %d\n"
  2103. "\tsend msg = %p\n"
  2104. "\trecv msg = %p\n",
  2105. status,
  2106. Dns_GetCurrentTimeInSeconds(),
  2107. pMsgSend,
  2108. pMsgRecv ));
  2109. DnsDbg_NetworkInfo(
  2110. "Network info after UDP recv\n",
  2111. pNetInfo );
  2112. }
  2113. // if allocated adapter list free it
  2114. if ( ptempNetInfo )
  2115. {
  2116. NetInfo_Free( ptempNetInfo );
  2117. }
  2118. // should not return NXRRSET except on update
  2119. ASSERT( fupdate || status != DNS_ERROR_RCODE_NXRRSET );
  2120. return( status );
  2121. }
  2122. DNS_STATUS
  2123. Send_AndRecvMulticast(
  2124. IN OUT PDNS_MSG_BUF pMsgSend,
  2125. OUT PDNS_MSG_BUF pMsgRecv,
  2126. IN OUT PDNS_NETINFO pNetInfo OPTIONAL
  2127. )
  2128. /*++
  2129. Routine Description:
  2130. Sends to and waits to recv from remote DNS.
  2131. Arguments:
  2132. pMsgSend - message to send
  2133. ppMsgRecv - and reuse
  2134. pNetInfo -- adapter list DNS server info
  2135. DCR - pNetInfo parameter could be leveraged to
  2136. identify specific networks to target a multicast
  2137. query against. For example, there could be a multihomed
  2138. machine that is configured to only multicast on one
  2139. of many adapters, thus filtering out useless mDNS packets.
  2140. Return Value:
  2141. ERROR_SUCCESS if successful response.
  2142. NAME_ERROR on timeout.
  2143. Error status on send\recv failure.
  2144. --*/
  2145. {
  2146. #if 1
  2147. return DNS_ERROR_RCODE_NAME_ERROR;
  2148. #else
  2149. SOCKET s;
  2150. INT fcreatedSocket = FALSE;
  2151. INT retry;
  2152. DWORD timeout;
  2153. DNS_STATUS status = ERROR_TIMEOUT;
  2154. IP4_ADDRESS recvIp = 0;
  2155. DWORD rcode = 0;
  2156. DWORD ignoredRcode = 0;
  2157. DNSDBG( SEND, (
  2158. "Enter Send_AndRecvMulticast()\n"
  2159. "\tsend msg at %p\n"
  2160. "\tsocket %d\n"
  2161. "\trecv msg at %p\n",
  2162. pMsgSend,
  2163. pMsgSend->Socket,
  2164. pMsgRecv ));
  2165. // verify params
  2166. if ( !pMsgSend || !pMsgRecv )
  2167. {
  2168. return( ERROR_INVALID_PARAMETER );
  2169. }
  2170. if ( pMsgSend->MessageHead.Opcode == DNS_OPCODE_UPDATE )
  2171. {
  2172. return( ERROR_INVALID_PARAMETER );
  2173. }
  2174. //
  2175. // TCP invalid -- invalid
  2176. //
  2177. // problem is we either leak TCP socket, or we close
  2178. // it here and may screw things up at higher level
  2179. //
  2180. if ( pMsgSend->fTcp &&
  2181. (pMsgSend->Socket4 || pMsgSend->Socket6) )
  2182. {
  2183. status = ERROR_INVALID_PARAMETER;
  2184. goto Done;
  2185. }
  2186. pMsgSend->fTcp = FALSE;
  2187. pMsgRecv->fTcp = FALSE;
  2188. pMsgRecv->Socket = 0;
  2189. pMsgRecv->Socket6 = 0;
  2190. pMsgRecv->Socket4 = 0;
  2191. //
  2192. // loop sending until
  2193. // - receive successful response
  2194. // or
  2195. // - receive errors response from all servers
  2196. // or
  2197. // - reach final timeout on all servers
  2198. //
  2199. retry = 0;
  2200. while ( 1 )
  2201. {
  2202. timeout = g_MulticastQueryTimeouts[retry];
  2203. //
  2204. // zero timeout indicates end of retries for this query type
  2205. //
  2206. if ( timeout == 0 )
  2207. {
  2208. break;
  2209. }
  2210. //
  2211. // send to multicast DNS address
  2212. //
  2213. if ( retry == 0 )
  2214. { //
  2215. // setup mcast address
  2216. //
  2217. status = DnsAddr_BuildMcast(
  2218. &addr,
  2219. Family,
  2220. pName
  2221. );
  2222. if ( status != NO_ERROR )
  2223. {
  2224. goto Failed;
  2225. }
  2226. //
  2227. // create multicast socket
  2228. // - bound to this address and DNS port
  2229. //
  2230. sock = Socket_Create(
  2231. Family,
  2232. SOCK_DGRAM,
  2233. &addr,
  2234. MCAST_PORT_NET_ORDER,
  2235. FALSE,
  2236. TRUE );
  2237. if ( sock == 0 )
  2238. {
  2239. goto Failed;
  2240. }
  2241. Dns_InitializeMsgRemoteSockaddr( pMsgSend, MCAST_DNS_RADDR );
  2242. }
  2243. Dns_Send( pMsgSend );
  2244. retry++;
  2245. rcode = DNS_RCODE_NO_ERROR;
  2246. pMsgRecv->Timeout = timeout;
  2247. //
  2248. // receive response
  2249. //
  2250. // note: the loop is strictly to allow us to drop back into
  2251. // receive if one server is misbehaving;
  2252. // in that case we go back into the receive without resending
  2253. // to allow other servers to respond
  2254. //
  2255. Send_SetMessageForRecv( pMsgRecv, pMsgSend );
  2256. status = Recv_Udp( pMsgRecv );
  2257. // recv wait completed
  2258. // - if timeout, commence next retry
  2259. // - if CONNRESET
  2260. // - back to recv if more DNS servers outstanding,
  2261. // - otherwise equivalent treat as timeout, except with
  2262. // very long timeout
  2263. // - if success, verify packet
  2264. if ( status != ERROR_SUCCESS )
  2265. {
  2266. if ( status == ERROR_TIMEOUT )
  2267. {
  2268. continue;
  2269. }
  2270. if ( status == WSAECONNRESET )
  2271. {
  2272. pMsgRecv->Timeout = NO_DNS_PRIORITY_DROP;
  2273. status = ERROR_TIMEOUT;
  2274. continue;
  2275. }
  2276. goto Done;
  2277. }
  2278. // check XID match
  2279. if ( pMsgRecv->MessageHead.Xid != pMsgSend->MessageHead.Xid )
  2280. {
  2281. DNS_PRINT(( "WARNING: Incorrect XID in response. Ignoring.\n" ));
  2282. continue;
  2283. }
  2284. //
  2285. // good response?
  2286. //
  2287. // special case AUTH-EMPTY and delegations
  2288. //
  2289. // - AUTH-EMPTY gets similar treatment to name error
  2290. // (this adapter can be considered to be finished)
  2291. //
  2292. // - referrals can be treated like SERVER_FAILURE
  2293. // (avoid this server for rest of query; server may
  2294. // be fine for direct lookup, so don't drop priority)
  2295. //
  2296. rcode = pMsgRecv->MessageHead.ResponseCode;
  2297. if ( rcode == DNS_RCODE_NO_ERROR )
  2298. {
  2299. if ( pMsgRecv->MessageHead.AnswerCount != 0 )
  2300. {
  2301. goto Done;
  2302. }
  2303. // auth-empty
  2304. if ( pMsgRecv->MessageHead.Authoritative == 1 )
  2305. {
  2306. DNSDBG( RECV, (
  2307. "Recv AUTH-EMPTY response from %s\n",
  2308. MSG_REMOTE_IPADDR_STRING(pMsgRecv) ));
  2309. rcode = DNS_RCODE_AUTH_EMPTY_RESPONSE;
  2310. }
  2311. }
  2312. } // end loop sending/recving packets
  2313. Done:
  2314. //
  2315. // if created socket -- close it
  2316. //
  2317. // DCR_ENHANCE: allow for possibility of keeping socket alive
  2318. //
  2319. Socket_CloseMessageSockets( pMsgSend );
  2320. Socket_ClearMessageSockets( pMsgRecv );
  2321. IF_DNSDBG( RECV )
  2322. {
  2323. DNSDBG( SEND, (
  2324. "Leave Send_AndRecvMulticast()\n"
  2325. "\tstatus = %d\n"
  2326. "\ttime = %d\n"
  2327. "\tsend msg at %p\n"
  2328. "\trecv msg at %p\n",
  2329. status,
  2330. Dns_GetCurrentTimeInSeconds(),
  2331. pMsgSend,
  2332. pMsgRecv ));
  2333. }
  2334. if ( status == ERROR_TIMEOUT )
  2335. {
  2336. status = DNS_ERROR_RCODE_NAME_ERROR;
  2337. }
  2338. return( status );
  2339. #endif
  2340. }
  2341. //
  2342. // TCP routines
  2343. //
  2344. DNS_STATUS
  2345. Send_OpenTcpConnectionAndSend(
  2346. IN OUT PDNS_MSG_BUF pMsg,
  2347. IN PDNS_ADDR pServAddr,
  2348. IN BOOL fBlocking
  2349. )
  2350. /*++
  2351. Routine Description:
  2352. Connect via TCP to desired server.
  2353. Arguments:
  2354. pMsg -- message info to set with connection socket
  2355. pServAddr -- IP of DNS server to connect to
  2356. fBlocking -- blocking connection
  2357. Return Value:
  2358. TRUE if successful.
  2359. FALSE on connect error.
  2360. --*/
  2361. {
  2362. SOCKET s;
  2363. INT err;
  2364. //
  2365. // setup a TCP socket
  2366. // - INADDR_ANY -- let stack select source IP
  2367. //
  2368. s = Socket_Create(
  2369. DnsAddr_Family( pServAddr ),
  2370. SOCK_STREAM,
  2371. NULL, // default binding
  2372. 0, // any port
  2373. 0 // no flags
  2374. );
  2375. if ( s == 0 )
  2376. {
  2377. DNS_PRINT((
  2378. "ERROR: unable to create TCP socket to create TCP"
  2379. "\tconnection to %s.\n",
  2380. DNSADDR_STRING( pServAddr ) ));
  2381. pMsg->Socket = 0;
  2382. err = WSAGetLastError();
  2383. if ( !err )
  2384. {
  2385. DNS_ASSERT( FALSE );
  2386. err = WSAENOTSOCK;
  2387. }
  2388. return( err );
  2389. }
  2390. //
  2391. // set TCP params
  2392. // - do before connect(), so can directly use sockaddr buffer
  2393. //
  2394. pMsg->fTcp = TRUE;
  2395. Send_SetMsgRemoteSockaddr( pMsg, pServAddr );
  2396. //
  2397. // connect
  2398. //
  2399. err = connect(
  2400. s,
  2401. & pMsg->RemoteAddress.Sockaddr,
  2402. pMsg->RemoteAddress.SockaddrLength
  2403. );
  2404. if ( err )
  2405. {
  2406. PCHAR pchIpString;
  2407. err = GetLastError();
  2408. pchIpString = MSG_REMOTE_IPADDR_STRING( pMsg );
  2409. DNS_LOG_EVENT(
  2410. DNS_EVENT_CANNOT_CONNECT_TO_SERVER,
  2411. 1,
  2412. &pchIpString,
  2413. err );
  2414. DNSDBG( TCP, (
  2415. "Unable to establish TCP connection to %s.\n"
  2416. "\tstatus = %d\n",
  2417. pchIpString,
  2418. err ));
  2419. Socket_Close( s );
  2420. pMsg->Socket = 0;
  2421. if ( !err )
  2422. {
  2423. err = WSAENOTCONN;
  2424. }
  2425. return( err );
  2426. }
  2427. DNSDBG( TCP, (
  2428. "Connected to %s for message at %p.\n"
  2429. "\tsocket = %d\n",
  2430. MSG_REMOTE_IPADDR_STRING( pMsg ),
  2431. pMsg,
  2432. s ));
  2433. pMsg->Socket = s;
  2434. //
  2435. // send desired packet
  2436. //
  2437. err = Send_MessagePrivate(
  2438. pMsg,
  2439. NULL, // no address
  2440. TRUE // no OPT
  2441. );
  2442. return( (DNS_STATUS)err );
  2443. } // Send_OpenTcpConnectionAndSend
  2444. DNS_STATUS
  2445. Dns_RecvTcp(
  2446. IN OUT PDNS_MSG_BUF pMsg
  2447. )
  2448. /*++
  2449. Routine Description:
  2450. Receive TCP DNS message.
  2451. EXPORTED (security.c): Dns_RecvTcp
  2452. EXPORTED rename Recv_Tcp
  2453. Arguments:
  2454. pMsg - message info buffer to receive packet; must contain connected
  2455. TCP socket
  2456. Return Value:
  2457. ERROR_SUCCESS if successfully receive a message.
  2458. Error code on failure.
  2459. --*/
  2460. {
  2461. PCHAR pchrecv; // ptr to recv location
  2462. INT recvLength; // length left to recv()
  2463. SOCKET socket;
  2464. INT err = NO_ERROR;
  2465. WORD messageLength;
  2466. struct timeval selectTimeout;
  2467. struct fd_set fdset;
  2468. DNS_ASSERT( pMsg );
  2469. socket = pMsg->Socket;
  2470. DNSDBG( RECV, (
  2471. "Enter Dns_RecvTcp( %p )\n"
  2472. "\tRecv on socket = %d.\n"
  2473. "\tBytes left to receive = %d\n"
  2474. "\tTimeout = %d\n",
  2475. pMsg,
  2476. socket,
  2477. pMsg->BytesToReceive,
  2478. pMsg->Timeout
  2479. ));
  2480. //
  2481. // verify socket, setup fd_set and select timeout
  2482. //
  2483. if ( socket == 0 || socket == INVALID_SOCKET )
  2484. {
  2485. return( ERROR_INVALID_PARAMETER );
  2486. }
  2487. FD_ZERO( &fdset );
  2488. FD_SET( socket, &fdset );
  2489. selectTimeout.tv_usec = 0;
  2490. selectTimeout.tv_sec = pMsg->Timeout;
  2491. //
  2492. // new message -- set to receive message length
  2493. // - reusing buffer
  2494. // - new buffer
  2495. //
  2496. // continuing receive of message
  2497. //
  2498. if ( !pMsg->pchRecv )
  2499. {
  2500. DNS_ASSERT( pMsg->fMessageComplete || pMsg->MessageLength == 0 );
  2501. pchrecv = (PCHAR) &pMsg->MessageLength;
  2502. recvLength = (INT) sizeof( WORD );
  2503. }
  2504. else
  2505. {
  2506. pchrecv = (PCHAR) pMsg->pchRecv;
  2507. recvLength = (INT) pMsg->BytesToReceive;
  2508. }
  2509. DNS_ASSERT( recvLength );
  2510. //
  2511. // loop until receive the entire message
  2512. //
  2513. while ( 1 )
  2514. {
  2515. //
  2516. // wait for stack to indicate packet reception
  2517. //
  2518. err = select( 0, &fdset, NULL, NULL, &selectTimeout );
  2519. if ( err <= 0 )
  2520. {
  2521. if ( err < 0 )
  2522. {
  2523. // select error
  2524. err = WSAGetLastError();
  2525. DNS_PRINT(( "ERROR: select() error = %p\n", err ));
  2526. return( err );
  2527. }
  2528. else
  2529. {
  2530. Trace_LogRecvEvent(
  2531. pMsg,
  2532. ERROR_TIMEOUT,
  2533. TRUE // TCP
  2534. );
  2535. DNS_PRINT(( "ERROR: timeout on response %p\n", pMsg ));
  2536. return( ERROR_TIMEOUT );
  2537. }
  2538. }
  2539. //
  2540. // Only recv() exactly as much data as indicated.
  2541. // Another message could follow during zone transfer.
  2542. //
  2543. err = recv(
  2544. socket,
  2545. pchrecv,
  2546. recvLength,
  2547. 0 );
  2548. DNSDBG( TCP, (
  2549. "\nRecv'd %d bytes on TCP socket %d\n",
  2550. err,
  2551. socket ));
  2552. //
  2553. // TCP FIN received -- error in the middle of a message.
  2554. //
  2555. if ( err == 0 )
  2556. {
  2557. goto FinReceived;
  2558. }
  2559. //
  2560. // recv error
  2561. // - perfectly reasonable if shutting down
  2562. // - otherwise actual recv() error
  2563. //
  2564. if ( err == SOCKET_ERROR )
  2565. {
  2566. goto SockError;
  2567. }
  2568. //
  2569. // update buffer params
  2570. //
  2571. recvLength -= err;
  2572. pchrecv += err;
  2573. DNS_ASSERT( recvLength >= 0 );
  2574. //
  2575. // received message or message length
  2576. //
  2577. if ( recvLength == 0 )
  2578. {
  2579. // done receiving message
  2580. if ( pchrecv > (PCHAR)&pMsg->MessageHead )
  2581. {
  2582. break;
  2583. }
  2584. //
  2585. // recv'd message length, setup to recv() message
  2586. // - byte flip length
  2587. // - continue reception with this length
  2588. //
  2589. DNS_ASSERT( pchrecv == (PCHAR)&pMsg->MessageHead );
  2590. messageLength = pMsg->MessageLength;
  2591. pMsg->MessageLength = messageLength = ntohs( messageLength );
  2592. if ( messageLength < sizeof(DNS_HEADER) )
  2593. {
  2594. DNS_PRINT((
  2595. "ERROR: Received TCP message with bad message"
  2596. " length %d.\n",
  2597. messageLength ));
  2598. goto BadTcpMessage;
  2599. }
  2600. recvLength = messageLength;
  2601. DNSDBG( TCP, (
  2602. "Received TCP message length %d, on socket %d,\n"
  2603. "\tfor msg at %p.\n",
  2604. messageLength,
  2605. socket,
  2606. pMsg ));
  2607. // starting recv of valid message length
  2608. if ( messageLength <= pMsg->BufferLength )
  2609. {
  2610. continue;
  2611. }
  2612. // note: currently do not realloc
  2613. goto BadTcpMessage;
  2614. #if 0
  2615. //
  2616. // DCR: allow TCP realloc
  2617. // - change call signature OR
  2618. // - return pMsg with ptr to realloced
  2619. // perhaps better to ignore and do 64K buffer all the time
  2620. //
  2621. // realloc, if existing message too small
  2622. //
  2623. pMsg = Dns_ReallocateTcpMessage( pMsg, messageLength );
  2624. if ( !pMsg )
  2625. {
  2626. return( GetLastError() );
  2627. }
  2628. #endif
  2629. }
  2630. }
  2631. //
  2632. // Message received
  2633. // recv ptr serves as flag, clear to start new message on reuse
  2634. //
  2635. pMsg->fMessageComplete = TRUE;
  2636. pMsg->pchRecv = NULL;
  2637. //
  2638. // return message information
  2639. // - flip count bytes
  2640. //
  2641. DNS_BYTE_FLIP_HEADER_COUNTS( &pMsg->MessageHead );
  2642. Trace_LogRecvEvent(
  2643. pMsg,
  2644. 0,
  2645. TRUE // TCP
  2646. );
  2647. IF_DNSDBG( RECV )
  2648. {
  2649. DnsDbg_Message(
  2650. "Received TCP packet",
  2651. pMsg );
  2652. }
  2653. return( ERROR_SUCCESS );
  2654. SockError:
  2655. err = GetLastError();
  2656. #if 0
  2657. //
  2658. // note: want non-blocking sockets if doing full async
  2659. //
  2660. // WSAEWOULD block is NORMAL return for message not fully recv'd.
  2661. // - save state of message reception
  2662. //
  2663. // We use non-blocking sockets, so bad client (that fails to complete
  2664. // message) doesn't hang TCP receiver.
  2665. //
  2666. if ( err == WSAEWOULDBLOCK )
  2667. {
  2668. pMsg->pchRecv = pchrecv;
  2669. pMsg->BytesToReceive = recvLength;
  2670. DNSDBG( TCP, (
  2671. "Leave ReceiveTcpMessage() after WSAEWOULDBLOCK.\n"
  2672. "\tSocket=%d, Msg=%p\n"
  2673. "\tBytes left to receive = %d\n",
  2674. socket,
  2675. pMsg,
  2676. pMsg->BytesToReceive
  2677. ));
  2678. goto CleanupConnection;
  2679. }
  2680. #endif
  2681. //
  2682. // cancelled connection
  2683. // -- perfectly legal, question is why
  2684. //
  2685. if ( pchrecv == (PCHAR) &pMsg->MessageLength
  2686. &&
  2687. ( err == WSAESHUTDOWN ||
  2688. err == WSAECONNABORTED ||
  2689. err == WSAECONNRESET ) )
  2690. {
  2691. DNSDBG( TCP, (
  2692. "WARNING: Recv RESET (%d) on socket %d\n",
  2693. err,
  2694. socket ));
  2695. goto CleanupConnection;
  2696. }
  2697. // anything else is our problem
  2698. DNS_LOG_EVENT(
  2699. DNS_EVENT_RECV_CALL_FAILED,
  2700. 0,
  2701. NULL,
  2702. err );
  2703. DNSDBG( ANY, (
  2704. "ERROR: recv() of TCP message failed.\n"
  2705. "\t%d bytes recvd\n"
  2706. "\t%d bytes left\n"
  2707. "\tGetLastError = 0x%08lx.\n",
  2708. pchrecv - (PCHAR)&pMsg->MessageLength,
  2709. recvLength,
  2710. err ));
  2711. DNS_ASSERT( FALSE );
  2712. goto CleanupConnection;
  2713. FinReceived:
  2714. //
  2715. // valid FIN -- if recv'd between messages (before message length)
  2716. //
  2717. DNSDBG( TCP, (
  2718. "ERROR: Recv TCP FIN (0 bytes) on socket %d\n",
  2719. socket,
  2720. recvLength ));
  2721. if ( !pMsg->MessageLength && pchrecv == (PCHAR)&pMsg->MessageLength )
  2722. {
  2723. err = DNS_ERROR_NO_PACKET;
  2724. goto CleanupConnection;
  2725. }
  2726. //
  2727. // FIN during message -- invalid message
  2728. //
  2729. DNSDBG( ANY, (
  2730. "ERROR: TCP message received has incorrect length.\n"
  2731. "\t%d bytes left when recv'd FIN.\n",
  2732. recvLength ));
  2733. goto BadTcpMessage;
  2734. BadTcpMessage:
  2735. {
  2736. PCHAR pchServer = MSG_REMOTE_IPADDR_STRING(pMsg);
  2737. DNS_LOG_EVENT(
  2738. DNS_EVENT_BAD_TCP_MESSAGE,
  2739. 1,
  2740. & pchServer,
  2741. 0 );
  2742. }
  2743. err = DNS_ERROR_BAD_PACKET;
  2744. CleanupConnection:
  2745. // note: don't actually close socket
  2746. // the socket is usually still referenced by the send message
  2747. // buffer and is closed when the calling function cleans it up
  2748. return err ? err : DNS_ERROR_BAD_PACKET;
  2749. }
  2750. DNS_STATUS
  2751. Send_AndRecvTcp(
  2752. IN OUT PSEND_BLOB pBlob
  2753. )
  2754. /*++
  2755. Routine Description:
  2756. Sends to and waits to recv from remote DNS.
  2757. INTERNAL public function.
  2758. Arguments:
  2759. pBlob -- send info
  2760. Return Value:
  2761. ERROR_SUCCESS if successful packet reception.
  2762. Error status on failure.
  2763. --*/
  2764. {
  2765. DNS_STATUS status = DNS_ERROR_NO_DNS_SERVERS;
  2766. DWORD rcode;
  2767. DWORD i;
  2768. PDNS_NETINFO pnetInfo;
  2769. PADDR_ARRAY pallocServerArray = NULL;
  2770. PADDR_ARRAY pservArray;
  2771. PIP4_ARRAY pserv4Array;
  2772. PDNS_MSG_BUF psendMsg;
  2773. PDNS_MSG_BUF precvMsg;
  2774. DNSDBG( SEND, (
  2775. "Enter Send_AndRecvTcp( %p )\n",
  2776. pBlob ));
  2777. //
  2778. // unpack
  2779. //
  2780. pnetInfo = pBlob->pNetInfo;
  2781. pservArray = pBlob->pServerList;
  2782. pserv4Array = pBlob->pServ4List;
  2783. psendMsg = pBlob->pSendMsg;
  2784. precvMsg = pBlob->Results.pMessage;
  2785. //
  2786. // verify params
  2787. //
  2788. if ( !psendMsg || !precvMsg || (!pnetInfo && !pservArray && !pserv4Array) )
  2789. {
  2790. return( ERROR_INVALID_PARAMETER );
  2791. }
  2792. //
  2793. // build server IP array?
  2794. //
  2795. // DCR: should use netinfo priorities in TCP also
  2796. // DCR: need TCP netinfo for IP6
  2797. // DCR: handle IP4 array -- here or ABOVE here
  2798. //
  2799. if ( !pservArray )
  2800. {
  2801. // FIX6: convert IP4 array here???
  2802. pallocServerArray = NetInfo_ConvertToAddrArray(
  2803. pnetInfo,
  2804. NULL, // all adapters
  2805. 0 // no addr family
  2806. );
  2807. if ( !pallocServerArray )
  2808. {
  2809. return( DNS_ERROR_NO_MEMORY );
  2810. }
  2811. pservArray = pallocServerArray;
  2812. }
  2813. //
  2814. // init messages for TCP
  2815. //
  2816. DNS_ASSERT( psendMsg->Socket == 0 );
  2817. psendMsg->fTcp = TRUE;
  2818. psendMsg->Socket = 0;
  2819. SET_MESSAGE_FOR_TCP_RECV( precvMsg );
  2820. //
  2821. // loop sending until
  2822. // - receive successful response
  2823. // or
  2824. // - receive errors response from all servers
  2825. // or
  2826. // - reach final timeout on all servers
  2827. //
  2828. if ( precvMsg->Timeout == 0 )
  2829. {
  2830. precvMsg->Timeout = DEFAULT_TCP_TIMEOUT;
  2831. }
  2832. for( i=0; i<pservArray->AddrCount; i++ )
  2833. {
  2834. //
  2835. // close any previous connection
  2836. //
  2837. if ( psendMsg->Socket )
  2838. {
  2839. Socket_CloseMessageSockets( psendMsg );
  2840. Socket_ClearMessageSockets( precvMsg );
  2841. }
  2842. //
  2843. // connect and send to next server
  2844. //
  2845. status = Send_OpenTcpConnectionAndSend(
  2846. psendMsg,
  2847. &pservArray->AddrArray[i],
  2848. TRUE
  2849. );
  2850. if ( status != ERROR_SUCCESS )
  2851. {
  2852. continue;
  2853. }
  2854. DNS_ASSERT( psendMsg->Socket != INVALID_SOCKET && psendMsg->Socket != 0 );
  2855. //
  2856. // receive response
  2857. // - if successful receive, done
  2858. // - if timeout continue
  2859. // - other errors indicate some setup or system level problem
  2860. // note: Dns_RecvTcp will close and zero msg->socket on error!
  2861. //
  2862. Send_SetMessageForRecv( precvMsg, psendMsg );
  2863. status = Dns_RecvTcp( precvMsg );
  2864. //
  2865. // timed out (or error)
  2866. // - if end of timeout, quit
  2867. // - otherwise double timeout and resend
  2868. //
  2869. switch( status )
  2870. {
  2871. case ERROR_SUCCESS:
  2872. break;
  2873. case ERROR_TIMEOUT:
  2874. DNS_PRINT((
  2875. "ERROR: connected to server at %s\n"
  2876. "\tbut no response to packet at %p\n",
  2877. MSG_REMOTE_IPADDR_STRING( psendMsg ),
  2878. psendMsg
  2879. ));
  2880. continue;
  2881. default:
  2882. DNS_PRINT((
  2883. "ERROR: connected to server at %s to send packet %p\n"
  2884. "\tbut error %d encountered on receive.\n",
  2885. MSG_REMOTE_IPADDR_STRING( psendMsg ),
  2886. psendMsg,
  2887. status
  2888. ));
  2889. continue;
  2890. }
  2891. //
  2892. // verify XID match
  2893. //
  2894. if ( precvMsg->MessageHead.Xid != psendMsg->MessageHead.Xid )
  2895. {
  2896. DNS_PRINT((
  2897. "ERROR: Incorrect XID in response. Ignoring.\n" ));
  2898. continue;
  2899. }
  2900. //
  2901. // verify question match
  2902. // - this is "Maggs Bug" check
  2903. // - ASSERT here just to investigate issue locally
  2904. // and make sure check is not bogus
  2905. //
  2906. if ( !Dns_IsSamePacketQuestion(
  2907. precvMsg,
  2908. psendMsg ))
  2909. {
  2910. DNS_PRINT((
  2911. "ERROR: Bad question response from server %s!\n"
  2912. "\tXID match, but question does not match question sent!\n",
  2913. MSG_REMOTE_IPADDR_STRING( psendMsg ) ));
  2914. DNS_ASSERT( FALSE );
  2915. continue;
  2916. }
  2917. //
  2918. // check response code
  2919. // - some move to next server, others terminal
  2920. //
  2921. // DCR_FIX1: bring TCP RCODE handling in-line with UDP
  2922. //
  2923. // DCR_FIX: save best TCP RCODE
  2924. // preserve RCODE (and message) for useless TCP response
  2925. // would need to then reset TIMEOUT to success at end
  2926. // or use these RCODEs as status returns
  2927. //
  2928. rcode = precvMsg->MessageHead.ResponseCode;
  2929. switch( rcode )
  2930. {
  2931. case DNS_RCODE_SERVER_FAILURE:
  2932. case DNS_RCODE_NOT_IMPLEMENTED:
  2933. case DNS_RCODE_REFUSED:
  2934. DNS_PRINT((
  2935. "WARNING: Servers have responded with failure.\n" ));
  2936. continue;
  2937. default:
  2938. break;
  2939. }
  2940. break;
  2941. } // end loop sending/recving UPDATEs
  2942. //
  2943. // close up final connection
  2944. // unless set to keep open for reuse
  2945. //
  2946. Socket_CloseMessageSockets( psendMsg );
  2947. Socket_ClearMessageSockets( precvMsg );
  2948. // if allocated adapter list free it
  2949. if ( pallocServerArray )
  2950. {
  2951. FREE_HEAP( pallocServerArray );
  2952. }
  2953. DNSDBG( SEND, (
  2954. "Leaving Send_AndRecvTcp()\n"
  2955. "\tstatus = %d\n",
  2956. status ));
  2957. return( status );
  2958. }
  2959. #if 0
  2960. DNS_STATUS
  2961. Dns_AsyncRecv(
  2962. IN OUT PDNS_MSG_BUF pMsgRecv
  2963. )
  2964. /*++
  2965. Routine Description:
  2966. Drop recv on async socket.
  2967. Arguments:
  2968. pMsgRecv - message to receive; OPTIONAL, if NULL message buffer
  2969. is allocated;
  2970. in either case global pDnsAsyncRecvMsg points at buffer
  2971. Return Value:
  2972. ERROR_SUCCESS if successful.
  2973. Error status on failure.
  2974. --*/
  2975. {
  2976. WSABUF wsabuf;
  2977. DWORD bytesRecvd;
  2978. DWORD flags = 0;
  2979. IF_DNSDBG( RECV )
  2980. {
  2981. DNS_PRINT((
  2982. "Enter Dns_AsyncRecv( %p )\n",
  2983. pMsgRecv ));
  2984. }
  2985. //
  2986. // allocate buffer if none given
  2987. //
  2988. if ( !pMsgRecv )
  2989. {
  2990. pMsgRecv = Dns_AllocateMsgBuf( MAXWORD );
  2991. if ( !pMsgRecv )
  2992. {
  2993. return( GetLastError() ):
  2994. }
  2995. }
  2996. pDnsAsyncRecvMsg = pMsgRecv;
  2997. //
  2998. // reset i/o completion event
  2999. //
  3000. ResetEvent( hDnsSocketEvent );
  3001. DNS_ASSERT( hDnsSocketEvent == Dns_SocketOverlapped.hEvent );
  3002. //
  3003. // drop down recv
  3004. //
  3005. status = WSARecvFrom(
  3006. DnsSocket,
  3007. & wsabuf,
  3008. 1,
  3009. & bytesRecvd, // dummy
  3010. & flags,
  3011. & pMsgRecv->RemoteAddress.Sockaddr,
  3012. & pMsgRecv->RemoteAddress.SockaddrLength,
  3013. & DnsSocketOverlapped,
  3014. NULL // no completion routine
  3015. );
  3016. return( ERROR_SUCCESS );
  3017. Failed:
  3018. return( status );
  3019. }
  3020. #endif
  3021. VOID
  3022. Dns_InitQueryTimeouts(
  3023. VOID
  3024. )
  3025. {
  3026. HKEY hKey = NULL;
  3027. DWORD status;
  3028. DWORD dwType;
  3029. DWORD ValueSize;
  3030. LPSTR lpTimeouts = NULL;
  3031. g_QueryTimeouts = QueryTimeouts;
  3032. g_QuickQueryTimeouts = QuickQueryTimeouts;
  3033. g_MulticastQueryTimeouts = MulticastQueryTimeouts;
  3034. status = RegOpenKeyExA(
  3035. HKEY_LOCAL_MACHINE,
  3036. NT_TCPIP_REG_LOCATION,
  3037. 0,
  3038. KEY_QUERY_VALUE,
  3039. &hKey );
  3040. if ( status )
  3041. return;
  3042. if ( !hKey )
  3043. return;
  3044. status = RegQueryValueExA(
  3045. hKey,
  3046. DNS_QUERY_TIMEOUTS,
  3047. NULL,
  3048. &dwType,
  3049. NULL,
  3050. &ValueSize );
  3051. if ( !status )
  3052. {
  3053. if ( ValueSize == 0 )
  3054. {
  3055. goto GetQuickQueryTimeouts;
  3056. }
  3057. lpTimeouts = ALLOCATE_HEAP( ValueSize );
  3058. if ( lpTimeouts )
  3059. {
  3060. LPSTR StringPtr;
  3061. DWORD StringLen;
  3062. DWORD Timeout;
  3063. DWORD Count = 0;
  3064. status = RegQueryValueExA( hKey,
  3065. DNS_QUERY_TIMEOUTS,
  3066. NULL,
  3067. &dwType,
  3068. lpTimeouts,
  3069. &ValueSize );
  3070. if ( status ||
  3071. dwType != REG_MULTI_SZ )
  3072. {
  3073. FREE_HEAP( lpTimeouts );
  3074. goto GetQuickQueryTimeouts;
  3075. }
  3076. StringPtr = lpTimeouts;
  3077. while ( ( StringLen = strlen( StringPtr ) ) != 0 &&
  3078. Count < DNS_MAX_QUERY_TIMEOUTS )
  3079. {
  3080. Timeout = atoi( StringPtr );
  3081. if ( Timeout )
  3082. RegistryQueryTimeouts[Count++] = Timeout;
  3083. StringPtr += (StringLen + 1);
  3084. }
  3085. RegistryQueryTimeouts[Count] = 0;
  3086. g_QueryTimeouts = RegistryQueryTimeouts;
  3087. FREE_HEAP( lpTimeouts );
  3088. }
  3089. }
  3090. GetQuickQueryTimeouts:
  3091. status = RegQueryValueExA( hKey,
  3092. DNS_QUICK_QUERY_TIMEOUTS,
  3093. NULL,
  3094. &dwType,
  3095. NULL,
  3096. &ValueSize );
  3097. if ( !status )
  3098. {
  3099. if ( ValueSize == 0 )
  3100. {
  3101. goto GetMulticastTimeouts;
  3102. }
  3103. lpTimeouts = ALLOCATE_HEAP( ValueSize );
  3104. if ( lpTimeouts )
  3105. {
  3106. LPSTR StringPtr;
  3107. DWORD StringLen;
  3108. DWORD Timeout;
  3109. DWORD Count = 0;
  3110. status = RegQueryValueExA( hKey,
  3111. DNS_QUICK_QUERY_TIMEOUTS,
  3112. NULL,
  3113. &dwType,
  3114. lpTimeouts,
  3115. &ValueSize );
  3116. if ( status ||
  3117. dwType != REG_MULTI_SZ )
  3118. {
  3119. FREE_HEAP( lpTimeouts );
  3120. goto GetMulticastTimeouts;
  3121. }
  3122. StringPtr = lpTimeouts;
  3123. while ( ( StringLen = strlen( StringPtr ) ) != 0 &&
  3124. Count < DNS_MAX_QUERY_TIMEOUTS )
  3125. {
  3126. Timeout = atoi( StringPtr );
  3127. if ( Timeout )
  3128. RegistryQuickQueryTimeouts[Count++] = Timeout;
  3129. StringPtr += (StringLen + 1);
  3130. }
  3131. RegistryQuickQueryTimeouts[Count] = 0;
  3132. g_QuickQueryTimeouts = RegistryQuickQueryTimeouts;
  3133. FREE_HEAP( lpTimeouts );
  3134. }
  3135. }
  3136. GetMulticastTimeouts:
  3137. status = RegQueryValueExA( hKey,
  3138. DNS_MULTICAST_QUERY_TIMEOUTS,
  3139. NULL,
  3140. &dwType,
  3141. NULL,
  3142. &ValueSize );
  3143. if ( !status )
  3144. {
  3145. if ( ValueSize == 0 )
  3146. {
  3147. RegCloseKey( hKey );
  3148. return;
  3149. }
  3150. lpTimeouts = ALLOCATE_HEAP( ValueSize );
  3151. if ( lpTimeouts )
  3152. {
  3153. LPSTR StringPtr;
  3154. DWORD StringLen;
  3155. DWORD Timeout;
  3156. DWORD Count = 0;
  3157. status = RegQueryValueExA( hKey,
  3158. DNS_MULTICAST_QUERY_TIMEOUTS,
  3159. NULL,
  3160. &dwType,
  3161. lpTimeouts,
  3162. &ValueSize );
  3163. if ( status ||
  3164. dwType != REG_MULTI_SZ )
  3165. {
  3166. FREE_HEAP( lpTimeouts );
  3167. RegCloseKey( hKey );
  3168. return;
  3169. }
  3170. StringPtr = lpTimeouts;
  3171. while ( ( StringLen = strlen( StringPtr ) ) != 0 &&
  3172. Count < DNS_MAX_QUERY_TIMEOUTS )
  3173. {
  3174. Timeout = atoi( StringPtr );
  3175. if ( Timeout )
  3176. RegistryMulticastQueryTimeouts[Count++] = Timeout;
  3177. StringPtr += (StringLen + 1);
  3178. }
  3179. RegistryMulticastQueryTimeouts[Count] = 0;
  3180. g_MulticastQueryTimeouts = RegistryMulticastQueryTimeouts;
  3181. FREE_HEAP( lpTimeouts );
  3182. }
  3183. }
  3184. RegCloseKey( hKey );
  3185. }
  3186. //
  3187. // OPT selection
  3188. //
  3189. // These routines track DNS server OPT awareness.
  3190. //
  3191. // The paradigm here is to default to sending OPTs, then track
  3192. // OPT non-awareness.
  3193. //
  3194. // DCR: RPC over OPT config info
  3195. // - either two lists (local and from-resolver in process)
  3196. // OR
  3197. // - RPC back OPT failures to resolver
  3198. // OR
  3199. // - flag network info blobs to RPC back to resolver
  3200. //
  3201. // security wise, prefer not to get info back
  3202. //
  3203. //
  3204. // DCR: OPT info in network info
  3205. // - then don't have to traverse locks
  3206. // - save is identical to current
  3207. // - could exclude OPT on any non-cache sends to
  3208. // handle problem of not saving OPT failures
  3209. //
  3210. //
  3211. // Global IP array of OPT-failed DNS servers
  3212. //
  3213. PADDR_ARRAY g_OptFailServerList = NULL;
  3214. // Allocation size for OptFail IP array.
  3215. // Ten servers nicely covers the typical case.
  3216. #define OPT_FAIL_LIST_SIZE 10
  3217. //
  3218. // Use global lock for OPT list
  3219. //
  3220. #define LOCK_OPT_LIST() LOCK_GENERAL()
  3221. #define UNLOCK_OPT_LIST() UNLOCK_GENERAL()
  3222. BOOL
  3223. Send_IsServerOptExclude(
  3224. IN PDNS_ADDR pAddr
  3225. )
  3226. /*++
  3227. Routine Description:
  3228. Determine if particular server is not OPT aware.
  3229. Arguments:
  3230. pAddr -- IP address of DNS server
  3231. Return Value:
  3232. TRUE if server should NOT get OPT send.
  3233. FALSE if server should can send OPT
  3234. --*/
  3235. {
  3236. BOOL retval;
  3237. //
  3238. // zero IP -- meaning TCP connect to unknown
  3239. // => must exclude OPT to allow success, otherwise
  3240. // we can't retry non-OPT
  3241. //
  3242. if ( !pAddr || DnsAddr_IsEmpty(pAddr) )
  3243. {
  3244. return TRUE;
  3245. }
  3246. //
  3247. // no exclusions?
  3248. // - doing outside lock for perf once we get to
  3249. // the "fully-deployed" case
  3250. //
  3251. if ( !g_OptFailServerList )
  3252. {
  3253. return FALSE;
  3254. }
  3255. //
  3256. // see if IP is in OPT list
  3257. // - only if found do we exclude
  3258. //
  3259. LOCK_OPT_LIST();
  3260. retval = FALSE;
  3261. if ( g_OptFailServerList
  3262. &&
  3263. AddrArray_ContainsAddr(
  3264. g_OptFailServerList,
  3265. pAddr ) )
  3266. {
  3267. retval = TRUE;
  3268. }
  3269. UNLOCK_OPT_LIST();
  3270. return retval;
  3271. }
  3272. VOID
  3273. Send_SetServerOptExclude(
  3274. IN PDNS_ADDR pAddr
  3275. )
  3276. /*++
  3277. Routine Description:
  3278. Set server for OPT exclusion.
  3279. Arguments:
  3280. IpAddress -- IP address of DNS server that failed OPT
  3281. Return Value:
  3282. None
  3283. --*/
  3284. {
  3285. //
  3286. // screen zero IP (TCP connect to unknown IP)
  3287. //
  3288. if ( !pAddr || DnsAddr_IsEmpty(pAddr) )
  3289. {
  3290. return;
  3291. }
  3292. //
  3293. // put IP in OPT-fail list
  3294. // - create if doesn't exist
  3295. // - resize if won't fit
  3296. // note: add failure means "won't fit"
  3297. //
  3298. // note: only safe to reset global if allocation successful
  3299. // note: only one retry to protect alloc failure looping
  3300. //
  3301. LOCK_OPT_LIST();
  3302. if ( ! g_OptFailServerList
  3303. ||
  3304. ! AddrArray_AddAddr(
  3305. g_OptFailServerList,
  3306. pAddr
  3307. ) )
  3308. {
  3309. PADDR_ARRAY pnewList;
  3310. pnewList = DnsAddrArray_CopyAndExpand(
  3311. g_OptFailServerList,
  3312. OPT_FAIL_LIST_SIZE,
  3313. TRUE // free current
  3314. );
  3315. if ( pnewList )
  3316. {
  3317. g_OptFailServerList = pnewList;
  3318. AddrArray_AddAddr(
  3319. g_OptFailServerList,
  3320. pAddr
  3321. );
  3322. }
  3323. }
  3324. UNLOCK_OPT_LIST();
  3325. }
  3326. VOID
  3327. Send_CleanupOptList(
  3328. VOID
  3329. )
  3330. /*++
  3331. Routine Description:
  3332. Dump OPT list for process detach.
  3333. Arguments:
  3334. None
  3335. Return Value:
  3336. None
  3337. --*/
  3338. {
  3339. LOCK_OPT_LIST();
  3340. DnsAddrArray_Free( g_OptFailServerList );
  3341. g_OptFailServerList = NULL;
  3342. UNLOCK_OPT_LIST();
  3343. }
  3344. //
  3345. // Main send routine
  3346. //
  3347. DNS_STATUS
  3348. Send_AndRecv(
  3349. IN OUT PSEND_BLOB pBlob
  3350. )
  3351. /*++
  3352. Routine Description:
  3353. Send message, receive response.
  3354. Arguments:
  3355. pBlob -- send blob
  3356. Return Value:
  3357. ERROR_SUCCESS if successful.
  3358. Error code on failure.
  3359. --*/
  3360. {
  3361. PDNS_NETINFO pnetInfo;
  3362. PIP4_ARRAY pserv4Array;
  3363. PADDR_ARRAY pservArray;
  3364. PADDR_ARRAY pservArrayIn = NULL;
  3365. PADDR_ARRAY pservArrayAlloc = NULL;
  3366. DWORD flags;
  3367. PDNS_MSG_BUF psendMsg;
  3368. PDNS_MSG_BUF precvMsg;
  3369. PDNS_MSG_BUF psavedUdpResponse = NULL;
  3370. DNS_STATUS statusFromUdp = ERROR_SUCCESS;
  3371. DNS_STATUS status = ERROR_TIMEOUT;
  3372. DNS_STATUS parseStatus;
  3373. BOOL ftcp;
  3374. ADDR_ARRAY tempArray;
  3375. //
  3376. // unpack
  3377. //
  3378. pnetInfo = pBlob->pNetInfo;
  3379. pservArray = pBlob->pServerList;
  3380. pserv4Array = pBlob->pServ4List;
  3381. flags = pBlob->Flags;
  3382. psendMsg = pBlob->pSendMsg;
  3383. precvMsg = pBlob->Results.pMessage;
  3384. pservArrayIn = pservArray;
  3385. DNSDBG( QUERY, (
  3386. "Send_AndRecv( %p )\n",
  3387. pBlob ));
  3388. IF_DNSDBG( QUERY )
  3389. {
  3390. DnsDbg_SendBlob(
  3391. "Send_AndRecv()",
  3392. pBlob );
  3393. }
  3394. //
  3395. // response buf passed in?
  3396. // if not allocate one -- big enough for TCP
  3397. //
  3398. if ( !precvMsg )
  3399. {
  3400. precvMsg = pBlob->pRecvMsgBuf;
  3401. if ( !precvMsg )
  3402. {
  3403. precvMsg = Dns_AllocateMsgBuf( DNS_TCP_DEFAULT_PACKET_LENGTH );
  3404. if ( !precvMsg )
  3405. {
  3406. status = DNS_ERROR_NO_MEMORY;
  3407. goto Cleanup;
  3408. }
  3409. }
  3410. }
  3411. //
  3412. // send packet and get response
  3413. // - try UDP first unless TCP only
  3414. //
  3415. ftcp = ( flags & DNS_QUERY_USE_TCP_ONLY ) ||
  3416. ( DNS_MESSAGE_CURRENT_OFFSET(psendMsg) >= DNS_RFC_MAX_UDP_PACKET_LENGTH );
  3417. if ( !ftcp )
  3418. {
  3419. if ( flags & DNS_QUERY_MULTICAST_ONLY )
  3420. {
  3421. //
  3422. // If the multicast query fails, then ERROR_TIMEOUT will
  3423. // be returned
  3424. //
  3425. goto DoMulticast;
  3426. }
  3427. if ( pserv4Array && !pservArray )
  3428. {
  3429. pservArrayAlloc = DnsAddrArray_CreateFromIp4Array( pserv4Array );
  3430. pservArray = pservArrayAlloc;
  3431. }
  3432. status = Send_AndRecvUdpWithParam(
  3433. psendMsg,
  3434. precvMsg,
  3435. flags,
  3436. pservArray,
  3437. pnetInfo );
  3438. statusFromUdp = status;
  3439. if ( status != ERROR_SUCCESS &&
  3440. status != DNS_ERROR_RCODE_NAME_ERROR &&
  3441. status != DNS_INFO_NO_RECORDS )
  3442. {
  3443. //
  3444. // DCR: this multicast ON_NAME_ERROR test is bogus
  3445. // this isn't NAME_ERROR this is pretty much any error
  3446. //
  3447. if ( pnetInfo &&
  3448. pnetInfo->InfoFlags & NINFO_FLAG_MULTICAST_ON_NAME_ERROR )
  3449. {
  3450. goto DoMulticast;
  3451. }
  3452. else
  3453. {
  3454. goto Cleanup;
  3455. }
  3456. }
  3457. // if truncated response switch to TCP
  3458. if ( precvMsg->MessageHead.Truncation &&
  3459. ! (flags & DNS_QUERY_ACCEPT_PARTIAL_UDP) )
  3460. {
  3461. ftcp = TRUE;
  3462. pservArrayIn = pservArray;
  3463. pservArray = &tempArray;
  3464. pBlob->pServerList = pservArray;
  3465. DnsAddrArray_InitSingleWithSockaddr(
  3466. pservArray,
  3467. &precvMsg->RemoteAddress.Sockaddr );
  3468. psavedUdpResponse = precvMsg;
  3469. precvMsg = NULL;
  3470. }
  3471. }
  3472. //
  3473. // TCP send
  3474. // - for TCP queries
  3475. // - or truncation on UDP unless accepting partial response
  3476. //
  3477. // DCR_FIX: this precvMsg Free is bad
  3478. // if message was passed in we shouldn't have it, we should
  3479. // just do our own thing and ignore this recv buffer somehow
  3480. // ideally that buffer action is at much higher level
  3481. //
  3482. if ( ftcp )
  3483. {
  3484. if ( precvMsg &&
  3485. precvMsg->BufferLength < DNS_TCP_DEFAULT_PACKET_LENGTH )
  3486. {
  3487. if ( precvMsg != pBlob->pRecvMsgBuf )
  3488. {
  3489. FREE_HEAP( precvMsg );
  3490. }
  3491. precvMsg = NULL;
  3492. }
  3493. if ( !precvMsg )
  3494. {
  3495. precvMsg = Dns_AllocateMsgBuf( DNS_TCP_DEFAULT_PACKET_LENGTH );
  3496. if ( !precvMsg )
  3497. {
  3498. status = DNS_ERROR_NO_MEMORY;
  3499. goto Cleanup;
  3500. }
  3501. }
  3502. psendMsg->fTcp = TRUE;
  3503. precvMsg->fTcp = TRUE;
  3504. #if 0
  3505. if ( flags & DNS_QUERY_SOCKET_KEEPALIVE )
  3506. {
  3507. precvMsg->fSocketKeepalive = TRUE;
  3508. }
  3509. #endif
  3510. pBlob->Results.pMessage = precvMsg;
  3511. status = Send_AndRecvTcp( pBlob );
  3512. //
  3513. // if recursing following truncated UDP query, then
  3514. // must make sure we actually have better data
  3515. // - if successful, but RCODE is different and bad
  3516. // => use UDP response
  3517. // - if failed TCP => use UDP
  3518. // - successful with good RCODE => parse TCP response
  3519. //
  3520. if ( psavedUdpResponse )
  3521. {
  3522. if ( status == ERROR_SUCCESS )
  3523. {
  3524. DWORD rcode = precvMsg->MessageHead.ResponseCode;
  3525. if ( rcode == ERROR_SUCCESS ||
  3526. rcode == psavedUdpResponse->MessageHead.ResponseCode ||
  3527. ( rcode != DNS_RCODE_SERVER_FAILURE &&
  3528. rcode != DNS_RCODE_FORMAT_ERROR &&
  3529. rcode != DNS_RCODE_REFUSED ) )
  3530. {
  3531. goto Parse;
  3532. }
  3533. }
  3534. // TCP failed or returned bum error code
  3535. FREE_HEAP( precvMsg );
  3536. precvMsg = psavedUdpResponse;
  3537. psavedUdpResponse = NULL;
  3538. }
  3539. // direct TCP query
  3540. // - cleanup if failed
  3541. else if ( status != ERROR_SUCCESS )
  3542. {
  3543. goto Cleanup;
  3544. }
  3545. }
  3546. //
  3547. // DCR: this multicast test is bogus (too wide open)
  3548. // essentially ANY error sends us on to multicast
  3549. // even INFO_NO_RECORDS
  3550. //
  3551. // multicast test should be intelligent
  3552. // - adpater with no DNS servers, or NO_RESPONSE
  3553. // from any DNS server
  3554. // multicast test also has to be skipped for update
  3555. //
  3556. if ( status == ERROR_SUCCESS )
  3557. {
  3558. DWORD rcode = precvMsg->MessageHead.ResponseCode;
  3559. if ( rcode == ERROR_SUCCESS ||
  3560. ( rcode != DNS_RCODE_SERVER_FAILURE &&
  3561. rcode != DNS_RCODE_FORMAT_ERROR &&
  3562. rcode != DNS_RCODE_REFUSED ) )
  3563. {
  3564. goto Parse;
  3565. }
  3566. }
  3567. //
  3568. // multicast?
  3569. //
  3570. DoMulticast:
  3571. if ( ( pnetInfo &&
  3572. pnetInfo->InfoFlags & NINFO_FLAG_ALLOW_MULTICAST )
  3573. ||
  3574. ( ( flags & DNS_QUERY_MULTICAST_ONLY ) &&
  3575. ! pnetInfo ) )
  3576. {
  3577. if ( !psendMsg ||
  3578. ( psendMsg &&
  3579. ( psendMsg->MessageHead.Opcode == DNS_OPCODE_UPDATE ) ) )
  3580. {
  3581. if ( statusFromUdp )
  3582. {
  3583. status = statusFromUdp;
  3584. }
  3585. else
  3586. {
  3587. status = DNS_ERROR_NO_DNS_SERVERS;
  3588. }
  3589. goto Cleanup;
  3590. }
  3591. status = Send_AndRecvMulticast(
  3592. psendMsg,
  3593. precvMsg,
  3594. pnetInfo );
  3595. if ( status != ERROR_SUCCESS &&
  3596. status != DNS_ERROR_RCODE_NAME_ERROR &&
  3597. status != DNS_INFO_NO_RECORDS )
  3598. {
  3599. if ( statusFromUdp )
  3600. {
  3601. status = statusFromUdp;
  3602. }
  3603. goto Cleanup;
  3604. }
  3605. }
  3606. //
  3607. // parse response (if desired)
  3608. //
  3609. // DCR: this is busted, should have one parsing function to handle
  3610. // taking fSaveRecords as param
  3611. // specifically need to tease out NO_RECORDS response even if
  3612. // not parsing records
  3613. //
  3614. Parse:
  3615. if ( pBlob->fSaveRecords )
  3616. {
  3617. parseStatus = Dns_ExtractRecordsFromMessage(
  3618. precvMsg,
  3619. //(flags & DNSQUERY_UNICODE_OUT),
  3620. TRUE, // unicode results
  3621. & pBlob->Results.pRecords );
  3622. if ( !(flags & DNS_QUERY_DONT_RESET_TTL_VALUES ) )
  3623. {
  3624. Dns_NormalizeAllRecordTtls( pBlob->Results.pRecords );
  3625. }
  3626. }
  3627. // not parsing -- just return RCODE as status
  3628. else
  3629. {
  3630. parseStatus = Dns_MapRcodeToStatus( precvMsg->MessageHead.ResponseCode );
  3631. }
  3632. //
  3633. // get "best" status
  3634. // - no-records response beats NAME_ERROR (or other error)
  3635. // dump bogus records from error response
  3636. //
  3637. // DCR: multi-adapter NXDOMAIN\no-records response broken
  3638. // note, here we'd give back a packet with NAME_ERROR
  3639. // or another error
  3640. //
  3641. if ( status != parseStatus )
  3642. {
  3643. // save previous NO_RECORDS response, from underlying query
  3644. // this trumps other errors (FORMERR, SERVFAIL, NXDOMAIN);
  3645. //
  3646. // note, that parsed message shouldn't be HIGHER level RCODE
  3647. // as these should beat out NO_RECORDS in original parsing
  3648. if ( status == DNS_INFO_NO_RECORDS &&
  3649. parseStatus != ERROR_SUCCESS )
  3650. {
  3651. ASSERT( precvMsg->MessageHead.ResponseCode <= DNS_RCODE_NAME_ERROR );
  3652. if ( pBlob->Results.pRecords )
  3653. {
  3654. Dns_RecordListFree( pBlob->Results.pRecords );
  3655. pBlob->Results.pRecords = NULL;
  3656. }
  3657. }
  3658. else
  3659. {
  3660. status = parseStatus;
  3661. }
  3662. }
  3663. Cleanup:
  3664. // cleanup recv buffer?
  3665. //
  3666. // DCR: should have more definitive "have-response" test
  3667. if ( pBlob->fSaveResponse &&
  3668. (status == ERROR_SUCCESS || Dns_IsStatusRcode(status)) )
  3669. {
  3670. pBlob->Results.pMessage = precvMsg;
  3671. }
  3672. else
  3673. {
  3674. if ( precvMsg != pBlob->pRecvMsgBuf )
  3675. {
  3676. FREE_HEAP( precvMsg );
  3677. }
  3678. pBlob->Results.pMessage = NULL;
  3679. }
  3680. if ( psavedUdpResponse )
  3681. {
  3682. FREE_HEAP( psavedUdpResponse );
  3683. }
  3684. // set response status
  3685. pBlob->Results.Status = status;
  3686. // replace original server array, if created
  3687. // new in TCP fallover
  3688. pBlob->pServerList = pservArrayIn;
  3689. if ( pservArrayAlloc )
  3690. {
  3691. DnsAddrArray_Free( pservArrayAlloc );
  3692. }
  3693. DNSDBG( RECV, (
  3694. "Leaving Send_AndRecv(), status = %s (%d)\n",
  3695. Dns_StatusString(status),
  3696. status ));
  3697. return( status );
  3698. }
  3699. //
  3700. // Obsolete exported crap
  3701. //
  3702. // May be here for ICS
  3703. //
  3704. DNS_STATUS
  3705. Dns_SendEx(
  3706. IN OUT PDNS_MSG_BUF pMsg,
  3707. IN IP4_ADDRESS IpAddr, OPTIONAL
  3708. IN BOOL fNoOpt
  3709. )
  3710. /*++
  3711. Routine Description:
  3712. Send a DNS packet.
  3713. This is the generic send routine used for ANY send of a DNS message.
  3714. It assumes nothing about the message type, but does assume:
  3715. - pCurrent points at byte following end of desired data
  3716. - RR count bytes are in HOST byte order
  3717. Note: EXPORTED function Dns_SendEx(), remove when clear
  3718. now an IP4 shim
  3719. DCR: Remove Dns_SendEx() from export when ICS fixed
  3720. Arguments:
  3721. pMsg - message info for message to send
  3722. IpAddr - IP to send to; OPTIONAL, required only if UDP
  3723. and message sockaddr not set
  3724. fNoOpt - TRUE if OPT send is forbidden
  3725. Return Value:
  3726. TRUE if successful.
  3727. FALSE on send error.
  3728. --*/
  3729. {
  3730. DNS_ADDR addr;
  3731. if ( IpAddr )
  3732. {
  3733. DnsAddr_BuildFromIp4(
  3734. &addr,
  3735. IpAddr,
  3736. 0 );
  3737. }
  3738. return Send_MessagePrivate(
  3739. pMsg,
  3740. IpAddr ? &addr : NULL,
  3741. fNoOpt
  3742. );
  3743. }
  3744. VOID
  3745. Dns_InitializeMsgRemoteSockaddr(
  3746. IN OUT PDNS_MSG_BUF pMsg,
  3747. IN IP4_ADDRESS IpAddr
  3748. )
  3749. /*++
  3750. Routine Description:
  3751. Initialize remote sockaddr.
  3752. Note: EXPORTED function -- IP4 shim
  3753. // DCR: EXPORTED may remove when clean
  3754. Arguments:
  3755. pMsg - message to send
  3756. IpAddr - IP4 address to send to
  3757. Return Value:
  3758. None.
  3759. --*/
  3760. {
  3761. DNS_ADDR addr;
  3762. DnsAddr_BuildFromIp4(
  3763. &addr,
  3764. IpAddr,
  3765. 0 );
  3766. Send_SetMsgRemoteSockaddr(
  3767. pMsg,
  3768. &addr );
  3769. }
  3770. DNS_STATUS
  3771. Dns_OpenTcpConnectionAndSend(
  3772. IN OUT PDNS_MSG_BUF pMsg,
  3773. IN IP4_ADDRESS IpAddr,
  3774. IN BOOL fBlocking
  3775. )
  3776. /*++
  3777. Routine Description:
  3778. Connect via TCP to desired server.
  3779. EXPORTED function! IP4 shim. Dns_OpenTcpConnectionAndSend() remove when clear
  3780. // DCR: EXPORTED may remove when clean
  3781. Arguments:
  3782. pMsg -- message info to set with connection socket
  3783. ipServer -- IP of DNS server to connect to
  3784. fBlocking -- blocking connection
  3785. Return Value:
  3786. TRUE if successful.
  3787. FALSE on connect error.
  3788. --*/
  3789. {
  3790. DNS_ADDR addr;
  3791. DnsAddr_BuildFromIp4(
  3792. &addr,
  3793. IpAddr,
  3794. 0 );
  3795. return Send_OpenTcpConnectionAndSend(
  3796. pMsg,
  3797. &addr,
  3798. fBlocking );
  3799. }
  3800. DNS_STATUS
  3801. Dns_SendAndRecvUdp(
  3802. IN OUT PDNS_MSG_BUF pMsgSend,
  3803. OUT PDNS_MSG_BUF pMsgRecv,
  3804. IN DWORD dwFlags,
  3805. IN PIP4_ARRAY pServ4List,
  3806. IN OUT PDNS_NETINFO pNetInfo
  3807. )
  3808. /*++
  3809. Routine Description:
  3810. Sends to and waits to recv from remote DNS.
  3811. EXPORTED function! Dns_SendAndRecvUdp() Kill once clear.
  3812. Arguments:
  3813. pMsgSend - message to send
  3814. ppMsgRecv - and reuse
  3815. dwFlags -- query flags
  3816. pServ4List -- list of server to use (IP4); overrides adapter info
  3817. pNetInfo -- adapter list DNS server info
  3818. Return Value:
  3819. ERROR_SUCCESS if successful response.
  3820. Error status for "best RCODE" response if rcode.
  3821. ERROR_TIMEOUT on timeout.
  3822. Error status on send\recv failure.
  3823. --*/
  3824. {
  3825. DNS_STATUS status;
  3826. PADDR_ARRAY parray;
  3827. //
  3828. // convert 4 to 6
  3829. //
  3830. parray = DnsAddrArray_CreateFromIp4Array( pServ4List );
  3831. status = Send_AndRecvUdpWithParam(
  3832. pMsgSend,
  3833. pMsgRecv,
  3834. dwFlags,
  3835. parray,
  3836. pNetInfo );
  3837. DnsAddrArray_Free( parray );
  3838. return status;
  3839. }