Beispiel #1
0
        /// <summary>
        /// Parses a resource record from the packet passed.
        /// </summary>
        /// <param name="message">The message containing the record being parsed.</param>
        /// <param name="packet">The raw DNS message packet.</param>
        /// <param name="offset">
        /// The current offset in the packet.  Returns as the offset of the first byte
        /// after the record.
        /// </param>
        /// <returns>The resource record or <c>null</c> if there was an error.</returns>
        public static DnsRR Parse(DnsMessage message, byte[] packet, ref int offset)
        {
            string    qname;
            DnsRRType rrtype;
            DnsRR     rr;
            int       savePos;

            // Peek the qname and record type

            savePos = offset;

            if (!message.ReadName(packet, ref offset, out qname))
            {
                return(null);
            }

            rrtype = (DnsRRType)Helper.ReadInt16(packet, ref offset);
            offset = savePos;

            switch (rrtype)
            {
            case DnsRRType.A:

                rr = new A_RR();
                break;

            case DnsRRType.CNAME:

                rr = new CNAME_RR();
                break;

            case DnsRRType.NS:

                rr = new NS_RR();
                break;

            case DnsRRType.MX:

                rr = new MX_RR();
                break;

            case DnsRRType.SOA:

                rr = new SOA_RR();
                break;

            default:

                rr = new DnsRR();
                break;
            }

            if (!rr.Read(message, packet, ref offset))
            {
                return(null);
            }

            return(rr);
        }
Beispiel #2
0
        /// <summary>
        /// This method parses the raw DNS message packet passed and initializes
        /// the message properties.
        /// </summary>
        /// <param name="packet">The raw DNS packet received.</param>
        /// <param name="cbPacket">Number of bytes in that packet.</param>
        /// <returns>True on success.</returns>
        public bool ParsePacket(byte[] packet, int cbPacket)
        {
            uint qdCount;
            uint anCount;
            uint nsCount;
            uint arCount;
            int  pos;

            // Read the message header

            pos      = 0;
            this.qid = (ushort)Helper.ReadInt16(packet, ref pos); if (pos > cbPacket)
            {
                return(false);
            }
            this.flags = (DnsFlag)Helper.ReadInt16(packet, ref pos); if (pos > cbPacket)
            {
                return(false);
            }
            qdCount = (ushort)Helper.ReadInt16(packet, ref pos); if (pos > cbPacket)
            {
                return(false);
            }
            anCount = (ushort)Helper.ReadInt16(packet, ref pos); if (pos > cbPacket)
            {
                return(false);
            }
            nsCount = (ushort)Helper.ReadInt16(packet, ref pos); if (pos > cbPacket)
            {
                return(false);
            }
            arCount = (ushort)Helper.ReadInt16(packet, ref pos); if (pos > cbPacket)
            {
                return(false);
            }

            Assertion.Test(pos == 12);

            // Check for unsupported packets

            if ((this.flags & DnsFlag.TC) != 0)     // truncation bit is set
            {
                return(false);
            }

            if (this.Opcode != DnsOpcode.QUERY)     // only accept standard queries
            {
                return(false);
            }

            if (qdCount != 1)                       // only supporting one question
            {
                return(false);
            }

            // Parse the question

            if (!ReadName(packet, ref pos, out this.qname))
            {
                return(false);
            }

            if (pos > cbPacket)
            {
                return(false);
            }

            this.qtype = (DnsQType)Helper.ReadInt16(packet, ref pos); if (pos > cbPacket)
            {
                return(false);
            }
            this.qclass = (DnsQClass)Helper.ReadInt16(packet, ref pos); if (pos > cbPacket)
            {
                return(false);
            }

            // We're only going to accept Internet queries

            if (this.qclass != DnsQClass.IN)
            {
                return(false);
            }

            // Parse the answer records

            for (int i = 0; i < anCount; i++)
            {
                var rr = DnsRR.Parse(this, packet, ref pos);

                if (rr == null || pos > cbPacket)
                {
                    return(false);
                }

                this.Answers.Add(rr);
            }

            // Parse the authority records

            for (int i = 0; i < nsCount; i++)
            {
                var rr = DnsRR.Parse(this, packet, ref pos);

                if (rr == null || pos > cbPacket)
                {
                    return(false);
                }

                this.Authorities.Add(rr);
            }

            // Parse the additional records

            for (int i = 0; i < arCount; i++)
            {
                var rr = DnsRR.Parse(this, packet, ref pos);

                if (rr == null || pos > cbPacket)
                {
                    return(false);
                }

                this.Additional.Add(rr);
            }

            // $todo(jeff.lill):
            //
            // Delete this once we've figured out why the DNS server
            // sometimes get requests with NULL QNAME properties.

            if (this.QName == null)
            {
                var packetBytes     = Helper.Extract(packet, cbPacket);
                var hexDump         = Helper.HexDump(packetBytes, 16, HexDumpOption.ShowAll);
                var diagnostics     = GetTraceDetails(IPAddress.Any);
                var extendedLogInfo = new StringSysLogEntryExtension(diagnostics + "\r\n\r\nPacket:\r\n\r\n" + hexDump);

                SysLog.LogWarning(extendedLogInfo, "DNS Packet with QNAME=NULL");
            }

            return(true);
        }