Beispiel #1
0
        internal static ResourceRecord ReadFrom(PacketReader reader)
        {
            string name = reader.ReadName();
            RecordType type = (RecordType)reader.ReadUShort();
            RecordClass rClass = (RecordClass)reader.ReadUShort();
            DateTime expiry = DateTime.UtcNow + TimeSpan.FromSeconds(reader.ReadInt());

            switch (type)
            {
                case RecordType.Pointer:
                    return new PointerRecord(name, type, rClass, expiry, reader);

                case RecordType.CanonicalName:
                    return new CanonicalNameRecord(name, type, rClass, expiry, reader);

                case RecordType.Address:
                    return new IP4AddressRecord(name, type, rClass, expiry, reader);

                case RecordType.Text:
                    return new TextRecord(name, type, rClass, expiry, reader);

                case RecordType.Service:
                    return new ServiceRecord(name, type, rClass, expiry, reader);

                default:
                    int len = reader.ReadUShort();
                    reader.Position += len;
                    return new ResourceRecord(name, type, rClass, expiry);
            }
        }
Beispiel #2
0
        public static Message Read(PacketReader reader)
        {
            Message result = new Message();

            result.TransactionId = reader.ReadUShort();
            result.Flags = new MessageFlags(reader.ReadUShort());

            ushort questions = reader.ReadUShort();
            ushort answers = reader.ReadUShort();
            ushort authorityRecords = reader.ReadUShort();
            ushort additionalRecords = reader.ReadUShort();

            for (int i = 0; i < questions; ++i)
            {
                result.Questions.Add(Question.ReadFrom(reader));
            }

            for (int i = 0; i < answers; ++i)
            {
                result.Answers.Add(ResourceRecord.ReadFrom(reader));
            }

            for (int i = 0; i < authorityRecords; ++i)
            {
                result.AuthorityRecords.Add(ResourceRecord.ReadFrom(reader));
            }

            for (int i = 0; i < additionalRecords; ++i)
            {
                result.AdditionalRecords.Add(ResourceRecord.ReadFrom(reader));
            }

            return result;
        }
Beispiel #3
0
        internal IP4AddressRecord(string name, RecordType type, RecordClass rClass, DateTime expiry, PacketReader reader)
            : base(name, type, rClass, expiry)
        {
            ushort dataLen = reader.ReadUShort();
            int pos = reader.Position;

            _address = new IPAddress(reader.ReadBytes(dataLen));

            reader.Position = pos + dataLen;
        }
Beispiel #4
0
        internal PointerRecord(string name, RecordType type, RecordClass rClass, DateTime expiry, PacketReader reader)
            : base(name, type, rClass, expiry)
        {
            ushort dataLen = reader.ReadUShort();
            int pos = reader.Position;

            _targetName = reader.ReadName();

            reader.Position = pos + dataLen;
        }
Beispiel #5
0
        internal ServiceRecord(string name, RecordType type, RecordClass rClass, DateTime expiry, PacketReader reader)
            : base(name, type, rClass, expiry)
        {
            ushort dataLen = reader.ReadUShort();
            int pos = reader.Position;

            _priority = reader.ReadUShort();
            _weight = reader.ReadUShort();
            _port = reader.ReadUShort();
            _target = reader.ReadName();

            reader.Position = pos + dataLen;
        }
Beispiel #6
0
        internal TextRecord(string name, RecordType type, RecordClass rClass, DateTime expiry, PacketReader reader)
            : base(name, type, rClass, expiry)
        {
            _values = new Dictionary<string, byte[]>();

            ushort dataLen = reader.ReadUShort();
            int pos = reader.Position;

            while (reader.Position < pos + dataLen)
            {
                int valueLen = reader.ReadByte();
                byte[] valueBinary = reader.ReadBytes(valueLen);

                StoreValue(valueBinary);
            }
        }
        private void ReceiveCallback(IAsyncResult ar)
        {
            try
            {
                IPEndPoint sender = null;
                byte[] packetBytes;

                lock (_udpClient)
                {
                    packetBytes = _udpClient.EndReceive(ar, ref sender);
                }

                PacketReader reader = new PacketReader(packetBytes);

                Message msg = Message.Read(reader);

                lock (_transactions)
                {
                    Transaction transaction;
                    _transactions.TryGetValue(msg.TransactionId, out transaction);

                    foreach (var answer in msg.AdditionalRecords)
                    {
                        AddRecord(_cache, answer);
                    }

                    foreach (var answer in msg.Answers)
                    {
                        if (transaction != null)
                        {
                            transaction.Answers.Add(answer);
                        }

                        AddRecord(_cache, answer);
                    }
                }
            }
            finally
            {
                lock (_udpClient)
                {
                    _udpClient.BeginReceive(ReceiveCallback, null);
                }
            }
        }
Beispiel #8
0
        /// <summary>
        /// Looks up a record in DNS.
        /// </summary>
        /// <param name="name">The name to lookup</param>
        /// <param name="type">The type of record requested</param>
        /// <returns>The records returned by the DNS server, if any</returns>
        public override ResourceRecord[] Lookup(string name, RecordType type)
        {
            ushort transactionId = _nextTransId++;
            string normName = NormalizeDomainName(name);

            using (UdpClient udpClient = new UdpClient(0))
            {
                IAsyncResult result = udpClient.BeginReceive(null, null);

                PacketWriter writer = new PacketWriter(1800);
                Message msg = new Message();
                msg.TransactionId = transactionId;
                msg.Flags = new MessageFlags(false, OpCode.Query, false, false, false, false, ResponseCode.Success);
                msg.Questions.Add(new Question() { Name = normName, Type = type, Class = RecordClass.Internet });

                msg.WriteTo(writer);

                byte[] msgBytes = writer.GetBytes();

                foreach (var server in _servers)
                {
                    udpClient.Send(msgBytes, msgBytes.Length, server);
                }

                for (int i = 0; i < maxRetries; ++i)
                {
                    DateTime now = DateTime.UtcNow;
                    while (result.AsyncWaitHandle.WaitOne(Math.Max(responseTimeout - (DateTime.UtcNow - now).Milliseconds, 0)))
                    {
                        try
                        {
                            IPEndPoint sourceEndPoint = null;
                            byte[] packetBytes = udpClient.EndReceive(result, ref sourceEndPoint);
                            PacketReader reader = new PacketReader(packetBytes);

                            Message response = Message.Read(reader);

                            if (response.TransactionId == transactionId)
                            {
                                return response.Answers.ToArray();
                            }
                        }
                        catch
                        {
                            // Do nothing - bad packet (probably...)
                        }
                    }
                }
            }

            return null;
        }
        internal CanonicalNameRecord(string name, RecordType type, RecordClass rClass, DateTime expiry, PacketReader reader)
            : base(name, type, rClass, expiry)
        {
            ushort dataLen = reader.ReadUShort();
            int    pos     = reader.Position;

            _canonicalName = reader.ReadName();

            reader.Position = pos + dataLen;
        }