/*
* Copyright 2004-2006 Luke Quinane and Daniel Frampton
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace NDns.Message{
/// <summary>
/// A DNS message used in DNS communications.
/// </summary>
public class DNSMessage
{
#region Attributes
/// <summary>
/// The header for this DNS message.
/// </summary>
protected Header header;
/// <summary>
/// The question sections associated with this DNS message.
/// </summary>
protected QuestionSection[] questionEntries = {};
/// <summary>
/// The answer sections associated with the DNS message.
/// </summary>
protected AnswerSection[] answerEntries = {};
#endregion
#region Constructors
/// <summary>
/// Creates a new DNS message.
/// </summary>
public DNSMessage()
{
this.header = new Header();
this.header.additionalEntries = 0;
this.header.answerEntries = 0;
this.header.nameServerEntries = 0;
this.header.questionEntries = 0;
}
/// <summary>
/// Creates a new DNS message using the given data. This data is typically the
/// response from a DNS server.
/// </summary>
/// <param name="data">The data to create the message from.</param>
public DNSMessage(byte[] data)
{
DomainCoder coder = new DomainCoder();
ushort position;
this.header = new Header(data, 0, out position);
// read the question sections
this.questionEntries = (QuestionSection[]) Array.CreateInstance(typeof(QuestionSection), this.header.questionEntries);
for (int i = 0; i < this.header.questionEntries; i++)
{
ushort length;
QuestionSection qs = new QuestionSection(data, position, out length, coder);
position += length;
this.questionEntries[i] = qs;
}
// read the answer sections
this.answerEntries = (AnswerSection[]) Array.CreateInstance(typeof(AnswerSection), this.header.answerEntries);
for (int i = 0; i < this.header.answerEntries; i++)
{
ushort length;
AnswerSection ans = new AnswerSection(data, position, out length, coder);
position += length;
this.answerEntries[i] = ans;
}
// TODO: authority and additional sections
}
#endregion
#region Properties
/// <summary>
/// Gets and sets the question section entries for this DNS message.
/// </summary>
public QuestionSection[] QuestionEntries
{
get
{
return this.questionEntries;
}
set
{
this.questionEntries = value;
this.header.questionEntries = (ushort) value.Length;
}
}
/// <summary>
/// Gets and sets the answer section entries for this DNS message.
/// </summary>
public AnswerSection[] AnswerEntries
{
get
{
return this.answerEntries;
}
set
{
this.answerEntries = value;
this.header.answerEntries = (ushort) value.Length;
}
}
/// <summary>
/// Gets the Id for this DNS message.
/// </summary>
public ushort Id
{
get
{
return this.header.Id;
}
}
/// <summary>
/// Was this message a response or a query?
/// </summary>
public bool Response
{
get
{
return this.header.response;
}
set
{
this.header.response = value;
}
}
/// <summary>
/// Is the answer authoritative?
/// </summary>
public bool Authoritative
{
get
{
return this.header.authoritative;
}
set
{
this.header.authoritative = value;
}
}
/// <summary>
/// Was the message truncated due to size constraints?
/// </summary>
public bool Truncated
{
get
{
return this.header.truncated;
}
set
{
this.header.truncated = value;
}
}
/// <summary>
/// Is recursion desired?
/// </summary>
public bool Recursive
{
get
{
return this.header.recursionDesired;
}
set
{
this.header.recursionDesired = value;
}
}
/// <summary>
/// Is recursion available?
/// </summary>
public bool RecursionAvailable
{
get
{
return this.header.recursionAvailable;
}
set
{
this.header.recursionAvailable = value;
}
}
/// <summary>
/// A four bit field that specifies query type in the message.
/// </summary>
public OpCode Opcode
{
get
{
return this.header.opcode;
}
set
{
this.header.opcode = value;
}
}
/// <summary>
/// The response code for this message.
/// </summary>
public ResponseCode Rcode
{
get
{
return this.header.rcode;
}
set
{
this.header.rcode = value;
}
}
#endregion
#region ToByteArray
/// <summary>
/// Converts the DNS message into a byte array.
/// </summary>
/// <returns>The DNS message as a byte array.</returns>
public byte[] ToByteArray()
{
DomainCoder coder = new DomainCoder();
byte[] message = new byte[512];
ushort position = 0;
// add the DNS header
byte[] header = this.header.ToByteArray();
header.CopyTo(message, 0);
position += (ushort) header.Length;
// add the DNS question sections
foreach (QuestionSection qs in this.questionEntries)
{
byte[] qsData = qs.ToByteArray(coder, position);
qsData.CopyTo(message, position);
position += (ushort) qsData.Length;
}
return message;
}
#endregion
}
}
|