/// <summary> /// Constructs a NS record by reading bytes from a return message /// </summary> /// <param name="pointer">A logical pointer to the bytes holding the record</param> internal SRVRecord(Pointer pointer) { m_Priority = pointer.ReadShort(); m_Weight = pointer.ReadShort(); m_Port = pointer.ReadShort(); m_Target = pointer.ReadDomain(); }
/// <summary> /// Construct the question reading from a DNS Server response. Consult RFC1035 4.1.2 /// for byte-wise details of this structure in byte array form /// </summary> /// <param name="pointer">a logical pointer to the Question in byte array form</param> internal Question(Pointer pointer) { // extract from the message _domain = pointer.ReadDomain(); _dnsType = (DnsType)pointer.ReadShort(); _dnsClass = (DnsClass)pointer.ReadShort(); }
/// <summary> /// Construct a resource record from a pointer to a byte array /// </summary> /// <param name="pointer">the position in the byte array of the record</param> internal ResourceRecord(Pointer pointer) { // extract the domain, question type, question class and Ttl _domain = pointer.ReadDomain(); _dnsType = (DnsType)pointer.ReadShort(); _dnsClass = (DnsClass)pointer.ReadShort(); _Ttl = pointer.ReadInt(); // the next short is the record length, we only use it for unrecognised record types int recordLength = pointer.ReadShort(); // and create the appropriate RDATA record based on the dnsType switch (_dnsType) { case DnsType.SRV: _record = new SRVRecord(pointer); break; default: { // move the pointer over this unrecognised record pointer.Position += recordLength; break; } } }
/// <summary> /// Construct a resource record from a pointer to a byte array /// </summary> /// <param name="pointer">the position in the byte array of the record</param> internal ResourceRecord(Pointer pointer) { // extract the domain, question type, question class and Ttl _domain = pointer.ReadDomain(); _dnsType = (DnsType) pointer.ReadShort(); _dnsClass = (DnsClass) pointer.ReadShort(); _Ttl = pointer.ReadInt(); // the next short is the record length, we only use it for unrecognised record types int recordLength = pointer.ReadShort(); // and create the appropriate RDATA record based on the dnsType switch (_dnsType) { case DnsType.SRV: _record = new SRVRecord(pointer); break; default: { // move the pointer over this unrecognised record pointer.Position += recordLength; break; } } }
/// <summary> /// Reads a domain name from the byte array. The method by which this works is described /// in RFC1035 - 4.1.4. Essentially to minimise the size of the message, if part of a domain /// name already been seen in the message, rather than repeating it, a pointer to the existing /// definition is used. Each word in a domain name is a label, and is preceded by its length /// /// eg. bigdevelopments.co.uk /// /// is [15] (size of bigdevelopments) + "bigdevelopments" /// [2] "co" /// [2] "uk" /// [1] 0 (NULL) /// </summary> /// <returns>the byte at the pointer</returns> public string ReadDomain() { StringBuilder domain = new StringBuilder(); int length = 0; // get the length of the first label while ((length = ReadByte()) != 0) { // top 2 bits set denotes domain name compression and to reference elsewhere if ((length & 0xc0) == 0xc0) { // work out the existing domain name, copy this pointer Pointer newPointer = Copy(); // and move it to where specified here newPointer.SetPosition((length & 0x3f) << 8 | ReadByte()); // repeat call recursively domain.Append(newPointer.ReadDomain()); return(domain.ToString()); } // if not using compression, copy a char at a time to the domain name while (length > 0) { domain.Append(ReadChar()); length--; } // if size of next label isn't null (end of domain name) add a period ready for next label if (Peek() != 0) { domain.Append('.'); } } // and return return(domain.ToString()); }