/// <summary> /// Constructs an SOA record by reading bytes from a return message /// </summary> /// <param name="pointer">A logical pointer to the bytes holding the record</param> internal SOARecord(Pointer pointer) { // read all fields RFC1035 3.3.13 _PrimaryNameServer = pointer.ReadDomain(); _ResponsibleMailAddress = pointer.ReadDomain(); _Serial = pointer.ReadInt(); _Refresh = pointer.ReadInt(); _Retry = pointer.ReadInt(); _Expire = pointer.ReadInt(); _DefaultTTL = pointer.ReadInt(); }
/// <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> /// 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()); }
/// <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.NS: _Record = new NSRecord(pointer); break; case DnsType.MX: _Record = new MXRecord(pointer); break; case DnsType.ANAME: _Record = new ANameRecord(pointer); break; case DnsType.SOA: _Record = new SOARecord(pointer); break; default: // move the pointer over this unrecognised record pointer += recordLength; break; } }
/// <summary> /// Constructs an MX record by reading bytes from a return message /// </summary> /// <param name="pointer">A logical pointer to the bytes holding the record</param> internal MXRecord(Pointer pointer) { _Preference = pointer.ReadShort(); _DomainName = pointer.ReadDomain(); }
/// <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 NSRecord(Pointer pointer) { _DomainName = pointer.ReadDomain(); }