コード例 #1
0
ファイル: Resolver.cs プロジェクト: queueit/Dns
        /// <summary>
        /// Query and get a resource record on specified DNS Server.
        /// </summary>
        /// <param name="host">The name of host to query.</param>
        /// <param name="qType">The QTYPE to use</param>
        /// <param name="qClass">The QCLASS to use</param>
        /// <returns>Return an asynchronsous operation.</returns>
        public Task <IResponse> QueryAsync(string host, QTYPE qType, QCLASS qClass)
        {
            var question = new Question(host, qType, qClass);
            var request  = new Request()
            {
                Retries    = this.Retries,
                DnsServers = this._dnsServers,
                Timeout    = this.Timeout
            };
            var id = (ushort)Interlocked.Increment(ref _uid);

            request.Header.ID = id;
            request.Header.RD = this.Recursion;
            request.AddQuestion(question);
            DnsChannel channel = null;

            if (_transportType == TransportType.Tcp)
            {
                channel = new TcpChannel(request);
            }
            else
            {
                channel = new UdpChannel(request);
            }
            return(channel.GetResponseAsync(_dnsServers[0]));
        }
コード例 #2
0
ファイル: Question.cs プロジェクト: boethin/dnstools
        /// <summary>
        /// Initialize a new DNS question.
        /// </summary>
        /// <param name="qname">A domain name represented as a sequence of labels.</param>
        /// <param name="qtype">A two octet code which specifies the type of the query.</param>
        /// <param name="qclass">A two octet code that specifies the class of the query.</param>
        public Question(string qname, QTYPE qtype, QCLASS qclass)
        {
            if (String.IsNullOrEmpty(qname))
            throw new ArgumentNullException("qname", "Value cannot be null or empty.");

              this.QNAME = qname;
              this.QTYPE = qtype;
              this.QCLASS = qclass;
        }
コード例 #3
0
ファイル: Question.cs プロジェクト: Moerty/dnstools
        /// <summary>
        /// Initialize a new DNS question using QCLASS IN.
        /// </summary>
        /// <param name="qname">A domain name represented as a sequence of labels.</param>
        /// <param name="qtype">A two octet code which specifies the type of the query.</param>
        public Question(string qname, QTYPE qtype)
        {
            if (String.IsNullOrEmpty(qname))
            {
                throw new ArgumentNullException("qname", "Value cannot be null or empty.");
            }

            this.QNAME  = qname;
            this.QTYPE  = qtype;
            this.QCLASS = DNS.QCLASS.IN;
        }
コード例 #4
0
        public override int GetHashCode()
        {
            return(0);

            unchecked
            {
                var hashCode = (QNAME != null ? QNAME.GetHashCode() : 0);
                hashCode = (hashCode * 397) ^ QTYPE.GetHashCode();
                hashCode = (hashCode * 397) ^ QCLASS.GetHashCode();
                return(hashCode);
            }
        }
コード例 #5
0
        private static Question[] ToQuestions(string QNAME, QTYPE[] QTYPEs, QCLASS QCLASS)
        {
            int i, c = QTYPEs.Length;

            Question[] Questions = new Question[c];

            for (i = 0; i < c; i++)
            {
                Questions[i] = new Question(QNAME, QTYPEs[i], QCLASS);
            }

            return(Questions);
        }
コード例 #6
0
ファイル: DnsMessage.cs プロジェクト: robinreigns/IoTGateway
        /// <summary>
        /// Represents a DNS message
        /// </summary>
        /// <param name="Data">Binary representation of a DNS message.</param>
        public DnsMessage(byte[] Data)
        {
            this.binary = Data;

            using (MemoryStream ms = new MemoryStream(Data))
            {
                this.id = DnsClient.ReadUInt16(ms);

                byte b = (byte)ms.ReadByte();
                this.response            = (b & 0x80) != 0;
                this.opCode              = (OpCode)((b >> 3) & 15);
                this.authoritativeAnswer = (b & 4) != 0;
                this.truncation          = (b & 2) != 0;
                this.recursionDesired    = (b & 1) != 0;

                b = (byte)ms.ReadByte();
                this.recursionAvailable = (b & 128) != 0;
                this.rCode = (RCode)(b & 31);

                ushort QDCOUNT = DnsClient.ReadUInt16(ms);
                ushort ANCOUNT = DnsClient.ReadUInt16(ms);
                ushort NSCOUNT = DnsClient.ReadUInt16(ms);
                ushort ARCOUNT = DnsClient.ReadUInt16(ms);

                this.questions = new Question[QDCOUNT];
                ushort i;

                for (i = 0; i < QDCOUNT; i++)
                {
                    string QNAME  = DnsClient.ReadName(ms);
                    QTYPE  QTYPE  = (QTYPE)DnsClient.ReadUInt16(ms);
                    QCLASS QCLASS = (QCLASS)DnsClient.ReadUInt16(ms);

                    this.questions[i] = new Question(QNAME, QTYPE, QCLASS);
                }

                this.answer     = DnsClient.ReadResourceRecords(ms, ANCOUNT);
                this.authority  = DnsClient.ReadResourceRecords(ms, NSCOUNT);
                this.additional = DnsClient.ReadResourceRecords(ms, ARCOUNT);
            }
        }
コード例 #7
0
 /// <summary>
 /// Execute a DNS query.
 /// </summary>
 /// <param name="QNAME">Query Name</param>
 /// <param name="QTYPEs">Query Type</param>
 /// <param name="QCLASS">Query Class</param>
 /// <param name="Destination">Destination. If null, default destination is assumed.</param>
 public Task <DnsMessage> QueryAsync(string QNAME, QTYPE[] QTYPEs, QCLASS QCLASS, IPEndPoint Destination)
 {
     return(this.QueryAsync(ToQuestions(QNAME, QTYPEs, QCLASS), Destination));
 }
コード例 #8
0
 /// <summary>
 /// Execute a DNS query.
 /// </summary>
 /// <param name="QNAME">Query Name</param>
 /// <param name="QTYPE">Query Type</param>
 /// <param name="QCLASS">Query Class</param>
 /// <param name="Destination">Destination. If null, default destination is assumed.</param>
 public Task <DnsMessage> QueryAsync(string QNAME, QTYPE QTYPE, QCLASS QCLASS, IPEndPoint Destination)
 {
     return(this.QueryAsync(new Question[] { new Question(QNAME, QTYPE, QCLASS) }, Destination));
 }
コード例 #9
0
 /// <summary>
 /// Execute a DNS query.
 /// </summary>
 /// <param name="QNAME">Query Name</param>
 /// <param name="QTYPEs">Query Types</param>
 /// <param name="QCLASS">Query Class</param>
 /// <param name="Destination">Destination. If null, default destination is assumed.</param>
 /// <param name="Callback">Method to call when response is returned.</param>
 /// <param name="State">State object to pass on to callback method.</param>
 public void Query(string QNAME, QTYPE[] QTYPEs, QCLASS QCLASS, IPEndPoint Destination, DnsMessageEventHandler Callback, object State)
 {
     this.Query(ToQuestions(QNAME, QTYPEs, QCLASS), Destination, Callback, State);
 }
コード例 #10
0
 /// <summary>
 /// Execute a DNS query.
 /// </summary>
 /// <param name="QNAME">Query Name</param>
 /// <param name="QTYPE">Query Type</param>
 /// <param name="QCLASS">Query Class</param>
 /// <param name="Destination">Destination. If null, default destination is assumed.</param>
 /// <param name="Callback">Method to call when response is returned.</param>
 /// <param name="State">State object to pass on to callback method.</param>
 public void Query(string QNAME, QTYPE QTYPE, QCLASS QCLASS, IPEndPoint Destination, DnsMessageEventHandler Callback, object State)
 {
     this.Query(new Question[] { new Question(QNAME, QTYPE, QCLASS) }, Destination, Callback, State);
 }
コード例 #11
0
ファイル: Question.cs プロジェクト: robinreigns/IoTGateway
 /// <summary>
 /// Contains information about a DNS Question
 /// </summary>
 /// <param name="QNAME">Qujery Name</param>
 /// <param name="QTYPE">Query Type</param>
 /// <param name="QCLASS">Query Class</param>
 public Question(string QNAME, QTYPE QTYPE, QCLASS QCLASS)
 {
     this.qNAME  = QNAME;
     this.qTYPE  = QTYPE;
     this.qCLASS = QCLASS;
 }
コード例 #12
0
        /// <summary>
        /// Resolves a DNS name.
        /// </summary>
        /// <param name="Name">Domain Name to resolve</param>
        /// <param name="TYPE">Resource Record Type of interest.</param>
        /// <param name="ExceptionType">If no answer of type <paramref name="TYPE"/> is found, records of this type can also be accepted.</param>
        /// <param name="CLASS">Resource Record Class of interest.</param>
        /// <returns>Answer to the query</returns>
        /// <exception cref="IOException">If the domain name could not be resolved for the TYPE and CLASS provided.</exception>
        public static async Task <ResourceRecord[]> Resolve(string Name, QTYPE TYPE,
                                                            TYPE?ExceptionType, QCLASS CLASS)
        {
            LinkedList <KeyValuePair <string, IPEndPoint> > Backup = null;
            TYPE?      ExpectedType;
            IPEndPoint Destination = null;
            string     LastName    = null;
            int        Timeout     = 2000;      // Local timeout

            if (Enum.TryParse <TYPE>(TYPE.ToString(), out TYPE T))
            {
                ExpectedType = T;
            }
            else
            {
                ExpectedType = null;
            }

            lock (synchObject)
            {
                if (nestingDepth == 0 && networkChanged)
                {
                    networkChanged = false;
                    client?.Dispose();
                    client = null;
                }

                if (client is null)
                {
                    client = new DnsUdpClient();
                }

                nestingDepth++;
            }

            try
            {
                while (true)
                {
                    DnsResponse Response = null;
                    DnsMessage  Message;

                    if (LastName is null || LastName != Name)
                    {
                        LastName = Name;

                        try
                        {
                            Response = await Database.FindFirstDeleteRest <DnsResponse>(new FilterAnd(
                                                                                            new FilterFieldEqualTo("Name", Name),
                                                                                            new FilterFieldEqualTo("Type", TYPE),
                                                                                            new FilterFieldEqualTo("Class", CLASS)));

                            if (!(Response is null) && Response.Expires <= DateTime.Now)
                            {
                                await Database.Delete(Response);

                                Response = null;
                            }
                        }
                        catch (Exception)
                        {
                            // Some inconsistency in database. Clear collection to get fresh set of DNS entries.
                            await Database.Clear("DnsCache");

                            Response = null;
                        }
                    }

                    if (Response is null)
                    {
                        try
                        {
                            Message = await client.SendRequestAsync(OpCode.Query, true, new Question[]
                            {
                                new Question(Name, TYPE, CLASS)
                            }, Destination, Timeout);

                            switch (Message.RCode)
                            {
                            case RCode.NXDomain:
                                throw new ArgumentException("Domain name does not exist.", nameof(Name));
                            }
                        }
                        catch (TimeoutException)
                        {
                            Message = null;
                        }

                        if (Message is null || Message.RCode != RCode.NoError)
                        {
                            Destination = await NextDestination(Backup);

                            if (Destination is null)
                            {
                                throw new IOException("Unable to resolve DNS query.");
                            }

                            continue;                               // Check an alternative
                        }

                        uint Ttl = 60 * 60 * 24 * 30;                               // Maximum TTL = 30 days

                        Response = new DnsResponse()
                        {
                            Name       = Name,
                            Type       = TYPE,
                            Class      = CLASS,
                            Answer     = CheckTtl(ref Ttl, Message.Answer),
                            Authority  = CheckTtl(ref Ttl, Message.Authority),
                            Additional = CheckTtl(ref Ttl, Message.Additional)
                        };

                        Response.Expires = DateTime.Now.AddSeconds(Ttl);

                        await Database.Insert(Response);
                    }

                    string CName = null;

                    if (!(Response.Answer is null))
                    {
                        if (!ExpectedType.HasValue)
                        {
                            return(Response.Answer);
                        }

                        foreach (ResourceRecord RR in Response.Answer)
                        {
                            if (RR.Type == ExpectedType.Value)
                            {
                                return(Response.Answer);
                            }

                            if (CName is null && RR.Type == Enumerations.TYPE.CNAME && RR is CNAME CNAME)
                            {
                                CName = CNAME.Name2;
                            }
                        }

                        if (ExceptionType.HasValue)
                        {
                            foreach (ResourceRecord RR in Response.Answer)
                            {
                                if (RR.Type == ExceptionType.Value)
                                {
                                    return(Response.Answer);
                                }
                            }
                        }

                        if (!(CName is null))
                        {
                            Name   = CName;
                            Backup = null;
                            continue;
                        }
                    }

                    if (!(Response.Authority is null))
                    {
                        foreach (ResourceRecord RR in Response.Authority)
                        {
                            if (RR is NS NS)
                            {
                                string    Authority        = NS.Name2;
                                IPAddress AuthorityAddress = null;

                                if (!(Response.Additional is null))
                                {
                                    foreach (ResourceRecord RR2 in Response.Additional)
                                    {
                                        if (RR2 is A A)
                                        {
                                            AuthorityAddress = A.Address;
                                            break;
                                        }
                                        else if (RR2 is AAAA AAAA)
                                        {
                                            AuthorityAddress = AAAA.Address;
                                            break;
                                        }
                                    }
                                }

                                if (Backup is null)
                                {
                                    Backup = new LinkedList <KeyValuePair <string, IPEndPoint> >();
                                }

                                if (AuthorityAddress is null)
                                {
                                    Backup.AddLast(new KeyValuePair <string, IPEndPoint>(Authority, null));
                                }
                                else
                                {
                                    Backup.AddLast(new KeyValuePair <string, IPEndPoint>(null, new IPEndPoint(AuthorityAddress, DefaultDnsPort)));
                                }
                            }
                        }
                    }

                    Destination = await NextDestination(Backup);

                    if (Destination is null)
                    {
                        throw new IOException("Unable to resolve DNS query.");
                    }

                    Timeout = 5000;
                }
            }
            finally
            {
                lock (synchObject)
                {
                    nestingDepth--;
                }
            }
        }
コード例 #13
0
 /// <summary>
 /// Resolves a DNS name.
 /// </summary>
 /// <param name="Name">Domain Name to resolve</param>
 /// <param name="TYPE">Resource Record Type of interest.</param>
 /// <param name="CLASS">Resource Record Class of interest.</param>
 /// <returns>Answer to the query</returns>
 /// <exception cref="IOException">If the domain name could not be resolved for the TYPE and CLASS provided.</exception>
 public static Task <ResourceRecord[]> Resolve(string Name, QTYPE TYPE, QCLASS CLASS)
 {
     return(Resolve(Name, TYPE, null, CLASS));
 }
コード例 #14
0
ファイル: Question.cs プロジェクト: queueit/Dns
 public Question(string qName, QTYPE qType, QCLASS qClass)
 {
     this.QName  = qName;
     this.QType  = qType;
     this.QClass = qClass;
 }
コード例 #15
0
ファイル: Question.cs プロジェクト: Moerty/dnstools
 void Internal.IResponseReader.ReadResponse(Internal.ByteReader reader)
 {
     QNAME  = reader.ReadDomain();
     QTYPE  = reader.ReadUIn16Enum <QTYPE>();
     QCLASS = reader.ReadUIn16Enum <QCLASS>();
 }