public DnsResponseMessage GetResponseMessage(ArraySegment <byte> responseData) { var reader = new DnsDatagramReader(responseData); var id = reader.ReadUInt16NetworkOrder(); var flags = reader.ReadUInt16NetworkOrder(); var questionCount = reader.ReadUInt16NetworkOrder(); var answerCount = reader.ReadUInt16NetworkOrder(); var nameServerCount = reader.ReadUInt16NetworkOrder(); var additionalCount = reader.ReadUInt16NetworkOrder(); var header = new DnsResponseHeader(id, flags, questionCount, answerCount, additionalCount, nameServerCount); var response = new DnsResponseMessage(header, responseData.Count); for (var questionIndex = 0; questionIndex < questionCount; questionIndex++) { var questionQueryString = reader.ReadQuestionQueryString(); var queryTypeValue = reader.ReadUInt16NetworkOrder(); var queryClass = reader.ReadUInt16NetworkOrder(); if (!_queryTypes.TryGetValue(queryTypeValue, out var queryType)) { queryType = new PseudoResourceRecordType( abbreviation: "Unknown", value: queryTypeValue ); } var question = new DnsQuestion(questionQueryString, queryType, (QueryClass)queryClass); response.AddQuestion(question); } for (var answerIndex = 0; answerIndex < answerCount; answerIndex++) { var info = ReadRecordInfo(reader); var record = _dnsRecordFactory.GetRecord(info, reader); response.AddAnswer(record); } for (var serverIndex = 0; serverIndex < nameServerCount; serverIndex++) { var info = ReadRecordInfo(reader); var record = _dnsRecordFactory.GetRecord(info, reader); response.AddAuthority(record); } for (var additionalIndex = 0; additionalIndex < additionalCount; additionalIndex++) { var info = ReadRecordInfo(reader); var record = _dnsRecordFactory.GetRecord(info, reader); response.AddAdditional(record); } return(response); }
public ICollection <ArraySegment <byte> > ReadLabels() { var result = new List <ArraySegment <byte> >(10); // read the length byte for the label, then get the content from offset+1 to length // proceed till we reach zero length byte. byte length; while ((length = ReadByte()) != 0) { // respect the reference bit and lookup the name at the given position // the reader will advance only for the 2 bytes read. if ((length & ReferenceByte) != 0) { int subIndex = (length & 0x3f) << 8 | ReadByte(); if (subIndex >= _data.Array.Length - 1) { // invalid length pointer, seems to be actual length of a label which exceeds 63 chars... // get back one and continue other labels _index--; result.Add(_data.SubArray(_index, length)); Advance(length); continue; } var subReader = new DnsDatagramReader(_data.SubArrayFromOriginal(subIndex)); var newLabels = subReader.ReadLabels(); result.AddRange(newLabels); // add range actually much faster than concat and equal to or faster than for-each.. (array copy would work maybe) return(result); } if (_index + length >= _count) { throw new DnsResponseParseException( "Found invalid label position.", _data.ToArray(), _index, length); } var label = _data.SubArray(_index, length); // maybe store original bytes in this instance too? result.Add(label); Advance(length); } return(result); }
public virtual DnsResponseMessage GetResponseMessage(ArraySegment <byte> responseData) { var reader = new DnsDatagramReader(responseData); var factory = new DnsRecordFactory(reader); var id = reader.ReadUInt16NetworkOrder(); var flags = reader.ReadUInt16NetworkOrder(); var questionCount = reader.ReadUInt16NetworkOrder(); var answerCount = reader.ReadUInt16NetworkOrder(); var nameServerCount = reader.ReadUInt16NetworkOrder(); var additionalCount = reader.ReadUInt16NetworkOrder(); var header = new DnsResponseHeader(id, flags, questionCount, answerCount, additionalCount, nameServerCount); var response = new DnsResponseMessage(header, responseData.Count); for (int questionIndex = 0; questionIndex < questionCount; questionIndex++) { var question = new DnsQuestion(reader.ReadQuestionQueryString(), (QueryType)reader.ReadUInt16NetworkOrder(), (QueryClass)reader.ReadUInt16NetworkOrder()); response.AddQuestion(question); } for (int answerIndex = 0; answerIndex < answerCount; answerIndex++) { var info = factory.ReadRecordInfo(); var record = factory.GetRecord(info); response.AddAnswer(record); } for (int serverIndex = 0; serverIndex < nameServerCount; serverIndex++) { var info = factory.ReadRecordInfo(); var record = factory.GetRecord(info); response.AddAuthority(record); } for (int additionalIndex = 0; additionalIndex < additionalCount; additionalIndex++) { var info = factory.ReadRecordInfo(); var record = factory.GetRecord(info); response.AddAdditional(record); } return(response); }
private DnsResourceRecord ResolveTXTRecord(ResourceRecordInfo info) { int pos = _reader.Index; var values = new List <string>(); var utf8Values = new List <string>(); while ((_reader.Index - pos) < info.RawDataLength) { var length = _reader.ReadByte(); var bytes = _reader.ReadBytes(length); var escaped = DnsDatagramReader.ParseString(bytes); var utf = DnsDatagramReader.ReadUTF8String(bytes); values.Add(escaped); utf8Values.Add(utf); } return(new TxtRecord(info, values.ToArray(), utf8Values.ToArray())); }
public static string ParseString(DnsDatagramReader reader, int length) { if (reader._count < reader._index + length) { throw new DnsResponseParseException("Cannot parse string.", reader._data.ToArray(), reader._index, length); } var builder = StringBuilderObjectPool.Default.Get(); for (var i = 0; i < length; i++) { byte b = reader.ReadByte(); char c = (char)b; if (b < 32 || b > 126) { builder.Append("\\" + b.ToString("000")); } else if (c == ';') { builder.Append("\\;"); } else if (c == '\\') { builder.Append("\\\\"); } else if (c == '"') { builder.Append("\\\""); } else { builder.Append(c); } } var value = builder.ToString(); StringBuilderObjectPool.Default.Return(builder); return(value); }
/// <summary> /// Reads a <see cref="ResourceRecord"/> from this <see cref="DnsDatagramReader"/>. /// </summary> private ResourceRecord ReadRecordInfo(DnsDatagramReader reader) { var queryString = reader.ReadQuestionQueryString(); var type = reader.ReadUInt16NetworkOrder(); if (!_resourceRecordTypes.TryGetValue(type, out var resourceRecordType)) { resourceRecordType = new PseudoResourceRecordType( abbreviation: "Unknown - machine generated", value: type ); } var queryClass = reader.ReadUInt16NetworkOrder(); var ttl = reader.ReadUInt32NetworkOrder(); var rdLength = reader.ReadUInt16NetworkOrder(); return(new ResourceRecord( queryString, // name resourceRecordType, // type (QueryClass)queryClass, // class (int)ttl, // ttl - 32bit!! rdLength)); // RDLength }
public static string ParseString(DnsDatagramReader reader, int length) { var builder = StringBuilderObjectPool.Default.Get(); for (var i = 0; i < length; i++) { byte b = reader.ReadByte(); char c = (char)b; if (b < 32 || b > 126) { builder.Append("\\" + b.ToString("000")); } else if (c == ';') { builder.Append("\\;"); } else if (c == '\\') { builder.Append("\\\\"); } else if (c == '"') { builder.Append("\\\""); } else { builder.Append(c); } } var value = builder.ToString(); StringBuilderObjectPool.Default.Return(builder); return(value); }
public DnsRecordFactory(DnsDatagramReader reader) { _reader = reader ?? throw new ArgumentNullException(nameof(reader)); }