Beispiel #1
0
        /// <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);
     }
 }
Beispiel #3
0
        public void Send(DnsResponse response)
        {
            DnsBuffer buffer = new DnsBuffer();

            response.Serialize(buffer);
            this.SendBuffer(buffer);
        }
Beispiel #4
0
        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);
            }
        }
Beispiel #6
0
        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);
        }
Beispiel #7
0
            internal DnsClientResponse(DnsClientRequest request, DnsResponse response, byte[] message)
            {
                Request = request;

                _message  = message;
                _response = response;
            }
Beispiel #8
0
        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
            {
            }
        }
Beispiel #9
0
        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);
            }
        }
Beispiel #10
0
        DnsResponse ProcessError(DnsRequest request, DnsStandard.ResponseCode code)
        {
            DnsResponse errorResponse = new DnsResponse(request);

            errorResponse.Header.ResponseCode = code;
            return(errorResponse);
        }
Beispiel #11
0
        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");
        }
Beispiel #12
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));
        }
Beispiel #13
0
        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
            }
        }
Beispiel #14
0
            internal DnsClientResponse(DnsClientRequest request, DnsResponse response)
            {
                Request = request;

                message       = response.ToArray();
                this.response = response;
            }
Beispiel #15
0
        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));
        }
Beispiel #16
0
 /// <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;
     }
 }
Beispiel #17
0
        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();
        }
Beispiel #18
0
        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++;
                    }
                }
            }
        }
Beispiel #19
0
        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);
                }
            }
        }
Beispiel #20
0
        /// <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);
        }
Beispiel #21
0
        public DnsResourceRecord Receive()
        {
            DnsBuffer   responseBuffer = this.ReceiveBuffer();
            DnsResponse response       = new DnsResponse(responseBuffer.CreateReader());

            Assert.True(response.AnswerRecords.Count != 0);
            return(response.AnswerRecords[0]);
        }
Beispiel #22
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);
        }
Beispiel #24
0
        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));
        }
Beispiel #25
0
        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);
         }
     }
 }
Beispiel #28
0
 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);
     }
 }
Beispiel #29
0
 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);
     }
 }
Beispiel #30
0
        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;
        }
Beispiel #33
0
		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);
					}
				}
			}

		}
Beispiel #34
0
		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";
			}

		}
Beispiel #35
0
        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 */
        }