/// <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.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 ANAME record by reading bytes from a return message /// </summary> /// <param name="pointer">A logical pointer to the bytes holding the record</param> internal ANameRecord(Pointer pointer) { byte b1 = pointer.ReadByte(); byte b2 = pointer.ReadByte(); byte b3 = pointer.ReadByte(); byte b4 = pointer.ReadByte(); // this next line's not brilliant - couldn't find a better way though _ipAddress = IPAddress.Parse(string.Format("{0}.{1}.{2}.{3}", b1, b2, b3, b4)); }
/// <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 a Response object from the supplied byte array /// </summary> /// <param name="message">a byte array returned from a DNS server query</param> internal Response(byte[] message) { // the bit flags are in bytes 2 and 3 byte flags1 = message[2]; byte flags2 = message[3]; // get return code from lowest 4 bits of byte 3 int returnCode = flags2 & 15; // if its in the reserved section, set to other if (returnCode > 6) returnCode = 6; _returnCode = (ReturnCode)returnCode; // other bit flags _authoritativeAnswer = ((flags1 & 4) != 0); _recursionAvailable = ((flags2 & 128) != 0); _truncated = ((flags1 & 2) != 0); // create the arrays of response objects _questions = new Question[GetShort(message, 4)]; _answers = new Answer[GetShort(message, 6)]; _nameServers = new NameServer[GetShort(message, 8)]; _additionalRecords = new AdditionalRecord[GetShort(message, 10)]; // need a pointer to do this, position just after the header Pointer pointer = new Pointer(message, 12); // and now populate them, they always follow this order for (int index = 0; index < _questions.Length; index++) { try { // try to build a quesion from the response _questions[index] = new Question(pointer); } catch (Exception ex) { Terminals.Logging.Error("DNS Response Question Failure", ex); // something grim has happened, we can't continue throw new InvalidResponseException(ex); } } for (int index = 0; index < _answers.Length; index++) { _answers[index] = new Answer(pointer); } for (int index = 0; index < _nameServers.Length; index++) { _nameServers[index] = new NameServer(pointer); } for (int index = 0; index < _additionalRecords.Length; index++) { _additionalRecords[index] = new AdditionalRecord(pointer); } }
/// <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(); }
/// <summary> /// Construct a Response object from the supplied byte array /// </summary> /// <param name="message">a byte array returned from a DNS server query</param> internal Response(byte[] message) { if (message == null) throw new ArgumentNullException("message"); // the bit flags are in bytes 2 and 3 byte flags1 = message[2]; byte flags2 = message[3]; // get return code from lowest 4 bits of byte 3 int returnCode = flags2 & 15; // if its in the reserved section, set to other if (returnCode > 6) returnCode = 6; _returnCode = (ReturnCode) returnCode; // other bit flags _authoritativeAnswer = ((flags1 & 4) != 0); _recursionAvailable = ((flags2 & 128) != 0); _messageTruncated = ((flags1 & 2) != 0); // create the arrays of response objects _questions = new Question[GetShort(message, 4)]; _answers = new Answer[GetShort(message, 6)]; _nameServers = new NameServer[GetShort(message, 8)]; _additionalRecords = new AdditionalRecord[GetShort(message, 10)]; // need a pointer to do this, position just after the header var pointer = new Pointer(message, 12); ReadQuestions(pointer); ReadAnswers(pointer); ReadNameServers(pointer); ReadAdditionalRecords(pointer); }
private void ReadAdditionalRecords(Pointer pointer) { for (int index = 0; index < _additionalRecords.Length; index++) { _additionalRecords[index] = new AdditionalRecord(pointer); } }
private void ReadNameServers(Pointer pointer) { for (int index = 0; index < _nameServers.Length; index++) { _nameServers[index] = new NameServer(pointer); } }
private void ReadAnswers(Pointer pointer) { for (int index = 0; index < _answers.Length; index++) { _answers[index] = new Answer(pointer); } }
internal NameServer(Pointer pointer) : base(pointer) { }
/// <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(); }
internal AdditionalRecord(Pointer pointer) : base(pointer) { }
internal Answer(Pointer pointer) : base(pointer) { }
private void ReadQuestions(Pointer pointer) { for (int index = 0; index < _questions.Length; index++) { try { // try to build a quesion from the response _questions[index] = new Question(pointer); } catch (Exception ex) { // something grim has happened, we can't continue throw new InvalidResponseException(ex); } } }