static IReadOnlyList <DnsResourceRecord>?ParseSection(ref DnsParseContext context, int count) { if (count == 0) { return(null); } var result = new DnsResourceRecord[count]; foreach (ref var record in result.AsSpan()) { string name = context.ReadDomainName(); DnsRecordType qtype = (DnsRecordType)context.ReadUInt16(); DnsEndpointClass qclass = (DnsEndpointClass)context.ReadUInt16(); int ttl = context.ReadInt32(); ushort rdlength = context.ReadUInt16(); record = qtype switch { DnsRecordType.A or DnsRecordType.AAAA => new IPRecord(), DnsRecordType.TXT => new TxtRecord(), DnsRecordType.CNAME => new DomainNameRecord(), DnsRecordType.MX => new MXRecord(), DnsRecordType.SOA => new SoaRecord(), _ => new UnknownRecord() }; record.Name = name; record.Type = qtype; record.EndpointClass = qclass; record.AliveSeconds = ttl; record.ReadData(ref context, rdlength); } return(result); } var queries = queryCount == 0 ? Array.Empty <DnsQuery>() : new DnsQuery[queryCount]; foreach (ref var query in queries.AsSpan()) { string name = context.ReadDomainName(); DnsRecordType qtype = (DnsRecordType)context.ReadUInt16(); DnsEndpointClass qclass = (DnsEndpointClass)context.ReadUInt16(); query = new(name, qtype, qclass); } message.Queries = queries; message.Answers = ParseSection(ref context, answerCount); message.NameServerAuthorities = ParseSection(ref context, serverCount); message.AdditionalRecords = ParseSection(ref context, additionalCount); bytesConsumed = context.BytesConsumed; return(message); }
public static DnsMessage ParseMessage(ReadOnlySpan <byte> span, out int bytesConsumed) { var context = new DnsParseContext(span); var message = new DnsMessage { QueryId = context.ReadUInt16(), }; ushort flags = context.ReadUInt16(); int queryCount = context.ReadUInt16(); int answerCount = context.ReadUInt16(); int serverCount = context.ReadUInt16(); int additionalCount = context.ReadUInt16(); message.IsResponse = (flags & ResponseFlag) != 0; message.Operation = (DnsOperation)((flags & OpCodeMask) >> OpCodeShift); message.IsAuthoritativeAnswer = (flags & AuthoritativeMask) != 0; message.IsTruncated = (flags & TruncationMask) != 0; message.IsRecursionDesired = (flags & RecursionDesiredMask) != 0; message.IsRecursionAvailable = (flags & RecursionAvailableMask) != 0; message.ResponseCode = (DnsResponseCode)(flags & ResponseCodeMask);