CacheRecordInfo.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. Technitium DNS Server
  3. Copyright (C) 2023 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.ResourceRecords;
  20. namespace DnsServerCore.Dns.ResourceRecords
  21. {
  22. class CacheRecordInfo
  23. {
  24. #region variables
  25. public static readonly CacheRecordInfo Default = new CacheRecordInfo();
  26. IReadOnlyList<DnsResourceRecord> _glueRecords;
  27. IReadOnlyList<DnsResourceRecord> _rrsigRecords;
  28. IReadOnlyList<DnsResourceRecord> _nsecRecords;
  29. NetworkAddress _eDnsClientSubnet;
  30. bool _conditionalForwardingClientSubnet; //not serialized
  31. DateTime _lastUsedOn; //not serialized
  32. #endregion
  33. #region constructor
  34. public CacheRecordInfo()
  35. { }
  36. public CacheRecordInfo(BinaryReader bR)
  37. {
  38. byte version = bR.ReadByte();
  39. switch (version)
  40. {
  41. case 1:
  42. _glueRecords = ReadRecordsFrom(bR, true);
  43. _rrsigRecords = ReadRecordsFrom(bR, false);
  44. _nsecRecords = ReadRecordsFrom(bR, true);
  45. if (bR.ReadBoolean())
  46. _eDnsClientSubnet = NetworkAddress.ReadFrom(bR);
  47. break;
  48. default:
  49. throw new InvalidDataException("CacheRecordInfo format version not supported.");
  50. }
  51. }
  52. #endregion
  53. #region private
  54. private static IReadOnlyList<DnsResourceRecord> ReadRecordsFrom(BinaryReader bR, bool includeInnerRRSigRecords)
  55. {
  56. int count = bR.ReadByte();
  57. if (count == 0)
  58. return null;
  59. DnsResourceRecord[] records = new DnsResourceRecord[count];
  60. for (int i = 0; i < count; i++)
  61. {
  62. records[i] = DnsResourceRecord.ReadCacheRecordFrom(bR, delegate (DnsResourceRecord record)
  63. {
  64. if (includeInnerRRSigRecords)
  65. {
  66. IReadOnlyList<DnsResourceRecord> rrsigRecords = ReadRecordsFrom(bR, false);
  67. if (rrsigRecords is not null)
  68. record.GetCacheRecordInfo()._rrsigRecords = rrsigRecords;
  69. }
  70. });
  71. }
  72. return records;
  73. }
  74. private static void WriteRecordsTo(IReadOnlyList<DnsResourceRecord> records, BinaryWriter bW, bool includeInnerRRSigRecords)
  75. {
  76. if (records is null)
  77. {
  78. bW.Write((byte)0);
  79. }
  80. else
  81. {
  82. bW.Write(Convert.ToByte(records.Count));
  83. foreach (DnsResourceRecord record in records)
  84. {
  85. record.WriteCacheRecordTo(bW, delegate ()
  86. {
  87. if (includeInnerRRSigRecords)
  88. {
  89. if (record.Tag is CacheRecordInfo cacheRecordInfo)
  90. WriteRecordsTo(cacheRecordInfo._rrsigRecords, bW, false);
  91. else
  92. bW.Write((byte)0);
  93. }
  94. });
  95. }
  96. }
  97. }
  98. #endregion
  99. #region public
  100. public void WriteTo(BinaryWriter bW)
  101. {
  102. bW.Write((byte)1); //version
  103. WriteRecordsTo(_glueRecords, bW, true);
  104. WriteRecordsTo(_rrsigRecords, bW, false);
  105. WriteRecordsTo(_nsecRecords, bW, true);
  106. if (_eDnsClientSubnet is null)
  107. {
  108. bW.Write(false);
  109. }
  110. else
  111. {
  112. bW.Write(true);
  113. _eDnsClientSubnet.WriteTo(bW);
  114. }
  115. }
  116. #endregion
  117. #region properties
  118. public IReadOnlyList<DnsResourceRecord> GlueRecords
  119. {
  120. get { return _glueRecords; }
  121. set
  122. {
  123. if ((value is null) || (value.Count == 0))
  124. _glueRecords = null;
  125. else
  126. _glueRecords = value;
  127. }
  128. }
  129. public IReadOnlyList<DnsResourceRecord> RRSIGRecords
  130. {
  131. get { return _rrsigRecords; }
  132. set
  133. {
  134. if ((value is null) || (value.Count == 0))
  135. _rrsigRecords = null;
  136. else
  137. _rrsigRecords = value;
  138. }
  139. }
  140. public IReadOnlyList<DnsResourceRecord> NSECRecords
  141. {
  142. get { return _nsecRecords; }
  143. set
  144. {
  145. if ((value is null) || (value.Count == 0))
  146. _nsecRecords = null;
  147. else
  148. _nsecRecords = value;
  149. }
  150. }
  151. public NetworkAddress EDnsClientSubnet
  152. {
  153. get { return _eDnsClientSubnet; }
  154. set { _eDnsClientSubnet = value; }
  155. }
  156. public bool ConditionalForwardingClientSubnet
  157. {
  158. get { return _conditionalForwardingClientSubnet; }
  159. set { _conditionalForwardingClientSubnet = value; }
  160. }
  161. public DateTime LastUsedOn
  162. {
  163. get { return _lastUsedOn; }
  164. set { _lastUsedOn = value; }
  165. }
  166. #endregion
  167. }
  168. }