/* All communications inside of the domain protocol are carried in a single format called a message. The top level format of message is divided into 5 sections (some of which are empty in certain cases) shown below: +---------------------+ | Header | +---------------------+ | Question | the question for the name server +---------------------+ | Answer | RRs answering the question +---------------------+ | Authority | RRs pointing toward an authority +---------------------+ | Additional | RRs holding additional information +---------------------+ */ public static byte[] EncodeDnsMessage(DnsMessage message) { MemoryStream stream = new MemoryStream(512); BinaryWriter writer = new BinaryWriter(stream); byte[] header = EncodeHeader(message); writer.Write(header); foreach (DnsQuery query in message.Querys) { writer.Write(EncodeDnsQuery(query)); } foreach (DnsResource answer in message.Answers) { writer.Write(EncodeDnsResource(answer)); } foreach (DnsResource record in message.AuthorityRecords) { writer.Write(EncodeDnsResource(record)); } foreach (DnsResource record in message.AdditionalRecords) { writer.Write(EncodeDnsResource(record)); } return stream.ToArray(); }
/* * Header Structure, the bit labeled 0 is the most significant bit. * * 0 1 2 3 4 5 6 7 8 9 A B C D E F +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ID | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ |QR| Opcode |AA|TC|RD|RA| Z | RCODE | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | QDCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ANCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | NSCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ARCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ public static byte[] EncodeHeader(DnsMessage message) { MemoryStream stream = new MemoryStream(12); BinaryWriter writer = new BinaryWriter(stream); WriteUInt16BE(writer, message.ID); int fields = (int)message.ResponseCode; if (message.IsRecursionAvailable) { fields |= 0x80; } if (message.IsRecursionDesired) { fields |= 0x100; } if (message.IsTruncated) { fields |= 0x200; } if (message.IsRecursionAvailable) { fields |= 0x400; } fields |= (int)message.QueryKind << 11; //Opcode if (message.Type == MessageType.Response) { fields |= 0x8000; } WriteUInt16BE(writer, (UInt16)fields); WriteUInt16BE(writer, (UInt16)message.Querys.Count); WriteUInt16BE(writer, (UInt16)message.Answers.Count); WriteUInt16BE(writer, (UInt16)message.AuthorityRecords.Count); WriteUInt16BE(writer, (UInt16)message.AdditionalRecords.Count); return(stream.ToArray()); }
/* * Header Structure, the bit labeled 0 is the most significant bit. 0 1 2 3 4 5 6 7 8 9 A B C D E F +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ID | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ |QR| Opcode |AA|TC|RD|RA| Z | RCODE | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | QDCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ANCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | NSCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ARCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ public static byte[] EncodeHeader(DnsMessage message) { MemoryStream stream = new MemoryStream(12); BinaryWriter writer = new BinaryWriter(stream); WriteUInt16BE(writer, message.ID); int fields = (int)message.ResponseCode; if (message.IsRecursionAvailable) { fields |= 0x80; } if (message.IsRecursionDesired) { fields |= 0x100; } if (message.IsTruncated) { fields |= 0x200; } if (message.IsRecursionAvailable) { fields |= 0x400; } fields |= (int)message.QueryKind << 11; //Opcode if (message.Type == MessageType.Response) { fields |= 0x8000; } WriteUInt16BE(writer, (UInt16)fields); WriteUInt16BE(writer, (UInt16)message.Querys.Count); WriteUInt16BE(writer, (UInt16)message.Answers.Count); WriteUInt16BE(writer, (UInt16)message.AuthorityRecords.Count); WriteUInt16BE(writer, (UInt16)message.AdditionalRecords.Count); return stream.ToArray(); }
public static DnsMessage DecodeDnsMessage(byte[] msgData) { DnsMessage message = new DnsMessage(); message.ID = (UInt16)(msgData[0] << 8 | msgData[1]); message.Type = (MessageType)(msgData[2] >> 7); message.QueryKind = (QueryKind)((msgData[2] >> 3) & 15); message.ResponseCode = (ResponseCode)(msgData[3] & 15); MemoryStream stream = new MemoryStream(msgData); stream.Position = 4; BinaryReader reader = new BinaryReader(stream); int queryCount = ReadUInt16BE(reader); int answerCount = ReadUInt16BE(reader); int nsCount = ReadUInt16BE(reader); int arCount = ReadUInt16BE(reader); for (int i = 0; i < queryCount; i++) { message.Querys.Add(ReadDnsQuery(reader)); } for (int i = 0; i < answerCount; i++) { message.Answers.Add(ReadResourceRecord(reader)); } for (int i = 0; i < nsCount; i++) { message.AuthorityRecords.Add(ReadResourceRecord(reader)); } for (int i = 0; i < arCount; i++) { message.AdditionalRecords.Add(ReadResourceRecord(reader)); } return(message); }
public static DnsMessage DecodeDnsMessage(byte[] msgData) { DnsMessage message = new DnsMessage(); message.ID = (UInt16)(msgData[0] << 8 | msgData[1]); message.Type = (MessageType)(msgData[2] >> 7); message.QueryKind = (QueryKind)((msgData[2] >> 3) & 15); message.ResponseCode = (ResponseCode)(msgData[3] & 15); MemoryStream stream = new MemoryStream(msgData); stream.Position = 4; BinaryReader reader = new BinaryReader(stream); int queryCount = ReadUInt16BE(reader); int answerCount = ReadUInt16BE(reader); int nsCount = ReadUInt16BE(reader); int arCount = ReadUInt16BE(reader); for (int i = 0; i < queryCount; i++) { message.Querys.Add(ReadDnsQuery(reader)); } for (int i = 0; i < answerCount; i++) { message.Answers.Add(ReadResourceRecord(reader)); } for (int i = 0; i < nsCount; i++) { message.AuthorityRecords.Add(ReadResourceRecord(reader)); } for (int i = 0; i < arCount; i++) { message.AdditionalRecords.Add(ReadResourceRecord(reader)); } return message; }
private static IPAddress[] GetAddressList(DnsMessage answer, List<string> authorities) { List<IPAddress> serverAddresses = new List<IPAddress>(); foreach (DnsResource resource in answer.AdditionalRecords) { if (resource.QueryType == QueryType.Address) { if (authorities.Contains(resource.Name)) { IPAddress serverIP = new IPAddress((byte[])resource.Content); serverAddresses.Add(serverIP); } } } return serverAddresses.ToArray(); }
private static IPAddress[] GetAuthorityServers(DnsMessage answer) { List<string> authorities = new List<string>(); foreach (DnsResource resource in answer.AuthorityRecords) { if (resource.QueryType == QueryType.NameServer) { string nameServer = (string)resource.Content; authorities.Add(nameServer); } } if (answer.AdditionalRecords.Count > 0) { return GetAddressList(answer, authorities); } else { List<IPAddress> serverAddresses = new List<IPAddress>(); foreach (string authority in authorities) { serverAddresses.AddRange(System.Net.Dns.GetHostAddresses(authority)); } return serverAddresses.ToArray(); } }
private static string[] GetMailExchangeAliases(string domainName, DnsMessage answer) { List<string> aliases = new List<string>(); foreach (DnsResource resource in answer.Answers) { if (resource.QueryType == QueryType.MailExchange && resource.Name == domainName) { MailExchange mailExchange = (MailExchange)resource.Content; aliases.Add(mailExchange.HostName); } } return aliases.ToArray(); }
private static IPAddress[] GetAddressList(string domainName, DnsMessage answer) { List<IPAddress> addresseList = new List<IPAddress>(); foreach (DnsResource resource in answer.Answers) { if (resource.QueryType == QueryType.Address && resource.Name == domainName) { IPAddress ipAddress = new IPAddress((byte[])resource.Content); addresseList.Add(ipAddress); } } return addresseList.ToArray(); }
public static DnsMessage InverseQuery() { DnsMessage message = new DnsMessage(); message.ID = GenerateID(); message.Type = MessageType.Query; message.QueryKind = QueryKind.InverseQuery; return message; }
public static DnsMessage StandardQuery() { DnsMessage message = new DnsMessage(); message.ID = GenerateID(); message.Type = MessageType.Query; message.QueryKind = QueryKind.StandardQuery; return message; }