Exemple #1
0
        /// <summary>
        /// Gets MX records.(MX records are sorted by preference, lower array element is prefered)
        /// </summary>
        /// <param name="domain"></param>
        /// <param name="mxRecords"></param>
        /// <returns></returns>
        public DnsReplyCode GetMXRecords(string domain, out MX_Record[] mxRecords)
        {
            //--- Try to get MX records from cache
            mxRecords = DnsCache.GetMXFromCache(domain);
            if (mxRecords != null)
            {
                //		Console.WriteLine("domain:" + domain + " from cahce.");
                return(DnsReplyCode.Ok);
            }
            //------------------------------------//

            Dns_Header header = new Dns_Header(DnsEx.ID, OPCODE.IQUERY);
            Dns_Query  query  = new Dns_Query(domain, QTYPE.MX, 1);

            byte[] bQuery = query.GetQuery(header);

            byte[] reply = GetQuery(bQuery, header.ID);
            if (reply != null)
            {
                Dns_Answers answers = new Dns_Answers();
                if (answers.ParseAnswers(reply, header.ID))
                {
                    mxRecords = answers.GetMxRecordsFromAnswers();

                    if (mxRecords != null)
                    {
                        // Add to cache
                        DnsCache.AddMXToCache(domain, mxRecords);
                        return(DnsReplyCode.Ok);
                    }
                    else
                    {
                        return(DnsReplyCode.NoEntries);
                    }
                }
            }

            return(DnsReplyCode.TempError);
        }
        /// <summary>
        /// Parses answer.
        /// </summary>
        /// <param name="reply"></param>
        /// <param name="queryID"></param>
        /// <returns>Returns true if answer parsed successfully.</returns>
        internal bool ParseAnswers(byte[] reply, int queryID)
        {
            try
            {
                /*
                 *                                                 1  1  1  1  1  1
                 * 0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
                 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
                 |                                               |
                 | /                                               /
                 | /                      NAME                     /
                 |                                               |
                 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
                 |                      TYPE                     |
                 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
                 |                     CLASS                     |
                 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
                 |                      TTL                      |
                 |                                               |
                 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
                 |                   RDLENGTH                    |
                 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
                 | /                     RDATA                     /
                 | /                                               /
                 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
                 */

                //------- Parse result -----------------------------------//

                Dns_Header replyHeader = new Dns_Header();
                if (!replyHeader.ParseHeader(reply))
                {
                    return(false);
                }

                // Check that it's query what we want
                if (queryID != replyHeader.ID)
                {
                    return(false);
                }

                int pos = 12;

                //----- Parse question part ------------//
                for (int q = 0; q < replyHeader.QDCOUNT; q++)
                {
                    string dummy = "";
                    GetQName(reply, ref pos, ref dummy);
                    //qtype + qclass
                    pos += 4;
                }
                //--------------------------------------//

                ArrayList answers = new ArrayList();

                //---- Start parsing aswers ------------------------------------------------------------------//
                for (int i = 0; i < replyHeader.ANCOUNT; i++)
                {
                    string name = "";
                    if (!GetQName(reply, ref pos, ref name))
                    {
                        return(false);
                    }

                    int type     = reply[pos++] << 8 | reply[pos++];
                    int rdClass  = reply[pos++] << 8 | reply[pos++];
                    int ttl      = reply[pos++] << 24 | reply[pos++] << 16 | reply[pos++] << 8 | reply[pos++];
                    int rdLength = reply[pos++] << 8 | reply[pos++];

                    object answerObj = null;
                    switch ((QTYPE)type)
                    {
                    case QTYPE.MX:
                        answerObj = ParseMxRecord(reply, ref pos);
                        break;

                    default:
                        answerObj = "sgas";                                 // Dummy place holder for now
                        pos      += rdLength;
                        break;
                    }

                    // Add answer to answer list
                    if (answerObj != null)
                    {
                        answers.Add(new Dns_Answer(name, (QTYPE)type, rdClass, ttl, rdLength, answerObj));
                    }
                    else
                    {
                        return(false);                        // Parse failed
                    }
                }
                //-------------------------------------------------------------------------------------------//

                if (answers.Count > 0)
                {
                    m_Answers = new Dns_Answer[answers.Count];
                    answers.CopyTo(m_Answers);
                }

                return(true);
            }
            catch {
                return(false);
            }
        }
Exemple #3
0
        /// <summary>
        /// Gets query.
        /// </summary>
        /// <param name="header"></param>
        /// <returns></returns>
        public byte[] GetQuery(Dns_Header header)
        {
            byte[] query = null;

            try
            {
                /*  4.1.2. Question section format
                 *                                1  1  1  1  1  1
                 * 0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
                 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
                 |                                               |
                 | /                     QNAME                     /
                 | /                                               /
                 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
                 |                     QTYPE                     |
                 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
                 |                     QCLASS                    |
                 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
                 |
                 | QNAME
                 |      a domain name represented as a sequence of labels, where
                 | each label consists of a length octet followed by that
                 |      number of octets.  The domain name terminates with the
                 | zero length octet for the null label of the root.  Note
                 |      that this field may be an odd number of octets; no
                 | padding is used.
                 */

                query = new byte[521];

                // Copy dns header to query
                byte[] head = header.GetHeader();
                head.CopyTo(query, 0);

                //--------- Query part ------------------------------------//
                string[] labels   = m_QNAME.Split(new char[] { '.' });
                int      position = 12;

                // Copy all domain parts(labels) to query
                // eg. lumisoft.ee = 2 labels, lumisoft and ee.
                // format = label.length + label(bytes)
                foreach (string label in labels)
                {
                    // add label lenght to query
                    query[position++] = (byte)(label.Length);

                    // convert label string to byte array
                    byte[] b = Encoding.ASCII.GetBytes(label.ToCharArray());
                    b.CopyTo(query, position);

                    // Move position by label length
                    position += b.Length;
                }

                // Terminate domain (see note above)
                query[position++] = (byte)0;

                // Set QTYPE
                query[position++] = (byte)0;
                query[position++] = (byte)m_QTYPE;

                // Set QCLASS
                query[position++] = (byte)0;
                query[position++] = (byte)m_QCALSS;
                //-------------------------------------------------------//
            }
            catch
            {
                query = null;
            }

            return(query);
        }