private byte[] BuildDnsRequest(string host, NsType queryType, NsClass queryClass, ProtocolType protocol)
{
// Combind the NsFlags with our constant flags
ushort flags = (ushort)((ushort)_queryResponse | (ushort)_opCode | (ushort)_nsFlags);
this._flags = flags;
this._nsType = queryType;
this._nsClass = queryClass;
byte[] flagBytes = new byte[2];
byte[] transactionId = new byte[2];
byte[] questions = new byte[2];
byte[] answerRRs = new byte[2];
byte[] authorityRRs = new byte[2];
byte[] additionalRRs = new byte[2];
byte[] nsType = new byte[2];
byte[] nsClass = new byte[2];
// Prepare data for over the wire transfer
transactionId = BitConverter.GetBytes((ushort)(IPAddress.HostToNetworkOrder(_transactionId) >> 16));
flagBytes = BitConverter.GetBytes((ushort)(IPAddress.HostToNetworkOrder(_flags) >> 16));
questions = BitConverter.GetBytes((ushort)(IPAddress.HostToNetworkOrder(_questions) >> 16));
answerRRs = BitConverter.GetBytes((ushort)(IPAddress.HostToNetworkOrder(_answerRRs) >> 16));
authorityRRs = BitConverter.GetBytes((ushort)(IPAddress.HostToNetworkOrder(_authorityRRs) >> 16));
additionalRRs = BitConverter.GetBytes((ushort)(IPAddress.HostToNetworkOrder(_additionalRRs) >> 16));
nsType = BitConverter.GetBytes((ushort)(IPAddress.HostToNetworkOrder((ushort)_nsType) >> 16));
nsClass = BitConverter.GetBytes((ushort)(IPAddress.HostToNetworkOrder((ushort)_nsClass) >> 16));
byte[] name = this.BuildQuery(host);
// Build UPD DNS Packet to query
MemoryStream ms = new MemoryStream();
ms.Write(transactionId, 0, transactionId.Length);
ms.Write(flagBytes, 0, flagBytes.Length);
ms.Write(questions, 0, questions.Length);
ms.Write(answerRRs, 0, answerRRs.Length);
ms.Write(authorityRRs, 0, authorityRRs.Length);
ms.Write(additionalRRs, 0, additionalRRs.Length);
ms.Write(name, 0, name.Length);
ms.Write(nsType, 0, nsType.Length);
ms.Write(nsClass, 0, nsClass.Length);
byte[] bDnsQuery = ms.ToArray();
// Add two byte prefix that contains the packet length per RFC 1035 section 4.2.2
if (protocol == ProtocolType.Tcp)
{
// 4.2.2. TCP usageMessages sent over TCP connections use server port 53 (decimal).
// The message is prefixed with a two byte length field which gives the message
// length, excluding the two byte length field. This length field allows the
// low-level processing to assemble a complete message before beginning to parse
// it.
int len = bDnsQuery.Length;
Array.Resize<byte>(ref bDnsQuery, len + 2);
Array.Copy(bDnsQuery, 0, bDnsQuery, 2, len);
bDnsQuery[0] = (byte)((len >> 8) & 0xFF);
bDnsQuery[1] = (byte)((len & 0xFF));
}
return bDnsQuery;
}
}