/// <summary> /// Handle the DNS query. /// </summary> public DnsResponse Get(DnsRequest request) { if (request == null) { throw new ArgumentNullException("request"); } DnsQuestion question = request.Question; if (question == null || question.Class != DnsStandard.Class.IN) { throw new DnsServerException(DnsStandard.ResponseCode.NotImplemented); } /* Don't handle NS and SOA record recursilvey since these are retrieved from the primary * DNS servers and are cached. So, we would always end up retrieving the cached values * from the primary DNS servers. */ if (request.Question.Type != DnsStandard.RecordType.ANAME && request.Question.Type != DnsStandard.RecordType.CERT && request.Question.Type != DnsStandard.RecordType.CNAME && request.Question.Type != DnsStandard.RecordType.MX) { throw new DnsServerException(DnsStandard.ResponseCode.NotImplemented); } DnsResponse response = ProcessRequest(request); return(response); }
/// <summary> /// processes a SRV Question, populated the response with any matching results pulled from the database store /// </summary> /// <param name="response">DnsResponse instance containing information about the question that will /// have any corresponding answer records populated upon return</param> protected void ProcessSRVQuestion(DnsResponse response) { using (RecordRetrievalServiceClient client = m_recordRetrievalServiceSettings.CreateRecordRetrievalClient()) { client.GetSRVRecords(response.Question.Domain, response.AnswerRecords); } }
public void Send(DnsResponse response) { DnsBuffer buffer = new DnsBuffer(); response.Serialize(buffer); this.SendBuffer(buffer); }
DnsResponse CreateResponse(DnsRequest request, IEnumerable <DnsResourceRecord> matches) { DnsStandard.RecordType questionType = request.Question.Type; DnsResponse response = new DnsResponse(request); int matchCount = 0; foreach (DnsResourceRecord record in matches) { if (record.Type == questionType) { ++matchCount; switch (record.Type) { default: response.AnswerRecords.Add(record); break; case DnsStandard.RecordType.NS: case DnsStandard.RecordType.SOA: response.AnswerRecords.Add(record); break; } } } if (matchCount == 0) { throw new DnsServerException(DnsStandard.ResponseCode.NameError); } return(response); }
/// <summary> /// this routine populates the cache with items and confirms that they are in there /// </summary> public void PopulateBasicCache() { m_drrc = new DnsResponseCache(Guid.NewGuid().ToString("D")); DumpSuccess(""); // populate the entires PopulateMockDnsARecordResponseEntries(); // force static TTL ForceTtlTime(m_basettl); foreach (DnsResponse dr in m_responses) { m_drrc.Put(dr); } DumpSuccess("Checking for {0} items stored in cache", m_responses.Count()); // make sure that the cache count reflects 10 entries Assert.Equal(m_responses.Count(), m_drrc.CacheCount); DumpSuccess("Checking all entries in cache to make sure they exist as expected"); // check the entries to make sure that all are found in the cache foreach (DnsResponse dr in m_responses) { DnsResponse res = m_drrc.Get(dr.Question); // make sure that the expect entry was found Assert.NotNull(res); } }
public DnsResponse Get(DnsRequest request) { ushort requestID = request.RequestID; DnsResponse response = null; try { using (DnsClient client = new DnsClient(m_serverIP)) { if (m_timeout != null) { client.Timeout = m_timeout.Value; } response = client.Resolve(request); } } finally { if (response != null) { response.RequestID = requestID; } request.RequestID = requestID; } return(response); }
internal DnsClientResponse(DnsClientRequest request, DnsResponse response, byte[] message) { Request = request; _message = message; _response = response; }
void HandleRequest(IAsyncResult result) { try { using (Socket socket = m_listener.EndAcceptSocket(result)) { TestTCPClient client = new TestTCPClient(socket); // Chunk sends DnsRequest request = client.ReceiveRequest(); DnsResponse response = null; try { response = m_store.Get(request); if (response == null) { response = new DnsResponse(request); response.Header.ResponseCode = DnsStandard.ResponseCode.NameError; } } catch { response = new DnsResponse(request); response.Header.ResponseCode = DnsStandard.ResponseCode.NameError; } if (response != null) { client.Send(response); } } } catch { } }
public void DnsResolve(string[] args) { string domain = args.GetRequiredValue(0); DnsStandard.RecordType recordType = args.GetOptionalEnum <DnsStandard.RecordType>(1, DnsStandard.RecordType.ANAME); try { using (DnsClient client = CreateClient()) { client.UseUDPFirst = (recordType != DnsStandard.RecordType.CERT); DnsResponse response = client.Resolve(new DnsRequest(recordType, domain)); if (response == null) { Console.WriteLine("No matches"); return; } m_recordPrinter.Print(response); } } catch (DnsServerException ex) { Console.WriteLine(ex.ResponseCode); } }
DnsResponse ProcessError(DnsRequest request, DnsStandard.ResponseCode code) { DnsResponse errorResponse = new DnsResponse(request); errorResponse.Header.ResponseCode = code; return(errorResponse); }
public void TestTypeSRVSort() { DnsResponse response = new DnsResponse(); response.AnswerRecords.Add(new SRVRecord("foo.order.com", 100, 389, "x.y.z.com", 50)); response.AnswerRecords.Add(new SRVRecord("foo.order.com", 100, 389, "x.y.z.com", 100)); response.AnswerRecords.Add(new SRVRecord("foo.order.com", 0, 389, "x.y.z.com", 0)); response.AnswerRecords.Add(new SRVRecord("foo.order.com", 0, 389, "x.y.z.com", 50)); response.AnswerRecords.Add(new SRVRecord("foo.order.com", 0, 389, "x.y.z.com", 100)); List <SRVRecord> responseList = response.AnswerRecords.SRV .OrderBy(r => r.Priority) .OrderByDescending(r => r.Weight) .ToList(); Assert.NotEqual(responseList[0].ToString(), "foo.order.com:389 Priority:0 Weight:0"); responseList = response.AnswerRecords.SRV .OrderBy(r => r.Priority) .ThenByDescending(r => r.Weight) .ToList(); Assert.Equal(responseList[0].ToString(), "foo.order.com:389 Priority:0 Weight:0"); Assert.Equal(responseList[1].ToString(), "foo.order.com:389 Priority:50 Weight:100"); Assert.Equal(responseList[2].ToString(), "foo.order.com:389 Priority:50 Weight:0"); Assert.Equal(responseList[3].ToString(), "foo.order.com:389 Priority:100 Weight:100"); Assert.Equal(responseList[4].ToString(), "foo.order.com:389 Priority:100 Weight:0"); }
/* * From a DnsResponse get a string representing the answers it provided with the TTLs removed. */ public static string GetAnswersString(DnsResponse response) { if (response.HasError) { return(response.Error.Code.ToString()); //TODO: Might be nice to make these prettier someday } var records = response.QueryResponse.Answers; if (records.Count == 0) { return("Empty"); } List <string> recordStrings = new List <string>(); foreach (var record in records) { var recordString = record.ToString(); var ttlStart = recordString.IndexOf(' '); var ttlEnd = recordString.IndexOf(' ', ttlStart + 1); recordString = recordString.Remove(ttlStart, ttlEnd - ttlStart); recordStrings.Add(recordString); } recordStrings.Sort(); return(string.Join(System.Environment.NewLine, recordStrings)); }
public void RequestResponse(IDnsContext context, ushort maxBufferLength) { if (context == null) { throw new ArgumentNullException(); } try { // // If we fail at parsing or receiving the request, then any exceptions will get logged and // the socket will be silently closed // context.ReceiveRequest(); DnsResponse response = this.ProcessRequest(context.DnsBuffer); if (response != null) { this.Serialize(response, context.DnsBuffer, maxBufferLength); context.SendResponse(); } } catch (IndexOutOfRangeException) { // Valid exception thrown during processing when bad requests are sent... // We won't dignify bad requests with a response } catch (DnsServerException) { // Valid exception thrown during processing when bad requests are sent... // We won't dignify bad requests with a response } }
internal DnsClientResponse(DnsClientRequest request, DnsResponse response) { Request = request; message = response.ToArray(); this.response = response; }
private void Resolve(DnsRequest request) { DnsResponse matches = m_client.Resolve(request); Assert.NotNull(matches); Assert.True(matches.HasAnswerRecords, string.Format("{0}:{1}", request.Question.Type, request.Question.Domain)); }
/// <summary> /// Look up a DNS SRV record, returning the best host and port number to connect to. /// </summary> /// <param name="prefix">The SRV prefix, ending with a dot. Example: "_xmpp-client._tcp."</param> /// <param name="domain">The domain to check</param> /// <param name="host">The host name to connect to</param> /// <param name="port">The port number to connect to</param> public static void LookupSRV(string prefix, string domain, ref string host, ref int port) { if (prefix == null) { throw new ArgumentNullException("prefix"); } if (domain == null) { throw new ArgumentNullException("domain"); } if (!prefix.EndsWith(".")) { throw new ArgumentOutOfRangeException("Prefix must end in '.'", "prefix"); } try { SRVRecord record; DnsRequest request = new DnsRequest(prefix + domain); DnsResponse response = request.GetResponse(DnsRecordType.SRV); record = PickSRV(response.SRVRecords); host = record.NameNext; port = record.Port; Debug.WriteLine(string.Format("SRV found: {0}:{1}", host, port)); } catch { host = domain; } }
public async Task DoesNotAccessOrgDmarcRecordWhenOrgDomain() { string[] records = { "v=DMARC1;p=reject;adkim=s;aspf=s ..." }; string orgDomain = "def.gov.uk"; string domain = "abc.def.gov.uk"; Response domainDnsQueryResponse = CreateRecord(domain, records, RCode.NXDomain); Response orgDomainDnsQueryResponse = CreateRecord(domain, records); OrganisationalDomain organisationalDomain = new OrganisationalDomain(orgDomain, orgDomain); A.CallTo(() => _dnsResolver.GetRecord($"_dmarc.{domain}", A <QType> ._)) .Returns(Task.FromResult(domainDnsQueryResponse)); A.CallTo(() => _dnsResolver.GetRecord($"_dmarc.{orgDomain}", A <QType> ._)) .Returns(Task.FromResult(orgDomainDnsQueryResponse)); A.CallTo(() => _organisationalDomainProvider.GetOrganisationalDomain(A <string> ._)) .Returns(Task.FromResult(organisationalDomain)); DnsResponse dmarcRecords = await _dmarcRecordDnsClient.GetRecord(domain); Assert.That(dmarcRecords.Records.Count, Is.EqualTo(1)); Assert.That(((DmarcRecordInfo)dmarcRecords.Records[0]).Record, Is.EqualTo(records[0])); A.CallTo(() => _organisationalDomainProvider.GetOrganisationalDomain(A <string> ._)).WithAnyArguments() .MustHaveHappenedOnceExactly(); A.CallTo(() => _dnsResolver.GetRecord(A <string> ._, A <QType> ._)).WithAnyArguments() .MustHaveHappenedOnceExactly(); }
public void ThreadProc(object state) { IEnumerable <string> domains = (IEnumerable <string>)state; using (DnsClient client = m_server.CreateClient()) { client.UseUDPFirst = m_udp; client.Timeout = m_timeout; foreach (string domain in domains) { try { DnsResponse response = client.Resolve(new DnsRequest(m_type, domain)); if (response.IsSuccess && response.HasAnswerRecords) { m_success++; } else { m_failure++; } } catch { m_failure++; } } } }
public void ResolveVerifyTTLUpdate() { using (DnsClient client = s_authoritativeResolverServer.CreateClient()) { DnsResponse response = client.Resolve(new DnsRequest(new DnsQuestion("direct.hisp.com", DnsStandard.RecordType.ANAME))); Thread.Sleep(2500); DnsResponse response2 = client.Resolve(new DnsRequest(new DnsQuestion("direct.hisp.com", DnsStandard.RecordType.ANAME))); for (int i = 0; i < response.AnswerRecords.Count; i++) { Assert.True(response.AnswerRecords[i].TTL > response2.AnswerRecords[i].TTL); } for (int i = 0; i < response.AdditionalRecords.Count; i++) { Assert.True(response.AdditionalRecords[i].TTL > response2.AdditionalRecords[i].TTL); } for (int i = 0; i < response.NameServerRecords.Count; i++) { Assert.True(response.NameServerRecords[i].TTL > response2.NameServerRecords[i].TTL); } } }
/// <summary> /// Get an empty error response with the given status code /// </summary> /// <param name="query"></param> /// <param name="statusCode"></param> /// <returns></returns> private static DnsResponse GetErrorResponse(DnsQuery query, DnsQueryStatusCode statusCode) { var response = new DnsResponse(query, null); response.StatusCode = statusCode; return(response); }
public DnsResourceRecord Receive() { DnsBuffer responseBuffer = this.ReceiveBuffer(); DnsResponse response = new DnsResponse(responseBuffer.CreateReader()); Assert.True(response.AnswerRecords.Count != 0); return(response.AnswerRecords[0]); }
public void TestNotSupported(string domain, DnsStandard.RecordType type, bool useUDP) { DnsClient client = TestServer.Default.CreateClient(); client.UseUDPFirst = !useUDP; DnsResponse response = client.Resolve(new DnsRequest(type, domain)); Assert.True(!response.IsSuccess); }
DnsResponse ProcessResponse(DnsResponse response) { if (!response.HasAnyRecords) { response = null; // This will cause the server to return a NameError } return(response); }
public void DnsSerialization_SOA_Response() { // Response packet captured for: // // nslookup -type=soa lilltek.com. const string raw = @" 00 07 81 80 00 01 00 00 00 01 00 00 07 6C 69 6C 6C 74 65 6B 03 63 6F 6D 00 00 06 00 01 C0 0C 00 06 00 01 00 00 2A 30 00 39 06 70 61 72 6B 31 39 0C 73 65 63 75 72 65 73 65 72 76 65 72 03 6E 65 74 00 03 64 6E 73 05 6A 6F 6D 61 78 C0 3D 77 82 0C F4 00 00 70 80 00 00 1C 20 00 09 3A 80 00 01 51 80 "; byte[] packet = Helper.FromHex(raw); DnsResponse message; SOA_RR soa_rr; // Test parsing message = new DnsResponse(); Assert.IsTrue(message.ParsePacket(packet, packet.Length)); Assert.AreEqual(DnsOpcode.QUERY, message.Opcode); Assert.AreEqual(DnsQClass.IN, message.QClass); Assert.AreEqual(DnsQType.SOA, message.QType); Assert.AreEqual(DnsFlag.RCODE_OK, message.RCode); Assert.AreEqual("lilltek.com.", message.QName); Assert.IsTrue((message.Flags & DnsFlag.QR) != 0); Assert.IsTrue((message.Flags & DnsFlag.TC) == 0); Assert.IsTrue((message.Flags & DnsFlag.RD) != 0); Assert.IsTrue((message.Flags & DnsFlag.RA) != 0); Assert.AreEqual(0, message.Answers.Count); Assert.AreEqual(1, message.Authorities.Count); Assert.AreEqual(DnsRRType.SOA, message.Authorities[0].RRType); soa_rr = (SOA_RR)message.Authorities[0]; Assert.AreEqual("lilltek.com.", soa_rr.RName); Assert.AreEqual(DnsRRType.SOA, soa_rr.RRType); Assert.AreEqual(DnsQClass.IN, soa_rr.QClass); Assert.AreEqual(10800, soa_rr.TTL); Assert.AreEqual("park19.secureserver.net.", soa_rr.Primary); Assert.AreEqual("dns.jomax.net.", soa_rr.AdminEmail); Assert.AreEqual((uint)2005011700, soa_rr.Serial); Assert.AreEqual((uint)28800, soa_rr.Refresh); Assert.AreEqual((uint)7200, soa_rr.Retry); Assert.AreEqual((uint)604800, soa_rr.Expire); Assert.AreEqual((uint)86400, soa_rr.Minimum); // Test rendering CollectionAssert.AreEqual(packet, Serialize(message)); }
public void DnsResolver_Multiple_Lookup() { // This test issues simultanious A queries for the 13 // global name servers and then verifies that the DnsResolver // was able to correctly correlate the responses to the // requests. IPAddress dns = GetDns(); string[] gtld = new string[] { "a.gtld-servers.net.", "b.gtld-servers.net.", "c.gtld-servers.net.", "d.gtld-servers.net.", "e.gtld-servers.net.", "f.gtld-servers.net.", "g.gtld-servers.net.", "h.gtld-servers.net.", "i.gtld-servers.net.", "j.gtld-servers.net.", "k.gtld-servers.net.", "l.gtld-servers.net.", "m.gtld-servers.net.", }; DnsRequest[] requests = new DnsRequest[gtld.Length]; DnsResponse[] responses = new DnsResponse[gtld.Length]; IAsyncResult[] rgAR = new IAsyncResult[gtld.Length]; for (int j = 0; j < 10; j++) { // Repeat the test 10 times just for fun for (int i = 0; i < gtld.Length; i++) { requests[i] = new DnsRequest(DnsFlag.RD, gtld[i], DnsQType.A); } for (int i = 0; i < gtld.Length; i++) { rgAR[i] = DnsResolver.BeginQuery(dns, requests[i], timeout, null, null); } for (int i = 0; i < gtld.Length; i++) { responses[i] = DnsResolver.EndQuery(rgAR[i]); } for (int i = 0; i < gtld.Length; i++) { Assert.AreEqual(requests[i].QID, responses[i].QID); Assert.AreEqual(requests[i].QName, responses[i].QName); } } }
/// <summary> /// processes a CERT Question, populated the response with any matching results pulled from the database store /// </summary> /// <param name="response">DnsResponse instance containing information about the question that will /// have any corresponding answer records populated upon return</param> void ProcessCERTQuestion(DnsResponse response) { using (RecordRetrievalServiceClient client = m_recordRetrievalServiceSettings.CreateRecordRetrievalClient()) { Certificate[] certs = client.GetCertificatesForOwner(response.Question.Domain); foreach (Certificate cert in certs) { response.AnswerRecords.Add(new CertRecord(new DnsX509Cert(cert.Data))); } } }
/// <summary> /// processes a ANAME Question, populated the response with any matching results pulled from the database store /// </summary> /// <param name="response">DnsResponse instance containing information about the question that will /// have any corresponding answer records populated upon return</param> protected void ProcessANAMEQuestion(DnsResponse response) { using (RecordRetrievalServiceClient client = m_recordRetrievalServiceSettings.CreateRecordRetrievalClient()) { client.GetANAMERecords(response.Question.Domain, response.AnswerRecords); if (!response.HasAnswerRecords) { client.GetCNAMERecords(response.Question.Domain, response.AnswerRecords); } } }
protected void Serialize(DnsResponse response, DnsBuffer buffer, int maxResponse) { buffer.Clear(); response.Serialize(buffer); if (buffer.Count > maxResponse) { response.Truncate(); buffer.Clear(); response.Serialize(buffer); } }
void OnTcpResponse(DnsResponse response) { if (m_logger.IsTraceEnabled) { m_logger.Debug(this.Summarize("TCP", response)); } else if (m_logger.IsDebugEnabled) { m_logger.Info("TCP Response {0} {1}", response.Question.Domain, response.Header.ResponseCode); } }
private DnsResponse CreateResponse(DnsRequest request, IPAddress address) { if (request == null || address == null) { return null; } DnsResponse response = CreateResponse(request.QueryID); response.Questions.Add(new ResourceRecord(request.Domain, request.QueryType, request.QueryClass, 127)); response.Answers.Add(new Address(request.Domain, request.QueryType, request.QueryClass, 127, address.ToString())); return response; }
/// <summary> /// Get an empty error response with the given status code /// </summary> /// <param name="query"></param> /// <param name="statusCode"></param> /// <returns></returns> private static DnsResponse GetErrorResponse(DnsQuery query, DnsQueryStatusCode statusCode) { var response = new DnsResponse(query, null); response.StatusCode = statusCode; return response; }
bool RetrieveDnsResponse(UdpSocket socket, UInt16 transactionID, out DnsResponse dnsResponse, Int64 timeoutInMachineTicks) { byte[] dnsFrameBuffer = new byte[DNS_FRAME_BUFFER_LENGTH]; while (timeoutInMachineTicks > Microsoft.SPOT.Hardware.Utility.GetMachineTime().Ticks) { Int32 bytesReceived = socket.Receive(dnsFrameBuffer, 0, dnsFrameBuffer.Length, 0, timeoutInMachineTicks); if (bytesReceived == 0) // timeout { break; } /* parse our DNS response */ Int32 bufferIndex = 0; // verify that the transaction ID matches UInt16 verifyTransactionID = (UInt16)( (UInt16)(dnsFrameBuffer[bufferIndex++] << 8) + (UInt16)(dnsFrameBuffer[bufferIndex++]) ); if (transactionID != verifyTransactionID) continue; /* filter out this DHCP frame */ // Flags UInt16 flags = (UInt16)( (UInt16)(dnsFrameBuffer[bufferIndex++] << 8) + (UInt16)(dnsFrameBuffer[bufferIndex++]) ); DnsResponseCode responseCode = (DnsResponseCode)(flags & 0x0F); // Query Count UInt16 queryCount = (UInt16)( (UInt16)(dnsFrameBuffer[bufferIndex++] << 8) + (UInt16)(dnsFrameBuffer[bufferIndex++]) ); // Answer Record Count UInt16 answerRecordCount = (UInt16)( (UInt16)(dnsFrameBuffer[bufferIndex++] << 8) + (UInt16)(dnsFrameBuffer[bufferIndex++]) ); // Authority Record Count UInt16 authorityRecordCount = (UInt16)( (UInt16)(dnsFrameBuffer[bufferIndex++] << 8) + (UInt16)(dnsFrameBuffer[bufferIndex++]) ); // Additional Information Record Count UInt16 additionalInformationRecordCount = (UInt16)( (UInt16)(dnsFrameBuffer[bufferIndex++] << 8) + (UInt16)(dnsFrameBuffer[bufferIndex++]) ); /* parse our query records */ string queryName = ""; DnsRecordType queryType = (DnsRecordType)0; for (int iRecord = 0; iRecord < queryCount; iRecord++) { // Query Name bufferIndex += ParseDnsName(dnsFrameBuffer, bufferIndex, out queryName); queryType = (DnsRecordType)( (UInt16)(dnsFrameBuffer[bufferIndex++] << 8) + (UInt16)(dnsFrameBuffer[bufferIndex++]) ); UInt16 queryClass = (UInt16)( (UInt16)(dnsFrameBuffer[bufferIndex++] << 8) + (UInt16)(dnsFrameBuffer[bufferIndex++]) ); if (queryClass != DNS_RECORD_CLASS_INTERNET) continue; /* filter out the current query */ } /* parse our answer records */ DnsResourceRecord[] answerRecords = new DnsResourceRecord[answerRecordCount]; for (int iRecord = 0; iRecord < answerRecordCount; iRecord++) { // store answer record bufferIndex += ParseResourceRecord(dnsFrameBuffer, bufferIndex, out answerRecords[iRecord]); } /* parse our authority records */ DnsResourceRecord[] authorityRecords = new DnsResourceRecord[authorityRecordCount]; for (int iRecord = 0; iRecord < authorityRecordCount; iRecord++) { // store authority record bufferIndex += ParseResourceRecord(dnsFrameBuffer, bufferIndex, out authorityRecords[iRecord]); } /* parse our authority records */ DnsResourceRecord[] additionalInformationRecords = new DnsResourceRecord[additionalInformationRecordCount]; for (int iRecord = 0; iRecord < additionalInformationRecordCount; iRecord++) { // store authority record bufferIndex += ParseResourceRecord(dnsFrameBuffer, bufferIndex, out additionalInformationRecords[iRecord]); } dnsResponse = new DnsResponse(responseCode, queryType, queryName, answerRecords, authorityRecords, additionalInformationRecords); return true; } // if we did not receive a message before timeout, return false. dnsResponse = null; return false; }
void OnReceive (IAsyncResult ares) { if (disposed) return; int nread = 0; EndPoint remote_ep = client.RemoteEndPoint; try { nread = client.EndReceive (ares); } catch (Exception e) { Console.Error.WriteLine (e); } BeginReceive (); byte [] buffer = (byte []) ares.AsyncState; if (nread > 12) { DnsResponse response = new DnsResponse (buffer, nread); int id = response.Header.ID; SimpleResolverEventArgs args = null; lock (queries) { if (queries.TryGetValue (id, out args)) { queries.Remove (id); } } if (args != null) { Timer t = args.Timer; if (t != null) t.Change (Timeout.Infinite, Timeout.Infinite); try { ProcessResponse (args, response, remote_ep); } catch (Exception e) { args.ResolverError = (ResolverError) (-1); args.ErrorMessage = e.Message; } IPHostEntry entry = args.HostEntry; if (args.ResolverError != 0 && args.PTRAddress != null && entry != null && entry.HostName != null) { args.PTRAddress = null; SendAQuery (args, entry.HostName, true); args.Timer.Change (5000, Timeout.Infinite); } else { args.OnCompleted (this); } } } }
void ProcessResponse (SimpleResolverEventArgs args, DnsResponse response, EndPoint server_ep) { DnsRCode status = response.Header.RCode; if (status != 0) { if (args.PTRAddress != null) { // PTR query failed -> no error, we have the IP return; } args.ResolverError = (ResolverError) status; return; } // TODO: verify IP of the server is in our list and the same one that got the query IPEndPoint ep = (IPEndPoint) server_ep; if (ep.Port != 53) { args.ResolverError = ResolverError.ResponseHeaderError; args.ErrorMessage = "Port"; return; } DnsHeader header = response.Header; if (!header.IsQuery) { args.ResolverError = ResolverError.ResponseHeaderError; args.ErrorMessage = "IsQuery"; return; } // TODO: handle Truncation. Retry with bigger buffer? if (header.QuestionCount > 1) { args.ResolverError = ResolverError.ResponseHeaderError; args.ErrorMessage = "QuestionCount"; return; } ReadOnlyCollection<DnsQuestion> q = response.GetQuestions (); if (q.Count != 1) { args.ResolverError = ResolverError.ResponseHeaderError; args.ErrorMessage = "QuestionCount 2"; return; } DnsQuestion question = q [0]; /* The answer might have dot at the end, etc... if (String.Compare (question.Name, args.HostName) != 0) { args.ResolverError = ResolverError.ResponseHeaderError; args.ErrorMessage = "HostName - " + question.Name + " != " + args.HostName; return; } */ DnsQType t = question.Type; if (t != DnsQType.A && t != DnsQType.AAAA && t != DnsQType.PTR) { args.ResolverError = ResolverError.ResponseHeaderError; args.ErrorMessage = "QType " + question.Type; return; } if (question.Class != DnsQClass.IN) { args.ResolverError = ResolverError.ResponseHeaderError; args.ErrorMessage = "QClass " + question.Class; return; } ReadOnlyCollection<DnsResourceRecord> records = response.GetAnswers (); if (records.Count == 0) { if (args.PTRAddress != null) { // PTR query failed -> no error return; } args.ResolverError = ResolverError.NameError; // is this ok? args.ErrorMessage = "NoAnswers"; return; } List<string> aliases = null; List<IPAddress> addresses = null; foreach (DnsResourceRecord r in records) { if (r.Class != DnsClass.IN) continue; if (r.Type == DnsType.A || r.Type == DnsType.AAAA) { if (addresses == null) addresses = new List<IPAddress> (); addresses.Add (((DnsResourceRecordIPAddress) r).Address); } else if (r.Type == DnsType.CNAME) { if (aliases == null) aliases = new List<string> (); aliases.Add (((DnsResourceRecordCName) r).CName); } else if (r.Type == DnsType.PTR) { args.HostEntry.HostName = ((DnsResourceRecordPTR) r).DName; args.HostEntry.Aliases = aliases == null ? EmptyStrings : aliases.ToArray (); args.HostEntry.AddressList = EmptyAddresses; return; } } IPHostEntry entry = args.HostEntry ?? new IPHostEntry (); if (entry.HostName == null && aliases != null && aliases.Count > 0) { entry.HostName = aliases [0]; aliases.RemoveAt (0); } entry.Aliases = aliases == null ? EmptyStrings : aliases.ToArray (); entry.AddressList = addresses == null ? EmptyAddresses : addresses.ToArray (); args.HostEntry = entry; if ((question.Type == DnsQType.A || question.Type == DnsQType.AAAA) && entry.AddressList == EmptyAddresses) { args.ResolverError = ResolverError.NameError; args.ErrorMessage = "No addresses in response"; } else if (question.Type == DnsQType.PTR && entry.HostName == null) { args.ResolverError = ResolverError.NameError; args.ErrorMessage = "No PTR in response"; } }
bool SendDnsQueryAndWaitForResponse(UInt32 dnsServerIPAddress, DnsRecordType recordType, string name, out DnsResponse dnsResponse, Int64 timeoutInMachineTicks) { // obtain an exclusive handle to the reserved socket int socketHandle = _ipv4Layer.CreateSocket(IPv4Layer.ProtocolType.Udp, timeoutInMachineTicks, true); // instantiate the reserved socket UdpSocket socket = (UdpSocket)_ipv4Layer.GetSocket(socketHandle); try { // create DNS request header byte[] dnsRequestBuffer = new byte[DNS_FRAME_BUFFER_LENGTH]; int bufferIndex = 0; /* Transaction ID */ UInt16 transactionID = _nextTransactionID++; dnsRequestBuffer[bufferIndex++] = (byte)((transactionID >> 8) & 0xFF); dnsRequestBuffer[bufferIndex++] = (byte)(transactionID & 0xFF); /* Flags (including OpCode and RCODE) */ DnsMessageFlagsFlags flags = 0; /* QR = 0 (query) * OpCode = 0 (standard query/response) * RD = 1 (recursion desired) */ flags |= DnsMessageFlagsFlags.RecursionDesired; dnsRequestBuffer[bufferIndex++] |= (byte)(((UInt16)flags >> 8) & 0xFF); dnsRequestBuffer[bufferIndex++] |= (byte)((UInt16)flags & 0xFF); /* Query Count */ UInt16 queryCount = 1; dnsRequestBuffer[bufferIndex++] = (byte)((queryCount >> 8) & 0xFF); dnsRequestBuffer[bufferIndex++] = (byte)(queryCount & 0xFF); /* Answer Count */ // skip bytes 6-7 bufferIndex += 2; /* Authority Record Count */ // skip bytes 8-9 bufferIndex += 2; /* Additional Information Count */ // skip bytes 10-11 bufferIndex += 2; // create dns question (query) // Query Name Int32 namePosition = 0; while (true) { Int32 labelLength = name.IndexOf('.', namePosition) - namePosition; if (labelLength < 0) { bufferIndex++; break; } dnsRequestBuffer[bufferIndex++] = (byte)labelLength; Int32 labelLengthVerify = System.Text.Encoding.UTF8.GetBytes(name, namePosition, labelLength, dnsRequestBuffer, bufferIndex); // if the label was not decoded as 8-bit characters, throw an exception; international punycode-encoded domains are not supported. if (labelLengthVerify != labelLength) throw new ArgumentException(); namePosition += labelLength + 1; bufferIndex += labelLength; } // Query Type dnsRequestBuffer[bufferIndex++] = (byte)((((UInt16)recordType) >> 8) & 0xFF); dnsRequestBuffer[bufferIndex++] = (byte)(((UInt16)recordType) & 0xFF); // Query Class UInt16 queryClass = DNS_RECORD_CLASS_INTERNET; dnsRequestBuffer[bufferIndex++] = (byte)((queryClass >> 8) & 0xFF); dnsRequestBuffer[bufferIndex++] = (byte)(queryClass & 0xFF); /* NOTE: this implementation queries the primary DNS address */ // send DNS request socket.SendTo(dnsRequestBuffer, 0, bufferIndex, 0, timeoutInMachineTicks, dnsServerIPAddress, DNS_SERVER_PORT); // wait for DNS response bool success = RetrieveDnsResponse(socket, transactionID, out dnsResponse, timeoutInMachineTicks); if (success) { return true; } } finally { // close the reserved socket _ipv4Layer.CloseSocket(socketHandle); } return false; /* could not retrieve DNS response */ }