/// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="owner">Owner DNS client.</param>
        /// <param name="id">Transaction ID.</param>
        /// <param name="qtype">QTYPE value.</param>
        /// <param name="qname">QNAME value.</param>
        /// <param name="timeout">Timeout in milliseconds.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>owner</b> or <b>qname</b> is null reference.</exception>
        internal DNS_ClientTransaction(Dns_Client owner,int id,DNS_QType qtype,string qname,int timeout)
        {
            if(owner == null){
                throw new ArgumentNullException("owner");
            }
            if(qname == null){
                throw new ArgumentNullException("qname");
            }

            m_pOwner = owner;
            m_ID     = id;
            m_QName  = qname;
            m_QType  = qtype;

            m_CreateTime    = DateTime.Now;
            m_pTimeoutTimer = new TimerEx(timeout);
            m_pTimeoutTimer.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimeoutTimer_Elapsed);
        }
Exemple #2
0
        public static string[] GetDomainHosts(string domain)
        {
            if(domain == null){
                throw new ArgumentNullException("domain");
            }
            if(string.IsNullOrEmpty(domain)){
                throw new ArgumentException("Invalid argument 'domain' value, you need to specify domain value.");
            }

            // We have email address, parse domain.
            if(domain.IndexOf("@") > -1){
                domain = domain.Substring(domain.IndexOf('@') + 1);
            }

            List<string> retVal = new List<string>();

            // Get MX records.
            using(Dns_Client dns = new Dns_Client()){
                DnsServerResponse response = dns.Query(domain,DNS_QType.MX);
                if(response.ResponseCode == DNS_RCode.NO_ERROR){
                    foreach(DNS_rr_MX mx in response.GetMXRecords()){
                        // Block invalid MX records.
                        if(!string.IsNullOrEmpty(mx.Host)){
                            retVal.Add(mx.Host);
                        }
                    }
                }
                else{
                    throw new DNS_ClientException(response.ResponseCode);
                }
            }

            /* RFC 2821 5.
                If no MX records are found, but an A RR is found, the A RR is treated as if it
                was associated with an implicit MX RR, with a preference of 0, pointing to that host.
            */
            if(retVal.Count == 0){
                retVal.Add(domain);
            }

            return retVal.ToArray();
        }
Exemple #3
0
        public static IPAddress[] Resolve(string host)
        {
            if(host == null){
                throw new ArgumentNullException("host");
            }

            // If hostName_IP is IP
            try{
                return new IPAddress[]{IPAddress.Parse(host)};
            }
            catch{
            }

            // This is probably NetBios name
            if(host.IndexOf(".") == -1){
                return System.Net.Dns.GetHostEntry(host).AddressList;
            }
            else{
                // hostName_IP must be host name, try to resolve it's IP
                using(Dns_Client dns = new Dns_Client()){
                    DnsServerResponse resp = dns.Query(host,DNS_QType.A);
                    if(resp.ResponseCode == DNS_RCode.NO_ERROR){
                        DNS_rr_A[] records = resp.GetARecords();
                        IPAddress[] retVal = new IPAddress[records.Length];
                        for(int i=0;i<records.Length;i++){
                            retVal[i] = records[i].IP;
                        }

                        return retVal;
                    }
                    else{
                        throw new Exception(resp.ResponseCode.ToString());
                    }
                }
            }
        }
Exemple #4
0
            /// <summary>
            /// Starts looking up MX records for specified domain.
            /// </summary>
            /// <param name="dnsClient">DNS client.</param>
            /// <param name="domain">Domain name.</param>
            /// <param name="domainIsCName">If true domain name is CNAME(alias).</param>
            /// <exception cref="ArgumentNullException">Is riased when <b>dnsClient</b> or <b>domain</b> is null reference.</exception>
            private void LookupMX(Dns_Client dnsClient,string domain,bool domainIsCName)
            {
                if(dnsClient == null){
                    throw new ArgumentNullException("dnsClient");
                }
                if(domain == null){
                    throw new ArgumentNullException("domain");
                }

                // Try to get MX records.
                DNS_ClientTransaction transaction_MX = dnsClient.CreateTransaction(DNS_QType.MX,domain,2000);
                transaction_MX.StateChanged += delegate(object s1,EventArgs<DNS_ClientTransaction> e1){
                    try{
                        if(e1.Value.State == DNS_ClientTransactionState.Completed){
                            // No errors.
                            if(e1.Value.Response.ResponseCode == DNS_RCode.NO_ERROR){
                                List<DNS_rr_MX> mxRecords = new List<DNS_rr_MX>();
                                foreach(DNS_rr_MX mx in e1.Value.Response.GetMXRecords()){
                                    // Skip invalid MX records.
                                    if(string.IsNullOrEmpty(mx.Host)){
                                    }
                                    else{
                                        mxRecords.Add(mx);
                                    }
                                }

                                // Use MX records.
                                if(mxRecords.Count > 0){
                                    m_pHosts = new HostEntry[mxRecords.Count];

                                    // Create name to index map, so we can map asynchronous A/AAAA lookup results back to MX priority index.
                                    Dictionary<string,int> name_to_index_map = new Dictionary<string,int>();
                                    List<string>           lookupQueue       = new List<string>();

                                    // Process MX records.
                                    for(int i=0;i<m_pHosts.Length;i++){
                                        DNS_rr_MX mx = mxRecords[i];

                                        IPAddress[] ips = Get_A_or_AAAA_FromResponse(mx.Host,e1.Value.Response);
                                        // No A or AAAA records in addtional answers section for MX, we need todo new query for that.
                                        if(ips.Length == 0){
                                            name_to_index_map[mx.Host] = i;
                                            lookupQueue.Add(mx.Host);
                                        }
                                        else{
                                            m_pHosts[i] = new HostEntry(mx.Host,ips,null);
                                        }
                                    }

                                    // We have MX records which A or AAAA records not provided in DNS response, lookup them.
                                    if(lookupQueue.Count > 0){
                                        GetHostsAddressesAsyncOP op = new GetHostsAddressesAsyncOP(lookupQueue.ToArray(),true);
                                        // This event is raised when lookup completes asynchronously.
                                        op.CompletedAsync += delegate(object s2,EventArgs<GetHostsAddressesAsyncOP> e2){
                                            LookupCompleted(op,name_to_index_map);
                                        };
                                        // Lookup completed synchronously.
                                        if(!dnsClient.GetHostsAddressesAsync(op)){
                                            LookupCompleted(op,name_to_index_map);
                                        }
                                    }
                                    // All MX records resolved.
                                    else{
                                        SetState(AsyncOP_State.Completed);
                                    }
                                }
                                // Use CNAME as initial domain name.
                                else if(e1.Value.Response.GetCNAMERecords().Length > 0){
                                    if(domainIsCName){
                                        m_pException = new Exception("CNAME to CNAME loop dedected.");
                                        SetState(AsyncOP_State.Completed);
                                    }
                                    else{
                                        LookupMX(dnsClient,e1.Value.Response.GetCNAMERecords()[0].Alias,true);
                                    }
                                }
                                // Use domain name as MX.
                                else{
                                    m_pHosts = new HostEntry[1];

                                    // Create name to index map, so we can map asynchronous A/AAAA lookup results back to MX priority index.
                                    Dictionary<string,int> name_to_index_map = new Dictionary<string,int>();
                                    name_to_index_map.Add(domain,0);

                                    GetHostsAddressesAsyncOP op = new GetHostsAddressesAsyncOP(new string[]{domain});
                                    // This event is raised when lookup completes asynchronously.
                                    op.CompletedAsync += delegate(object s2,EventArgs<GetHostsAddressesAsyncOP> e2){
                                        LookupCompleted(op,name_to_index_map);
                                    };
                                    // Lookup completed synchronously.
                                    if(!dnsClient.GetHostsAddressesAsync(op)){
                                        LookupCompleted(op,name_to_index_map);
                                    }
                                }
                            }
                            // DNS server returned error, just return error.
                            else{
                                m_pException = new DNS_ClientException(e1.Value.Response.ResponseCode);
                                SetState(AsyncOP_State.Completed);
                            }
                        }
                        transaction_MX.Timeout += delegate(object s2,EventArgs e2){
                            m_pException = new IOException("DNS transaction timeout, no response from DNS server.");
                            SetState(AsyncOP_State.Completed);
                        };
                    }
                    catch(Exception x){
                        m_pException = x;
                        SetState(AsyncOP_State.Completed);
                    }
                };
                transaction_MX.Start();
            }
Exemple #5
0
            /// <summary>
            /// Starts operation processing.
            /// </summary>
            /// <param name="dnsClient">DNS client.</param>
            /// <returns>Returns true if asynchronous operation in progress or false if operation completed synchronously.</returns>
            /// <exception cref="ArgumentNullException">Is raised when <b>dnsClient</b> is null reference.</exception>
            internal bool Start(Dns_Client dnsClient)
            {
                if(dnsClient == null){
                    throw new ArgumentNullException("dnsClient");
                }

                SetState(AsyncOP_State.Active);

                /* RFC 5321 5.
                    The lookup first attempts to locate an MX record associated with the
                    name.  If a CNAME record is found, the resulting name is processed as
                    if it were the initial name.

                    If no MX records are found, but an A RR is found, the A RR is treated as if it
                    was associated with an implicit MX RR, with a preference of 0, pointing to that host.
                */

                try{
                    LookupMX(dnsClient,m_Domain,false);
                }
                catch(Exception x){
                    m_pException = x;
                    SetState(AsyncOP_State.Completed);
                }

                // Set flag rise CompletedAsync event flag. The event is raised when async op completes.
                // If already completed sync, that flag has no effect.
                lock(m_pLock){
                    m_RiseCompleted = true;

                    return m_State == AsyncOP_State.Active;
                }
            }
Exemple #6
0
        /// <summary>
        /// Is called when smart hosts ip addresses resolve operation has completed.
        /// </summary>
        /// <param name="op">Asynchronous operation.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>op</b> is null reference.</exception>
        private void SmartHostsResolveCompleted(Dns_Client.GetHostsAddressesAsyncOP op)
        {
            if(op == null){
                throw new ArgumentNullException("op");
            }

            if(op.Error != null){
                LogText("Failed to resolve relay smart host(s) ip addresses with error: " + op.Error.Message + ".");

                Dispose(op.Error);
            }
            else{
                for(int i=0;i<op.HostEntries.Length;i++){
                    Relay_SmartHost smartHost = m_pSmartHosts[i];

                    foreach(IPAddress ip in op.HostEntries[i].Addresses){
                        m_pTargets.Add(new Relay_Target(smartHost.Host,new IPEndPoint(ip,smartHost.Port),smartHost.SslMode,smartHost.UserName,smartHost.Password));
                    }
                }

                BeginConnect();
            }

            op.Dispose();
        }
Exemple #7
0
        /// <summary>
        /// Is called when email domain target servers resolve operation has completed.
        /// </summary>
        /// <param name="to">RCPT TO: address.</param>
        /// <param name="op">Asynchronous operation.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>to</b> or <b>op</b> is null reference.</exception>
        private void EmailHostsResolveCompleted(string to,Dns_Client.GetEmailHostsAsyncOP op)
        {
            if(to == null){
                throw new ArgumentNullException("to");
            }
            if(op == null){
                throw new ArgumentNullException("op");
            }

            if(op.Error != null){
                LogText("Failed to resolve email domain for email address '" + to + "' with error: " + op.Error.Message + ".");

                Dispose(op.Error);
            }
            else{
                StringBuilder buf = new StringBuilder();
                foreach(HostEntry host in op.Hosts){
                    foreach(IPAddress ip in host.Addresses){
                        m_pTargets.Add(new Relay_Target(host.HostName,new IPEndPoint(ip,25)));
                    }
                    buf.Append(host.HostName + " ");
                }
                LogText("Resolved to following email hosts: (" + buf.ToString().TrimEnd() + ").");

                BeginConnect();
            }

            op.Dispose();
        }
Exemple #8
0
        /// <summary>
        /// Gets host name. If fails returns ip address.
        /// </summary>
        /// <param name="ip">IP address which to reverse lookup.</param>
        /// <returns>Returns host name of specified IP address.</returns>
        /// <exception cref="ArgumentNullException">Is raised when <b>ip</b> is null.</exception>
        public static string GetHostName(IPAddress ip)
        {
            if(ip == null){
                throw new ArgumentNullException("ip");
            }

            string retVal = ip.ToString();
            try{
                Dns_Client dns = new Dns_Client();
                DnsServerResponse response = dns.Query(ip.ToString(),DNS_QType.PTR);
                if(response.ResponseCode == DNS_RCode.NO_ERROR){
                    DNS_rr_PTR[] ptrs = response.GetPTRRecords();
                    if(ptrs.Length > 0){
                        retVal = ptrs[0].DomainName;
                    }
                }
            }
            catch{
            }

            return retVal;
        }
Exemple #9
0
 /// <summary>
 /// Default constructor.
 /// </summary>
 public Relay_Server()
 {
     m_pQueues     = new List<Relay_Queue>();
     m_pSmartHosts = new CircleCollection<Relay_SmartHost>();
     m_pDsnClient  = new Dns_Client();
 }