using DnsClient.Protocol; using System.Linq; namespace DnsClient { /// /// The header section of a . /// public class DnsResponseHeader { private readonly ushort _flags = 0; /// /// Gets the number of additional records in the . /// /// /// The number of additional records. /// public int AdditionalCount { get; } /// /// Gets the number of answer records in the . /// /// /// The number of answer records. /// public int AnswerCount { get; } /// /// Gets a value indicating whether the future use flag is set. /// /// /// The future use flag. /// public bool FutureUse => HasFlag(DnsHeaderFlag.FutureUse); /// /// Gets a value indicating whether this instance has authority answers. /// /// /// true if this instance has authority answers; otherwise, false. /// public bool HasAuthorityAnswer => HasFlag(DnsHeaderFlag.HasAuthorityAnswer); internal DnsHeaderFlag HeaderFlags => (DnsHeaderFlag)_flags; /// /// Gets the identifier. /// /// /// The identifier. /// public int Id { get; } /// /// Gets a value indicating whether the result is authentic data. /// /// /// true if the result is authentic; otherwise, false. /// public bool IsAuthenticData => HasFlag(DnsHeaderFlag.IsAuthenticData); /// /// Gets a value indicating whether checking is disabled. /// /// /// true if checking is disabled; otherwise, false. /// public bool IsCheckingDisabled => HasFlag(DnsHeaderFlag.IsCheckingDisabled); /// /// Gets a value indicating whether this instance has a query. /// /// /// true if this instance has a query; otherwise, false. /// public bool HasQuery => HasFlag(DnsHeaderFlag.HasQuery); /// /// Gets the number of name servers. /// /// /// The number of name servers. /// public int NameServerCount { get; } /// /// Gets the kind of query defined by . /// /// /// The query kind. /// public DnsOpCode OPCode => (DnsOpCode)((DnsHeader.OPCodeMask & _flags) >> DnsHeader.OPCodeShift); /// /// Gets the number of questions of the . /// /// /// The number of questions. /// public int QuestionCount { get; } /// /// Gets a value indicating whether recursion is available on the DNS server. /// /// /// true if recursion is available; otherwise, false. /// public bool RecursionAvailable => HasFlag(DnsHeaderFlag.RecursionAvailable); /// /// Gets the response code. /// /// /// The response code. /// public DnsResponseCode ResponseCode => (DnsResponseCode)(_flags & DnsHeader.RCodeMask); /// /// Gets a value indicating whether the result was truncated. /// /// /// true if the result was truncated; otherwise, false. /// public bool ResultTruncated => HasFlag(DnsHeaderFlag.ResultTruncated); /// /// Gets a value indicating whether recursion desired flag was set by the request. /// /// /// true if the recursion desired flag was set; otherwise, false. /// public bool RecursionDesired => HasFlag(DnsHeaderFlag.RecursionDesired); /// /// Initializes a new instance of the class. /// /// The identifier. /// The flags. /// The question count. /// The answer count. /// The additional count. /// The server count. public DnsResponseHeader(int id, ushort flags, int questionCount, int answerCount, int additionalCount, int serverCount) { Id = id; _flags = flags; QuestionCount = questionCount; AnswerCount = answerCount; AdditionalCount = additionalCount; NameServerCount = serverCount; } private bool HasFlag(DnsHeaderFlag flag) => (HeaderFlags & flag) != 0; /// /// Returns a that represents this instance. /// /// /// A that represents this instance. /// public override string ToString() { var head = $";; ->>HEADER<<- opcode: {OPCode}, status: {DnsResponseCodeText.GetErrorText(ResponseCode)}, id: {Id}"; var flags = new string[] { HasQuery ? "qr" : "", HasAuthorityAnswer ? "aa" : "", RecursionDesired ? "rd" : "", RecursionAvailable ? "ra" : "", ResultTruncated ? "tc" : "", IsCheckingDisabled ? "cd" : "", IsAuthenticData ? "ad" : "" }; var flagsString = string.Join(" ", flags.Where(p => p != "")); return $"{head}\r\n;; flags: {flagsString}; QUERY: {QuestionCount}, " + $"ANSWER: {AnswerCount}, AUTORITY: {NameServerCount}, ADDITIONAL: {AdditionalCount}"; } } }