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.

1092 lines
22 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. rrcomp.c
  5. Abstract:
  6. Domain Name System (DNS) Library
  7. Compare resource record routines.
  8. Author:
  9. Jim Gilroy (jamesg) February, 1997
  10. Revision History:
  11. --*/
  12. #include "local.h"
  13. #include "locale.h" // for setlocale stuff for Win9x
  14. //
  15. // Type specific RR compare routine prototypes
  16. //
  17. BOOL
  18. ARecordCompare(
  19. IN PDNS_RECORD pRR1,
  20. IN PDNS_RECORD pRR2
  21. )
  22. /*++
  23. Routine Description:
  24. Compare A records.
  25. All these routines assume:
  26. - type compare complete
  27. - datalength compare completed
  28. - NO unicode
  29. Arguments:
  30. pRR1 - first record
  31. pRR2 -- second record
  32. Return Value:
  33. TRUE if record data equal
  34. FALSE otherwise
  35. --*/
  36. {
  37. return( pRR1->Data.A.IpAddress == pRR2->Data.A.IpAddress );
  38. }
  39. BOOL
  40. PtrRecordCompare(
  41. IN PDNS_RECORD pRR1,
  42. IN PDNS_RECORD pRR2
  43. )
  44. /*++
  45. Routine Description:
  46. Compare PTR compatible record.
  47. Includes: NS, PTR, CNAME, MB, MR, MG, MD, MF
  48. Arguments:
  49. pRR1 - first record
  50. pRR2 -- second record
  51. Return Value:
  52. TRUE if record data equal
  53. FALSE otherwise
  54. --*/
  55. {
  56. return Dns_NameComparePrivate(
  57. (LPSTR) pRR1->Data.PTR.pNameHost,
  58. (LPSTR) pRR2->Data.PTR.pNameHost,
  59. RECORD_CHARSET(pRR1) );
  60. }
  61. BOOL
  62. MxRecordCompare(
  63. IN PDNS_RECORD pRR1,
  64. IN PDNS_RECORD pRR2
  65. )
  66. /*++
  67. Routine Description:
  68. Compare MX compatible record.
  69. Includes: MX, RT, AFSDB
  70. Arguments:
  71. pRR1 - first record
  72. pRR2 -- second record
  73. Return Value:
  74. TRUE if record data equal
  75. FALSE otherwise
  76. --*/
  77. {
  78. // verify preference match first
  79. if ( pRR1->Data.MX.wPreference != pRR2->Data.MX.wPreference )
  80. {
  81. return( FALSE );
  82. }
  83. // then result is name comparison
  84. return Dns_NameComparePrivate(
  85. (LPSTR) pRR1->Data.MX.pNameExchange,
  86. (LPSTR) pRR2->Data.MX.pNameExchange,
  87. RECORD_CHARSET(pRR1) );
  88. }
  89. BOOL
  90. SoaRecordCompare(
  91. IN PDNS_RECORD pRR1,
  92. IN PDNS_RECORD pRR2
  93. )
  94. /*++
  95. Routine Description:
  96. Compare SOA record.
  97. Arguments:
  98. pRR1 - first record
  99. pRR2 -- second record
  100. Return Value:
  101. TRUE if record data equal
  102. FALSE otherwise
  103. --*/
  104. {
  105. // verify integer data match first
  106. if ( memcmp( & pRR1->Data.SOA.dwSerialNo,
  107. & pRR2->Data.SOA.dwSerialNo,
  108. SIZEOF_SOA_FIXED_DATA ) )
  109. {
  110. return( FALSE );
  111. }
  112. // match check names
  113. // - primary name server
  114. // - admin email name
  115. if ( ! Dns_NameComparePrivate(
  116. (LPSTR) pRR1->Data.SOA.pNamePrimaryServer,
  117. (LPSTR) pRR2->Data.SOA.pNamePrimaryServer,
  118. RECORD_CHARSET(pRR1) ) )
  119. {
  120. return( FALSE );
  121. }
  122. return Dns_NameComparePrivate(
  123. (LPSTR) pRR1->Data.SOA.pNameAdministrator,
  124. (LPSTR) pRR2->Data.SOA.pNameAdministrator,
  125. RECORD_CHARSET(pRR1) );
  126. }
  127. BOOL
  128. MinfoRecordCompare(
  129. IN PDNS_RECORD pRR1,
  130. IN PDNS_RECORD pRR2
  131. )
  132. /*++
  133. Routine Description:
  134. Compare MINFO and RP records.
  135. Arguments:
  136. pRR1 -- first record
  137. pRR2 -- second record
  138. Return Value:
  139. TRUE if record data equal
  140. FALSE otherwise
  141. --*/
  142. {
  143. if ( ! Dns_NameComparePrivate(
  144. (LPSTR) pRR1->Data.MINFO.pNameMailbox,
  145. (LPSTR) pRR2->Data.MINFO.pNameMailbox,
  146. RECORD_CHARSET(pRR1) ) )
  147. {
  148. return( FALSE );
  149. }
  150. return Dns_NameComparePrivate(
  151. (LPSTR) pRR1->Data.MINFO.pNameErrorsMailbox,
  152. (LPSTR) pRR2->Data.MINFO.pNameErrorsMailbox,
  153. RECORD_CHARSET(pRR1) );
  154. }
  155. BOOL
  156. TxtRecordCompare(
  157. IN PDNS_RECORD pRR1,
  158. IN PDNS_RECORD pRR2
  159. )
  160. /*++
  161. Routine Description:
  162. Compare TXT compatible records.
  163. Includes: TXT, X25, HINFO, ISDN
  164. Arguments:
  165. pRR1 -- first record
  166. pRR2 -- second record
  167. Return Value:
  168. TRUE if record data equal
  169. FALSE otherwise
  170. --*/
  171. {
  172. DWORD count;
  173. PCHAR * pstring1;
  174. PCHAR * pstring2;
  175. //
  176. // compare every string
  177. // since string order DOES matter
  178. // - find string count
  179. // - compare each (case-sensitive)
  180. //
  181. count = pRR1->Data.TXT.dwStringCount;
  182. if ( count != pRR2->Data.TXT.dwStringCount )
  183. {
  184. return( FALSE );
  185. }
  186. pstring1 = (PCHAR *) pRR1->Data.TXT.pStringArray;
  187. pstring2 = (PCHAR *) pRR2->Data.TXT.pStringArray;
  188. while ( count-- )
  189. {
  190. if ( IS_UNICODE_RECORD(pRR1) )
  191. {
  192. if ( wcscmp( (LPWSTR)*pstring1++, (LPWSTR)*pstring2++ ) != 0 )
  193. {
  194. return( FALSE );
  195. }
  196. }
  197. else
  198. {
  199. if ( strcmp( *pstring1++, *pstring2++ ) != 0 )
  200. {
  201. return( FALSE );
  202. }
  203. }
  204. }
  205. return( TRUE );
  206. }
  207. BOOL
  208. FlatRecordCompare(
  209. IN PDNS_RECORD pRR1,
  210. IN PDNS_RECORD pRR2
  211. )
  212. /*++
  213. Routine Description:
  214. Compare flat data records.
  215. Includes AAAA type.
  216. Arguments:
  217. pRR1 -- first record
  218. pRR2 -- second record
  219. Return Value:
  220. TRUE if record data equal
  221. FALSE otherwise
  222. --*/
  223. {
  224. if ( pRR1->wDataLength != pRR2->wDataLength )
  225. {
  226. return( FALSE );
  227. }
  228. return( !memcmp( & pRR1->Data,
  229. & pRR2->Data,
  230. pRR1->wDataLength ) );
  231. }
  232. BOOL
  233. SrvRecordCompare(
  234. IN PDNS_RECORD pRR1,
  235. IN PDNS_RECORD pRR2
  236. )
  237. /*++
  238. Routine Description:
  239. Compare SRV record.
  240. Arguments:
  241. pRR1 -- first record
  242. pRR2 -- second record
  243. Return Value:
  244. TRUE if record data equal
  245. FALSE otherwise
  246. --*/
  247. {
  248. // verify integer data match first
  249. if ( memcmp( & pRR1->Data.SRV.wPriority,
  250. & pRR2->Data.SRV.wPriority,
  251. SIZEOF_SRV_FIXED_DATA ) )
  252. {
  253. return( FALSE );
  254. }
  255. // then result is compare on target host
  256. return Dns_NameComparePrivate(
  257. (LPSTR) pRR1->Data.SRV.pNameTarget,
  258. (LPSTR) pRR2->Data.SRV.pNameTarget,
  259. RECORD_CHARSET(pRR1) );
  260. }
  261. BOOL
  262. AtmaRecordCompare(
  263. IN PDNS_RECORD pRR1,
  264. IN PDNS_RECORD pRR2
  265. )
  266. /*++
  267. Routine Description:
  268. Compare ATMA record.
  269. Arguments:
  270. pRR1 -- first record
  271. pRR2 -- second record
  272. Return Value:
  273. TRUE if record data equal
  274. FALSE otherwise
  275. --*/
  276. {
  277. WORD length = pRR1->wDataLength;
  278. if ( length > pRR2->wDataLength )
  279. {
  280. length = pRR2->wDataLength;
  281. }
  282. // verify integer data match first
  283. if ( pRR1->Data.ATMA.AddressType != pRR2->Data.ATMA.AddressType )
  284. {
  285. return( FALSE );
  286. }
  287. if ( memcmp(
  288. pRR1->Data.ATMA.Address,
  289. pRR2->Data.ATMA.Address,
  290. length ) != 0 )
  291. {
  292. return( FALSE );
  293. }
  294. return( TRUE );
  295. }
  296. //
  297. // RR compare routines jump table
  298. //
  299. typedef BOOL (* RR_COMPARE_FUNCTION)(
  300. PDNS_RECORD,
  301. PDNS_RECORD );
  302. //extern RR_COMPARE_FUNCTION RRCompareTable[];
  303. RR_COMPARE_FUNCTION RRCompareTable[] =
  304. {
  305. NULL, // ZERO
  306. ARecordCompare, // A
  307. PtrRecordCompare, // NS
  308. PtrRecordCompare, // MD
  309. PtrRecordCompare, // MF
  310. PtrRecordCompare, // CNAME
  311. SoaRecordCompare, // SOA
  312. PtrRecordCompare, // MB
  313. PtrRecordCompare, // MG
  314. PtrRecordCompare, // MR
  315. NULL, // NULL
  316. NULL, //WksRecordCompare, // WKS
  317. PtrRecordCompare, // PTR
  318. TxtRecordCompare, // HINFO
  319. MinfoRecordCompare, // MINFO
  320. MxRecordCompare, // MX
  321. TxtRecordCompare, // TXT
  322. MinfoRecordCompare, // RP
  323. MxRecordCompare, // AFSDB
  324. TxtRecordCompare, // X25
  325. TxtRecordCompare, // ISDN
  326. MxRecordCompare, // RT
  327. NULL, // NSAP
  328. NULL, // NSAPPTR
  329. NULL, // SIG
  330. NULL, // KEY
  331. NULL, // PX
  332. NULL, // GPOS
  333. FlatRecordCompare, // AAAA
  334. NULL, // LOC
  335. NULL, // NXT
  336. NULL, // EID
  337. NULL, // NIMLOC
  338. SrvRecordCompare, // SRV
  339. AtmaRecordCompare, // ATMA
  340. NULL, // NAPTR
  341. NULL, // KX
  342. NULL, // CERT
  343. NULL, // A6
  344. NULL, // DNAME
  345. NULL, // SINK
  346. NULL, // OPT
  347. NULL, // 42
  348. NULL, // 43
  349. NULL, // 44
  350. NULL, // 45
  351. NULL, // 46
  352. NULL, // 47
  353. NULL, // 48
  354. //
  355. // NOTE: last type indexed by type ID MUST be set
  356. // as MAX_SELF_INDEXED_TYPE #define in record.h
  357. // (see note above in record info table)
  358. //
  359. // Pseudo record types
  360. //
  361. NULL, // TKEY
  362. NULL, // TSIG
  363. //
  364. // MS only types
  365. //
  366. FlatRecordCompare, // WINS
  367. NULL, // WINSR
  368. };
  369. BOOL
  370. WINAPI
  371. Dns_RecordCompare(
  372. IN PDNS_RECORD pRecord1,
  373. IN PDNS_RECORD pRecord2
  374. )
  375. /*++
  376. Routine Description:
  377. Compare two records.
  378. Record compare ignores TTL and flags and section information.
  379. Arguments:
  380. pRecord1 -- first record
  381. pRecord2 -- second record
  382. Return Value:
  383. TRUE if records equal.
  384. FALSE otherwise.
  385. --*/
  386. {
  387. BOOL fresult;
  388. WORD type = pRecord1->wType;
  389. WORD index;
  390. IF_DNSDBG( UPDATE )
  391. {
  392. DNS_PRINT((
  393. "Dns_RecordCompare()\n"
  394. "\tfirst = %p\n"
  395. "\tfirst = %p\n",
  396. pRecord1,
  397. pRecord2 ));
  398. }
  399. //
  400. // verify that both records have same character set
  401. //
  402. if ( RECORD_CHARSET(pRecord1) != RECORD_CHARSET(pRecord2) )
  403. {
  404. DNS_PRINT(( "ERROR: comparing records with non-matching character sets!\n" ));
  405. //
  406. // If they are different and one of them is undefined, just use
  407. // the defined char set of the other for each.
  408. //
  409. if ( !RECORD_CHARSET(pRecord1) && RECORD_CHARSET(pRecord2) )
  410. {
  411. RECORD_CHARSET(pRecord1) = RECORD_CHARSET(pRecord2);
  412. }
  413. if ( !RECORD_CHARSET(pRecord2) && RECORD_CHARSET(pRecord1) )
  414. {
  415. RECORD_CHARSET(pRecord2) = RECORD_CHARSET(pRecord1);
  416. }
  417. }
  418. //
  419. // compare type
  420. //
  421. if ( type != pRecord2->wType )
  422. {
  423. DNSDBG( UPDATE, (
  424. "record compare failed -- type mismatch\n" ));
  425. return( FALSE );
  426. }
  427. //
  428. // compare names
  429. //
  430. if ( ! Dns_NameComparePrivate(
  431. pRecord1->pName,
  432. pRecord2->pName,
  433. RECORD_CHARSET( pRecord1 )
  434. ) )
  435. {
  436. DNSDBG( UPDATE, (
  437. "record compare failed -- owner name mismatch\n" ));
  438. return( FALSE );
  439. }
  440. //
  441. // compare data
  442. //
  443. index = INDEX_FOR_TYPE( type );
  444. DNS_ASSERT( index <= MAX_RECORD_TYPE_INDEX );
  445. if ( !index || !RRCompareTable[ index ] )
  446. {
  447. fresult = FlatRecordCompare( pRecord1, pRecord2 );
  448. }
  449. else
  450. {
  451. fresult = RRCompareTable[ index ](
  452. pRecord1,
  453. pRecord2 );
  454. }
  455. IF_DNSDBG( UPDATE )
  456. {
  457. DNS_PRINT((
  458. "Dns_RecordCompare(%p, %p) returns = %d.\n",
  459. pRecord1,
  460. pRecord2,
  461. fresult ));
  462. }
  463. return( fresult );
  464. }
  465. DNS_STATUS
  466. buildUnmatchedRecordSet(
  467. OUT PDNS_RECORD * ppDiffRR,
  468. IN OUT PDNS_RECORD pRR
  469. )
  470. /*++
  471. Routine Description:
  472. Build new list of difference records.
  473. Arguments:
  474. ppDiffRR - address to recieve PTR to new set
  475. pRR - incoming RR set; matched records marked wReserved TRUE
  476. Return Value:
  477. ERROR_SUCCESS if successful.
  478. Error code on failure.
  479. --*/
  480. {
  481. PDNS_RECORD pcur;
  482. PDNS_RECORD pnew;
  483. DNS_RRSET rrset;
  484. // init comparison rrset
  485. DNS_RRSET_INIT( rrset );
  486. //
  487. // loop through RR set, add records to either match or diff sets
  488. //
  489. pcur = pRR;
  490. while ( pcur )
  491. {
  492. if ( ! IS_RR_MATCHED(pcur) )
  493. {
  494. // make copy of record
  495. pnew = Dns_RecordCopyEx(
  496. pcur,
  497. RECORD_CHARSET(pcur),
  498. RECORD_CHARSET(pcur)
  499. );
  500. if ( !pnew )
  501. {
  502. // DCR_FIX1: last error not set on all Dns_RecordCopy() failures
  503. // Charlie Wickham was getting some random win32 error
  504. //
  505. // DNS_STATUS status = GetLastError();
  506. // assume unable to copy because of invalid data
  507. DNS_PRINT((
  508. "ERROR: unable to copy record at %p\n"
  509. "\thence unable to build diff of set at %p\n",
  510. pcur,
  511. pRR ));
  512. Dns_RecordListFree( rrset.pFirstRR );
  513. *ppDiffRR = NULL;
  514. //return( status ? status : ERROR_INVALID_DATA );
  515. return( ERROR_INVALID_DATA );
  516. }
  517. DNS_RRSET_ADD( rrset, pnew );
  518. }
  519. pcur = pcur->pNext;
  520. }
  521. *ppDiffRR = rrset.pFirstRR;
  522. return( ERROR_SUCCESS );
  523. }
  524. DWORD
  525. isUnmatchedRecordInSet(
  526. IN PDNS_RECORD pRR
  527. )
  528. /*++
  529. Routine Description:
  530. Check if unmatched record in set.
  531. Arguments:
  532. pRR - incoming RR set; matched records marked wReserved TRUE
  533. Return Value:
  534. Count of all unmatched records in set.
  535. Zero if all records matched.
  536. --*/
  537. {
  538. PDNS_RECORD pcur;
  539. DWORD countUnmatched = 0;
  540. //
  541. // loop through RR set check for unmatched records
  542. //
  543. pcur = pRR;
  544. while ( pcur )
  545. {
  546. if ( ! IS_RR_MATCHED(pcur) )
  547. {
  548. countUnmatched++;
  549. }
  550. pcur = pcur->pNext;
  551. }
  552. return( countUnmatched );
  553. }
  554. DNS_SET_COMPARE_RESULT
  555. WINAPI
  556. Dns_RecordSetCompareEx(
  557. IN OUT PDNS_RECORD pRR1,
  558. IN OUT PDNS_RECORD pRR2,
  559. OUT PDNS_RECORD * ppDiff1, OPTIONAL
  560. OUT PDNS_RECORD * ppDiff2 OPTIONAL
  561. )
  562. /*++
  563. Routine Description:
  564. Compare two records.
  565. Record compare ignores TTL and flags and section information.
  566. Arguments:
  567. pRR1 - first incoming RR set
  568. pRR2 - second incoming RR set
  569. ppDiff1 - addr to receive ptr to unmatched records from first set
  570. ppDiff2 - addr to receive ptr to unmatched records from second set
  571. Return Value:
  572. Result indicating relationship -- or error on allocation error:
  573. DnsSetCompareError
  574. DnsSetCompareIdentical
  575. DnsSetCompareNoOverlap
  576. DnsSetCompareOneSubsetOfTwo
  577. DnsSetCompareTwoSubsetOfOne
  578. DnsSetCompareIntersection
  579. --*/
  580. {
  581. PDNS_RECORD pcur1;
  582. PDNS_RECORD pcur2;
  583. DWORD count1 = 0;
  584. DWORD count2 = 0;
  585. DNS_STATUS status;
  586. DWORD unmatched1;
  587. DWORD unmatched2;
  588. DNS_SET_COMPARE_RESULT result;
  589. //
  590. // init RR sets for compare
  591. // - clear reserved field used as matched flag in compare
  592. //
  593. pcur1 = pRR1;
  594. while ( pcur1 )
  595. {
  596. CLEAR_RR_MATCHED(pcur1);
  597. pcur1 = pcur1->pNext;
  598. count1++;
  599. }
  600. pcur1 = pRR2;
  601. while ( pcur1 )
  602. {
  603. CLEAR_RR_MATCHED(pcur1);
  604. pcur1 = pcur1->pNext;
  605. count2++;
  606. }
  607. //
  608. // loop through set 1
  609. // attempt match of each record to all records in set 2
  610. // except those already matched
  611. pcur1 = pRR1;
  612. while ( pcur1 )
  613. {
  614. pcur2 = pRR2;
  615. while ( pcur2 )
  616. {
  617. if ( !IS_RR_MATCHED(pcur2) && Dns_RecordCompare( pcur1, pcur2 ) )
  618. {
  619. SET_RR_MATCHED(pcur1);
  620. SET_RR_MATCHED(pcur2);
  621. }
  622. pcur2 = pcur2->pNext;
  623. }
  624. pcur1 = pcur1->pNext;
  625. }
  626. //
  627. // get diff record lists, return
  628. // - if no diffs, then have match
  629. //
  630. // tedious, but do all this error handling because it is easy for
  631. // user to pass in bad records that may fail copy routines, need
  632. // way to easily report info, even if only for debugging apps calling in
  633. //
  634. if ( ppDiff2 )
  635. {
  636. *ppDiff2 = NULL;
  637. }
  638. if ( ppDiff1 )
  639. {
  640. *ppDiff1 = NULL;
  641. status = buildUnmatchedRecordSet( ppDiff1, pRR1 );
  642. if ( status != ERROR_SUCCESS )
  643. {
  644. goto Failed;
  645. }
  646. }
  647. if ( ppDiff2 )
  648. {
  649. status = buildUnmatchedRecordSet( ppDiff2, pRR2 );
  650. if ( status != ERROR_SUCCESS )
  651. {
  652. if ( ppDiff1 && *ppDiff1 )
  653. {
  654. Dns_RecordListFree( *ppDiff1 );
  655. }
  656. goto Failed;
  657. }
  658. }
  659. //
  660. // determine relationship between sets
  661. //
  662. // impl note: the only better way i could see doing this
  663. // is to map relationships directly to bit flags
  664. // however, our enum type doesn't map to bit flags, so
  665. // then would have to run mapping table to map flags to enum
  666. //
  667. // note, we do compare so that NULL lists comes out the first
  668. // as no-overlap rather than as subset
  669. //
  670. unmatched1 = isUnmatchedRecordInSet( pRR1 );
  671. unmatched2 = isUnmatchedRecordInSet( pRR2 );
  672. if ( unmatched1 == count1 )
  673. {
  674. ASSERT( unmatched2 == count2 );
  675. result = DnsSetCompareNoOverlap;
  676. }
  677. else if ( unmatched1 == 0 )
  678. {
  679. if ( unmatched2 == 0 )
  680. {
  681. result = DnsSetCompareIdentical;
  682. }
  683. else
  684. {
  685. ASSERT( unmatched2 != count2 );
  686. result = DnsSetCompareOneSubsetOfTwo;
  687. }
  688. }
  689. else if ( unmatched2 == 0 )
  690. {
  691. result = DnsSetCompareTwoSubsetOfOne;
  692. }
  693. else
  694. {
  695. ASSERT( unmatched2 != count2 );
  696. result = DnsSetCompareIntersection;
  697. }
  698. return( result );
  699. Failed:
  700. SetLastError( status );
  701. return( DnsSetCompareError );
  702. }
  703. BOOL
  704. WINAPI
  705. Dns_RecordSetCompare(
  706. IN OUT PDNS_RECORD pRR1,
  707. IN OUT PDNS_RECORD pRR2,
  708. OUT PDNS_RECORD * ppDiff1, OPTIONAL
  709. OUT PDNS_RECORD * ppDiff2 OPTIONAL
  710. )
  711. /*++
  712. Routine Description:
  713. Compare two records.
  714. Record compare ignores TTL and flags and section information.
  715. Arguments:
  716. pRR1 - first incoming RR set
  717. pRR2 - second incoming RR set
  718. ppDiff1 - addr to receive ptr to unmatched records from first set
  719. ppDiff2 - addr to receive ptr to unmatched records from second set
  720. Return Value:
  721. TRUE if record sets equal.
  722. FALSE otherwise.
  723. --*/
  724. {
  725. DNS_SET_COMPARE_RESULT result;
  726. result = Dns_RecordSetCompareEx(
  727. pRR1,
  728. pRR2,
  729. ppDiff1,
  730. ppDiff2 );
  731. return( result == DnsSetCompareIdentical );
  732. }
  733. BOOL
  734. WINAPI
  735. Dns_RecordSetCompareForIntersection(
  736. IN OUT PDNS_RECORD pRR1,
  737. IN OUT PDNS_RECORD pRR2
  738. )
  739. /*++
  740. Routine Description:
  741. Compare two record sets for intersection.
  742. Arguments:
  743. pRR1 - first incoming RR set
  744. pRR2 - second incoming RR set
  745. Return Value:
  746. TRUE if record sets intersect.
  747. FALSE otherwise.
  748. --*/
  749. {
  750. DNS_SET_COMPARE_RESULT result;
  751. result = Dns_RecordSetCompareEx(
  752. pRR1,
  753. pRR2,
  754. NULL,
  755. NULL );
  756. return( result == DnsSetCompareIdentical ||
  757. result == DnsSetCompareIntersection ||
  758. result == DnsSetCompareOneSubsetOfTwo ||
  759. result == DnsSetCompareTwoSubsetOfOne );
  760. }
  761. //
  762. // End rrcomp.c
  763. //
  764. BOOL
  765. WINAPI
  766. Dns_DeleteRecordFromList(
  767. IN OUT PDNS_RECORD * ppRRList,
  768. IN PDNS_RECORD pRRDelete
  769. )
  770. /*++
  771. Routine Description:
  772. Delete matching record from record list.
  773. Arguments:
  774. ppRRList -- addr of record list ptr
  775. note that in case FIRST record in list is deleted, ppRRList
  776. is set with ptr to new first record in the list (possibly NULL)
  777. pRRDelete -- record to delete
  778. Return Value:
  779. TRUE if record found in list and deleted.
  780. FALSE if no match.
  781. --*/
  782. {
  783. PDNS_RECORD prr;
  784. PDNS_RECORD pprev;
  785. DNSDBG( TRACE, (
  786. "Dns_DeleteRecordFromList( %p, %p )\n",
  787. ppRRList,
  788. pRRDelete ));
  789. //
  790. // loop through list
  791. //
  792. // note, startup works as pNext is first field in DNS_RECORD
  793. // so access to pNext is simply dereference of the record ptr
  794. // -- same operation as deref of list address to get first record;
  795. // this allows us to have pprev pointer starting at ppRRList, and
  796. // eliminates special code for handling delete of first record
  797. //
  798. prr = (PDNS_RECORD) ppRRList;
  799. while ( pprev = prr,
  800. prr = prr->pNext )
  801. {
  802. if ( Dns_RecordCompare(
  803. prr,
  804. pRRDelete ) )
  805. {
  806. pprev->pNext = prr->pNext;
  807. Dns_RecordFree( prr );
  808. return TRUE;
  809. }
  810. }
  811. return FALSE;
  812. }