private void DecodeQuestions(IDnsResponse response, IByteBuffer buffer, int questionCount)
 {
     for (int i = questionCount - 1; i > 0; i--)
     {
         response.AddRecord(DnsSection.QUESTION, recordDecoder.DecodeQuestion(buffer));
     }
 }
        internal ClientDnsResponse(IDnsRequest request, IDnsResponse response, byte[] message)
        {
            Request = request;

            this.message  = message;
            this.response = response;
        }
        internal ClientDnsResponse(IDnsRequest request, IDnsResponse response)
        {
            Request = request;

            this.message  = response.ToArray();
            this.response = response;
        }
예제 #4
0
        public async Task <IDnsResponse> Resolve(IDnsRequest request)
        {
            using (TcpClient tcp = new TcpClient())
            {
                await tcp.ConnectAsync(dns.Address, dns.Port);

                Stream stream = tcp.GetStream();
                byte[] buffer = request.ToArray();
                byte[] length = BitConverter.GetBytes((ushort)buffer.Length);

                if (BitConverter.IsLittleEndian)
                {
                    Array.Reverse(length);
                }

                await stream.WriteAsync(length, 0, length.Length);

                await stream.WriteAsync(buffer, 0, buffer.Length);

                buffer = new byte[2];
                await Read(stream, buffer);

                if (BitConverter.IsLittleEndian)
                {
                    Array.Reverse(buffer);
                }

                buffer = new byte[BitConverter.ToUInt16(buffer, 0)];
                await Read(stream, buffer);

                IDnsResponse response = DefaultDnsResponse.FromArray(buffer);
                return(new ClientDnsResponse(request, response, buffer));
            }
        }
        protected override void Decode(IChannelHandlerContext context, DatagramPacket message, List <object> output)
        {
            IByteBuffer  buffer   = message.Content;
            IDnsResponse response = NewResponse(message, buffer);
            bool         success  = false;

            try
            {
                int questionCount         = buffer.ReadUnsignedShort();
                int answerCount           = buffer.ReadUnsignedShort();
                int authorityRecordCount  = buffer.ReadUnsignedShort();
                int additionalRecordCount = buffer.ReadUnsignedShort();

                DecodeQuestions(response, buffer, questionCount);
                DecodeRecords(response, DnsSection.ANSWER, buffer, answerCount);
                DecodeRecords(response, DnsSection.AUTHORITY, buffer, authorityRecordCount);
                DecodeRecords(response, DnsSection.ADDITIONAL, buffer, additionalRecordCount);

                output.Add(response);
                success = true;
            }
            finally
            {
                if (!success)
                {
                    response.Release();
                }
            }
        }
예제 #6
0
        /// <summary>
        /// Resolves this request into a response using the provided DNS information. The given
        /// request strategy is used to retrieve the response.
        /// </summary>
        /// <exception cref="DnsResponseException">Throw if a malformed response is received from the server</exception>
        /// <exception cref="IOException">Thrown if a IO error occurs</exception>
        /// <exception cref="SocketException">Thrown if the reading or writing to the socket fails</exception>
        /// <exception cref="OperationCanceledException">Thrown if reading or writing to the socket timeouts</exception>
        /// <returns>The response received from server</returns>
        public async Task <IDnsResponse> Resolve()
        {
            try
            {
                IDnsResponse response = await resolver.Resolve(this);

                if (response.Id != this.Id)
                {
                    throw new DnsResponseException(response, "Mismatching request/response IDs");
                }

                if (response.ResponseCode != DnsResponseCode.NoError)
                {
                    throw new DnsResponseException(response);
                }

                return(response);
            }
            catch (ArgumentException e)
            {
                throw new DnsResponseException("Invalid response", e);
            }
            catch (IndexOutOfRangeException e)
            {
                throw new DnsResponseException("Invalid response", e);
            }
        }
예제 #7
0
            public async Task<IDnsResponse> Resolve(IDnsRequest request)
            {
                IDnsResponse response = null;

                foreach (IDnsRequestResolver resolver in resolvers)
                {
                    response = await resolver.Resolve(request);
                    if (response.AnswerRecords.Count > 0) break;
                }

                return response;
            }
예제 #8
0
        public async Task <string> Reverse(IPAddress ip)
        {
            IDnsResponse response = await Resolve(Domain.PointerName(ip), DnsRecordType.PTR);

            IResourceRecord ptr = response.AnswerRecords.FirstOrDefault(r => r.Type == DnsRecordType.PTR);

            if (ptr == null)
            {
                throw new DnsResponseException(response, "No matching records");
            }

            return(((PointerResourceRecord)ptr).PointerDomainName.ToString());
        }
        private void DecodeRecords(IDnsResponse response, DnsSection section, IByteBuffer buffer, int count)
        {
            for (int i = count - 1; i > 0; i--)
            {
                IDnsRecord r = recordDecoder.DecodeRecord(buffer);
                if (r == null)
                {
                    break;
                }

                response.AddRecord(section, r);
            }
        }
        public DefaultDnsResponse(IDnsResponse response)
        {
            this.header     = new DnsMessageHeader();
            this.questions  = new List <DnsQuestion>(response.Questions);
            this.answers    = new List <IResourceRecord>(response.AnswerRecords);
            this.authority  = new List <IResourceRecord>(response.AuthorityRecords);
            this.additional = new List <IResourceRecord>(response.AdditionalRecords);

            this.header.Response = true;

            Id = response.Id;
            RecursionAvailable = response.RecursionAvailable;
            AuthorativeServer  = response.AuthorativeServer;
            OperationCode      = response.OperationCode;
            ResponseCode       = response.ResponseCode;
        }
예제 #11
0
            public DnsResponse(IDnsResponse response)
            {
                header            = new DnsHeader();
                Questions         = new List <DnsQuestion>(response.Questions);
                AnswerRecords     = new List <IDnsResourceRecord>(response.AnswerRecords);
                AuthorityRecords  = new List <IDnsResourceRecord>(response.AuthorityRecords);
                AdditionalRecords = new List <IDnsResourceRecord>(response.AdditionalRecords);

                header.Response = true;

                Id = response.Id;
                IsRecursionAvailable = response.IsRecursionAvailable;
                IsAuthorativeServer  = response.IsAuthorativeServer;
                OperationCode        = response.OperationCode;
                ResponseCode         = response.ResponseCode;
            }
예제 #12
0
        public IDnsResponse Decode(T sender, T recipient, IByteBuffer buffer)
        {
            int id    = buffer.ReadUnsignedShort();
            int flags = buffer.ReadUnsignedShort();

            if (flags >> 15 == 0)
            {
                throw new CorruptedFrameException("not a response");
            }

            IDnsResponse response = NewResponse(
                sender,
                recipient,
                id,
                new DnsOpCode((byte)(flags >> 11 & 0xf)), DnsResponseCode.From((flags & 0xf)));

            response.IsRecursionDesired    = (flags >> 8 & 1) == 1;
            response.IsAuthoritativeAnswer = (flags >> 10 & 1) == 1;
            response.IsTruncated           = (flags >> 9 & 1) == 1;
            response.IsRecursionAvailable  = (flags >> 7 & 1) == 1;
            response.Z = flags >> 4 & 0x7;

            bool success = false;

            try
            {
                int questionCount         = buffer.ReadUnsignedShort();
                int answerCount           = buffer.ReadUnsignedShort();
                int authorityRecordCount  = buffer.ReadUnsignedShort();
                int additionalRecordCount = buffer.ReadUnsignedShort();

                DecodeQuestions(response, buffer, questionCount);
                DecodeRecords(response, DnsSection.ANSWER, buffer, answerCount);
                DecodeRecords(response, DnsSection.AUTHORITY, buffer, authorityRecordCount);
                DecodeRecords(response, DnsSection.ADDITIONAL, buffer, additionalRecordCount);
                success = true;
                return(response);
            }
            finally
            {
                if (!success)
                {
                    response.Release();
                }
            }
        }
예제 #13
0
        public Task <IDnsResponse> Resolve(IDnsRequest request)
        {
            IDnsResponse response = DefaultDnsResponse.FromRequest(request);

            foreach (DnsQuestion question in request.Questions)
            {
                IList <IResourceRecord> answers = Get(question);

                if (answers.Count > 0)
                {
                    Merge(response.AnswerRecords, answers);
                }
                else
                {
                    response.ResponseCode = DnsResponseCode.NameError;
                }
            }

            return(Task.FromResult(response));
        }
예제 #14
0
        public async Task <IList <IPAddress> > Lookup(string domain, DnsRecordType type = DnsRecordType.A)
        {
            if (type != DnsRecordType.A && type != DnsRecordType.AAAA)
            {
                throw new ArgumentException("Invalid record type " + type);
            }

            IDnsResponse response = await Resolve(domain, type);

            IList <IPAddress> ips = response.AnswerRecords
                                    .Where(r => r.Type == type)
                                    .Cast <IPAddressResourceRecord>()
                                    .Select(r => r.IPAddress)
                                    .ToList();

            if (ips.Count == 0)
            {
                throw new DnsResponseException(response, "No matching records");
            }

            return(ips);
        }
 public DnsResponseException(IDnsResponse response) : this(response, Format(response))
 {
 }
예제 #16
0
파일: Utils.cs 프로젝트: shanyipeng/KissU
        internal static StringBuilder AppendResponseHeader(this StringBuilder builder, IDnsResponse response)
        {
            builder.Append(response.GetType().GetTypeInfo().Name)
            .Append('(')
            .AppendAddresses(response)
            .Append(response.Id)
            .Append(", ")
            .Append(response.OpCode)
            .Append(", ")
            .Append(response.Code)
            .Append(',');

            bool hasComma = true;

            if (response.IsRecursionDesired)
            {
                hasComma = false;
                builder.Append(" RD");
            }
            if (response.IsAuthoritativeAnswer)
            {
                hasComma = false;
                builder.Append(" AA");
            }
            if (response.IsTruncated)
            {
                hasComma = false;
                builder.Append(" TC");
            }
            if (response.IsRecursionAvailable)
            {
                hasComma = false;
                builder.Append(" RA");
            }
            if (response.Z != 0)
            {
                if (!hasComma)
                {
                    builder.Append(',');
                }
                builder.Append(" Z: ")
                .Append(response.Z);
            }

            if (hasComma)
            {
                builder[builder.Length - 1] = ')';
            }
            else
            {
                builder.Append(')');
            }

            return(builder);
        }
예제 #17
0
파일: Utils.cs 프로젝트: shanyipeng/KissU
 internal static StringBuilder AppendResponse(this StringBuilder builder, IDnsResponse response)
 {
     builder.AppendResponseHeader(response)
     .AppendAllRecords(response);
     return(builder);
 }
 public DnsResponseException(IDnsResponse response, string message)
     : base(message)
 {
     DnsResponse = response;
 }
예제 #19
0
        private async void HandleRequest(byte[] data, IPEndPoint remote)
        {
            DefaultDnsRequest request = null;

            try
            {
                request = DefaultDnsRequest.FromArray(data);
                OnRequested(request);

                IDnsResponse response = await resolver.Resolve(request);

                OnResponded(request, response);
                await udp
                    .SendAsync(response.ToArray(), response.Size, remote)
                    .WithCancellationTimeout(UDP_TIMEOUT);
            }
            catch (SocketException e)
            {
                OnErrored(e);
            }
            catch (ArgumentException e)
            {
                OnErrored(e);
            }
            catch (IndexOutOfRangeException e)
            {
                OnErrored(e);
            }
            catch (OperationCanceledException e)
            {
                OnErrored(e);
            }
            catch (IOException e)
            {
                OnErrored(e);
            }
            catch (ObjectDisposedException e)
            {
                OnErrored(e);
            }
            catch (DnsResponseException e)
            {
                IDnsResponse response = e.DnsResponse;

                if (response == null)
                {
                    response = DefaultDnsResponse.FromRequest(request);
                }

                try
                {
                    await udp
                        .SendAsync(response.ToArray(), response.Size, remote)
                        .WithCancellationTimeout(UDP_TIMEOUT);
                }
                catch (SocketException)
                {
                }
                catch (OperationCanceledException)
                {
                }
                finally
                {
                    OnErrored(e);
                }
            }
        }
예제 #20
0
 protected virtual void OnResponded(IDnsRequest request, IDnsResponse response)
 {
     RespondedEventHandler handlers = Responded;
     if (handlers != null) handlers(request, response);
 }
 private static string Format(IDnsResponse response)
 {
     return(string.Format("Invalid response received with code {0}", response.ResponseCode));
 }
 public DnsResponseException(IDnsResponse response, Exception e)
     : base(Format(response), e)
 {
     DnsResponse = response;
 }