public static int Parse(out DnsQuestion question, byte[] array, int offset) { question = new DnsQuestion (); question.DataPointer = offset; int startingOffset = offset; // Parse the domain name byte partLength = 0; var hostnameBuilder = new StringBuilder (); while ((partLength = array[offset++]) > 0) { var domainPart = Encoding.UTF8.GetString (array, offset, partLength); // Add separating dots if (hostnameBuilder.Length > 0) { hostnameBuilder.Append ('.'); } hostnameBuilder.Append (domainPart); offset += partLength; // TODO: handle bytes larger than 255 chracters (LIMIT!) } // Parse the zone request type // 2 bytes var zoneType = (DnsZoneType)DnsEncoder.ParseUint16(array, offset); offset += 2; // Skip 2 bytes of QCLASS, we don't need them var questionClass = (DnsRecordClass)DnsEncoder.ParseUint16(array, offset); offset += 2; // Wire up the data question.Hostname = hostnameBuilder.ToString (); question.ZoneType = zoneType; question.Class = questionClass; return offset - startingOffset; }
/// <summary> /// Parse the DnsQuery from the given UdpReceiveResult /// </summary> /// <param name="data"></param> /// <returns></returns> public static DnsQuery Parse(byte[] buffer, IPAddress remoteEndpoint) { // Create the query var query = new DnsQuery(); query.Status = DnsQueryStatus.OK; query.ClientIPAddress = remoteEndpoint; // Parse the dns request header query.Header = DnsMessageHeader.Parse(buffer, 0); // DNS QUESTIONS: int offset = 12; for (int i = 0; i < query.Header.QuestionCount; i++) { try { // Save the question DnsQuestion question; offset += DnsQuestion.Parse(out question, buffer, offset); if (question != null) { query.Questions.Add(question); } } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); query.Status = DnsQueryStatus.ParsingError; break; } } // Save the original question data to include it in the answer query.OriginalQuestionData = new byte[offset]; Buffer.BlockCopy(buffer, 0, query.OriginalQuestionData, 0, offset); // Parse the additional EDNS question // For now, we only support a single additional question if (query.Header.AdditionalQuestionCount > 0) { //Console.WriteLine("Reading OPT"); try { int bytesProcessed = 0; query.EdnsQuestion = EdnsQuestion.Parse(buffer, offset, ref bytesProcessed); offset += bytesProcessed; // If the question was validely parsed, try using the subnet to assign the IP based on the user's location instead of the // dns proxy server if (query.EdnsQuestion != null) { var clientSubnetOption = (EdnsClientSubnetOption)query.EdnsQuestion.GetOption(EdnsOptionCode.ClientSubnet); if (clientSubnetOption != null) { query.ClientIPAddress = clientSubnetOption.IPAddress; } } } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); // If this fails, we still try to proceed normally // TODO: log } } return(query); }
/// <summary> /// Create a DnsAnswer linked to the given question /// </summary> /// <param name="dnsQuestion">DnsQuestion.</param> public DnsAnswer (DnsQuestion dnsQuestion) { this.Question = dnsQuestion; this.Hostname = null; }
/// <summary> /// Create a DnsAnswer linked to the given question /// </summary> /// <param name="dnsQuestion">DnsQuestion.</param> public DnsAnswer(DnsQuestion dnsQuestion) { this.Question = dnsQuestion; this.Hostname = null; }