CacheRecordInfo.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /*
  2. Technitium DNS Server
  3. Copyright (C) 2024 Shreyas Zare (shreyas@technitium.com)
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. using System;
  16. using System.Collections.Generic;
  17. using System.IO;
  18. using TechnitiumLibrary.Net;
  19. using TechnitiumLibrary.Net.Dns;
  20. using TechnitiumLibrary.Net.Dns.ResourceRecords;
  21. namespace DnsServerCore.Dns.ResourceRecords
  22. {
  23. class CacheRecordInfo
  24. {
  25. #region variables
  26. public static readonly CacheRecordInfo Default = new CacheRecordInfo();
  27. IReadOnlyList<DnsResourceRecord> _glueRecords;
  28. IReadOnlyList<DnsResourceRecord> _rrsigRecords;
  29. IReadOnlyList<DnsResourceRecord> _nsecRecords;
  30. NetworkAddress _eDnsClientSubnet;
  31. DnsDatagramMetadata _responseMetadata;
  32. DateTime _lastUsedOn; //not serialized
  33. #endregion
  34. #region constructor
  35. public CacheRecordInfo()
  36. { }
  37. public CacheRecordInfo(BinaryReader bR)
  38. {
  39. byte version = bR.ReadByte();
  40. switch (version)
  41. {
  42. case 1:
  43. case 2:
  44. _glueRecords = ReadRecordsFrom(bR, true);
  45. _rrsigRecords = ReadRecordsFrom(bR, false);
  46. _nsecRecords = ReadRecordsFrom(bR, true);
  47. if (bR.ReadBoolean())
  48. _eDnsClientSubnet = NetworkAddress.ReadFrom(bR);
  49. if (version >= 2)
  50. {
  51. if (bR.ReadBoolean())
  52. _responseMetadata = new DnsDatagramMetadata(bR);
  53. }
  54. break;
  55. default:
  56. throw new InvalidDataException("CacheRecordInfo format version not supported.");
  57. }
  58. }
  59. #endregion
  60. #region private
  61. private static DnsResourceRecord[] ReadRecordsFrom(BinaryReader bR, bool includeInnerRRSigRecords)
  62. {
  63. int count = bR.ReadByte();
  64. if (count == 0)
  65. return null;
  66. DnsResourceRecord[] records = new DnsResourceRecord[count];
  67. for (int i = 0; i < count; i++)
  68. {
  69. records[i] = DnsResourceRecord.ReadCacheRecordFrom(bR, delegate (DnsResourceRecord record)
  70. {
  71. if (includeInnerRRSigRecords)
  72. {
  73. IReadOnlyList<DnsResourceRecord> rrsigRecords = ReadRecordsFrom(bR, false);
  74. if (rrsigRecords is not null)
  75. record.GetCacheRecordInfo()._rrsigRecords = rrsigRecords;
  76. }
  77. });
  78. }
  79. return records;
  80. }
  81. private static void WriteRecordsTo(IReadOnlyList<DnsResourceRecord> records, BinaryWriter bW, bool includeInnerRRSigRecords)
  82. {
  83. if (records is null)
  84. {
  85. bW.Write((byte)0);
  86. }
  87. else
  88. {
  89. bW.Write(Convert.ToByte(records.Count));
  90. foreach (DnsResourceRecord record in records)
  91. {
  92. record.WriteCacheRecordTo(bW, delegate ()
  93. {
  94. if (includeInnerRRSigRecords)
  95. {
  96. if (record.Tag is CacheRecordInfo cacheRecordInfo)
  97. WriteRecordsTo(cacheRecordInfo._rrsigRecords, bW, false);
  98. else
  99. bW.Write((byte)0);
  100. }
  101. });
  102. }
  103. }
  104. }
  105. #endregion
  106. #region public
  107. public void WriteTo(BinaryWriter bW)
  108. {
  109. bW.Write((byte)2); //version
  110. WriteRecordsTo(_glueRecords, bW, true);
  111. WriteRecordsTo(_rrsigRecords, bW, false);
  112. WriteRecordsTo(_nsecRecords, bW, true);
  113. if (_eDnsClientSubnet is null)
  114. {
  115. bW.Write(false);
  116. }
  117. else
  118. {
  119. bW.Write(true);
  120. _eDnsClientSubnet.WriteTo(bW);
  121. }
  122. if (_responseMetadata is null)
  123. {
  124. bW.Write(false);
  125. }
  126. else
  127. {
  128. bW.Write(true);
  129. _responseMetadata.WriteTo(bW);
  130. }
  131. }
  132. #endregion
  133. #region properties
  134. public IReadOnlyList<DnsResourceRecord> GlueRecords
  135. {
  136. get { return _glueRecords; }
  137. set
  138. {
  139. if ((value is null) || (value.Count == 0))
  140. _glueRecords = null;
  141. else
  142. _glueRecords = value;
  143. }
  144. }
  145. public IReadOnlyList<DnsResourceRecord> RRSIGRecords
  146. {
  147. get { return _rrsigRecords; }
  148. set
  149. {
  150. if ((value is null) || (value.Count == 0))
  151. _rrsigRecords = null;
  152. else
  153. _rrsigRecords = value;
  154. }
  155. }
  156. public IReadOnlyList<DnsResourceRecord> NSECRecords
  157. {
  158. get { return _nsecRecords; }
  159. set
  160. {
  161. if ((value is null) || (value.Count == 0))
  162. _nsecRecords = null;
  163. else
  164. _nsecRecords = value;
  165. }
  166. }
  167. public NetworkAddress EDnsClientSubnet
  168. {
  169. get { return _eDnsClientSubnet; }
  170. set { _eDnsClientSubnet = value; }
  171. }
  172. public DnsDatagramMetadata ResponseMetadata
  173. {
  174. get { return _responseMetadata; }
  175. set { _responseMetadata = value; }
  176. }
  177. public DateTime LastUsedOn
  178. {
  179. get { return _lastUsedOn; }
  180. set { _lastUsedOn = value; }
  181. }
  182. #endregion
  183. }
  184. }