Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

403 lines
6.5 KiB

  1. /*++
  2. Copyright (c) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. rrlist.c
  5. Abstract:
  6. Domain Name System (DNS) Library
  7. Record list manipulation.
  8. Author:
  9. Jim Gilroy (jamesg) January, 1997
  10. Environment:
  11. User Mode - Win32
  12. Revision History:
  13. --*/
  14. #include "local.h"
  15. PDNS_RECORD
  16. Dns_RecordSetDetach(
  17. IN OUT PDNS_RECORD pRR
  18. )
  19. /*++
  20. Routine Description:
  21. Detach first RR set from the rest of the list.
  22. Arguments:
  23. pRR - incoming record set
  24. Return Value:
  25. Ptr to first record of next RR set.
  26. NULL if at end of list.
  27. --*/
  28. {
  29. PDNS_RECORD prr = pRR;
  30. PDNS_RECORD pback; // previous RR in set
  31. WORD type; // first RR set type
  32. DWORD section; // section of first RR set
  33. if ( !prr )
  34. {
  35. return( NULL );
  36. }
  37. //
  38. // loop until find start of new RR set
  39. // - new type or
  40. // - new section or
  41. // - new name
  42. // note that NULL name is automatically considered
  43. // previous name
  44. //
  45. type = prr->wType;
  46. section = prr->Flags.S.Section;
  47. pback = prr;
  48. while ( prr = pback->pNext )
  49. {
  50. if ( prr->wType == type &&
  51. prr->Flags.S.Section == section &&
  52. ( prr->pName == NULL ||
  53. Dns_NameComparePrivate(
  54. prr->pName,
  55. pback->pName,
  56. pback->Flags.S.CharSet ) ) )
  57. {
  58. pback = prr;
  59. continue;
  60. }
  61. // should not be detaching nameless record
  62. // - fixup for robustness
  63. if ( !prr->pName )
  64. {
  65. ASSERT( prr->pName );
  66. prr->pName = Dns_NameCopyAllocate(
  67. pRR->pName,
  68. 0, // length unknown
  69. pRR->Flags.S.CharSet,
  70. prr->Flags.S.CharSet );
  71. SET_FREE_OWNER( prr );
  72. }
  73. break;
  74. }
  75. // have following RR set, NULL terminate first set
  76. if ( prr )
  77. {
  78. pback->pNext = NULL;
  79. }
  80. return( prr );
  81. }
  82. PDNS_RECORD
  83. WINAPI
  84. Dns_RecordListAppend(
  85. IN OUT PDNS_RECORD pHeadList,
  86. IN PDNS_RECORD pTailList
  87. )
  88. /*++
  89. Routine Description:
  90. Append record list onto another.
  91. Arguments:
  92. pHeadList -- record list to be head
  93. pTailList -- record list to append to pHeadList
  94. Return Value:
  95. Ptr to first record of combined RR set.
  96. - pHeadList UNLESS pHeadList is NULL,
  97. then it is pTailList.
  98. --*/
  99. {
  100. PDNS_RECORD prr = pHeadList;
  101. if ( !prr )
  102. {
  103. return pTailList;
  104. }
  105. // find end of first list and append second list
  106. while ( prr->pNext )
  107. {
  108. prr = prr->pNext;
  109. }
  110. // should be appending new set (with new name)
  111. // or matching previous set
  112. DNS_ASSERT( !pTailList || pTailList->pName ||
  113. (pTailList->wType == prr->wType &&
  114. pTailList->Flags.S.Section == prr->Flags.S.Section) );
  115. prr->pNext = pTailList;
  116. return pHeadList;
  117. }
  118. DWORD
  119. Dns_RecordListCount(
  120. IN PDNS_RECORD pRRList,
  121. IN WORD wType
  122. )
  123. /*++
  124. Routine Description:
  125. Count records in list.
  126. Arguments:
  127. pRRList - incoming record set
  128. Return Value:
  129. Count of records of given type in list.
  130. --*/
  131. {
  132. DWORD count = 0;
  133. //
  134. // loop counting all records that match
  135. // - either direct match
  136. // - or if matching type is ALL
  137. //
  138. while ( pRRList )
  139. {
  140. if ( pRRList->wType == wType ||
  141. wType == DNS_TYPE_ALL )
  142. {
  143. count++;
  144. }
  145. pRRList = pRRList->pNext;
  146. }
  147. return( count );
  148. }
  149. DWORD
  150. Dns_RecordListGetMinimumTtl(
  151. IN PDNS_RECORD pRRList
  152. )
  153. /*++
  154. Routine Description:
  155. Get minimum TTL of record list
  156. Arguments:
  157. pRRList - incoming record set
  158. Return Value:
  159. Minimum TTL of records in list.
  160. --*/
  161. {
  162. PDNS_RECORD prr = pRRList;
  163. DWORD minTtl = MAXDWORD;
  164. DNSDBG( TRACE, (
  165. "Dns_RecordListGetMinimumTtl( %p )\n",
  166. pRRList ));
  167. //
  168. // loop through list build minimum TTL
  169. //
  170. while ( prr )
  171. {
  172. if ( prr->dwTtl < minTtl )
  173. {
  174. minTtl = prr->dwTtl;
  175. }
  176. prr = prr->pNext;
  177. }
  178. return minTtl;
  179. }
  180. //
  181. // Record screening
  182. //
  183. BOOL
  184. Dns_ScreenRecord(
  185. IN PDNS_RECORD pRR,
  186. IN DWORD ScreenFlag
  187. )
  188. /*++
  189. Routine Description:
  190. Screen a record.
  191. Arguments:
  192. pRR - incoming record
  193. ScreenFlag - screeing flag
  194. Return Value:
  195. TRUE if passes screening.
  196. FALSE if record fails screen.
  197. --*/
  198. {
  199. BOOL fsave = TRUE;
  200. DNSDBG( TRACE, (
  201. "Dns_ScreenRecord( %p, %08x )\n",
  202. pRR,
  203. ScreenFlag ));
  204. // section screening
  205. if ( ScreenFlag & SCREEN_OUT_SECTION )
  206. {
  207. if ( IS_ANSWER_RR(pRR) )
  208. {
  209. fsave = !(ScreenFlag & SCREEN_OUT_ANSWER);
  210. }
  211. else if ( IS_AUTHORITY_RR(pRR) )
  212. {
  213. fsave = !(ScreenFlag & SCREEN_OUT_AUTHORITY);
  214. }
  215. else if ( IS_ADDITIONAL_RR(pRR) )
  216. {
  217. fsave = !(ScreenFlag & SCREEN_OUT_ADDITIONAL);
  218. }
  219. if ( !fsave )
  220. {
  221. return FALSE;
  222. }
  223. }
  224. // type screening
  225. if ( ScreenFlag & SCREEN_OUT_NON_RPC )
  226. {
  227. fsave = Dns_IsRpcRecordType( pRR->wType );
  228. }
  229. return fsave;
  230. }
  231. PDNS_RECORD
  232. Dns_RecordListScreen(
  233. IN PDNS_RECORD pRR,
  234. IN DWORD ScreenFlag
  235. )
  236. /*++
  237. Routine Description:
  238. Screen records from record set.
  239. Arguments:
  240. pRR - incoming record set
  241. ScreenFlag - flag with record screening parameters
  242. Return Value:
  243. Ptr to new record set, if successful.
  244. NULL on error.
  245. --*/
  246. {
  247. PDNS_RECORD prr;
  248. PDNS_RECORD pnext;
  249. DNS_RRSET rrset;
  250. DNSDBG( TRACE, (
  251. "Dns_RecordListScreen( %p, %08x )\n",
  252. pRR,
  253. ScreenFlag ));
  254. // init copy rrset
  255. DNS_RRSET_INIT( rrset );
  256. //
  257. // loop through RR list
  258. //
  259. pnext = pRR;
  260. while ( pnext )
  261. {
  262. prr = pnext;
  263. pnext = prr->pNext;
  264. //
  265. // screen
  266. // - reappend record passing screen
  267. // - delete record failing screen
  268. //
  269. if ( Dns_ScreenRecord( prr, ScreenFlag ) )
  270. {
  271. prr->pNext = NULL;
  272. DNS_RRSET_ADD( rrset, prr );
  273. continue;
  274. }
  275. else
  276. {
  277. Dns_RecordFree( prr );
  278. }
  279. }
  280. return( rrset.pFirstRR );
  281. }
  282. //
  283. // End rrlist.c
  284. //