/// <summary> /// Processes DNS server response through this transaction. /// </summary> /// <param name="response">DNS server response.</param> /// <exception cref="ArgumentNullException">Is raised when <b>response</b> is null reference.</exception> internal void ProcessResponse(DnsServerResponse response) { if (response == null) { throw new ArgumentNullException("response"); } m_pResponse = response; OnCompleted(); }
/// <summary> /// Cleans up any resource being used. /// </summary> public void Dispose() { m_pTimeoutTimer.Dispose(); m_pTimeoutTimer = null; m_pOwner.m_pTransactions.Remove(this.ID); m_pOwner = null; m_pQuery = null; m_pResponse = null; this.Timeout = null; this.Completed = null; }
/// <summary> /// Sends query to server. /// </summary> /// <param name="timeout">Query timeout in milli seconds.</param> /// <param name="qname">Query text.</param> /// <param name="qtype">Query type.</param> /// <param name="qclass">Query class.</param> /// <returns>Returns DNS server response.</returns> private DnsServerResponse QueryServer(int timeout, string qname, QTYPE qtype, int qclass) { if (m_DnsServers == null || m_DnsServers.Length == 0) { throw new Exception("Dns server isn't specified !"); } // See if query is in cache if (m_UseDnsCache) { DnsServerResponse resopnse = DnsCache.GetFromCache(qname, (int)qtype); if (resopnse != null) { return(resopnse); } } int queryID = Dns_Client.ID; byte[] query = CreateQuery(queryID, qname, qtype, qclass); // Create transcation and start processing it. using (DnsTransaction transaction = new DnsTransaction(this, queryID, qname, (int)qtype, timeout, query)){ ManualResetEvent wait = new ManualResetEvent(false); transaction.Timeout += delegate(object s, EventArgs e){ wait.Set(); }; transaction.Completed += delegate(object s, EventArgs e){ wait.Set(); }; m_pTransactions.Add(transaction.ID, transaction); // Start transaction processing and wait transaction to complete. transaction.Start(); wait.WaitOne(); // DNS server response received. if (transaction.Response != null) { return(transaction.Response); } // No server response - timeout. else { throw new Exception("Timeout - no response from DNS server."); } } }
/// <summary> /// Adds dns records to cache. If old entry exists, it is replaced. /// </summary> /// <param name="qname"></param> /// <param name="qtype"></param> /// <param name="answers"></param> public static void AddToCache(string qname, int qtype, DnsServerResponse answers) { if (answers == null) { return; } try{ lock (m_pCache){ // Remove old cache entry, if any. if (m_pCache.Contains(qname + qtype)) { m_pCache.Remove(qname + qtype); } m_pCache.Add(qname + qtype, new DnsCacheEntry(answers, DateTime.Now)); } } catch { } }
/// <summary> /// Resolves host name to IP addresses. /// </summary> /// <param name="host">Host name or IP address.</param> /// <returns>Return specified host IP addresses.</returns> /// <exception cref="ArgumentNullException">Is raised when <b>host</b> is null.</exception> 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 Dns_Client dns = new Dns_Client(); DnsServerResponse resp = dns.Query(host, QTYPE.A); if (resp.ResponseCode == 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()); } } }
/// <summary> /// Gets specified host IP addresses(A and AAAA). /// </summary> /// <param name="host">Host name.</param> /// <returns>Returns specified host IP addresses.</returns> /// <exception cref="ArgumentNullException">Is raised when <b>host</b> is null reference.</exception> public IPAddress[] GetHostAddresses(string host) { if (host == null) { throw new ArgumentNullException("host"); } List <IPAddress> retVal = new List <IPAddress>(); // This is probably NetBios name if (host.IndexOf(".") == -1) { return(System.Net.Dns.GetHostEntry(host).AddressList); } else { DnsServerResponse response = Query(host, QTYPE.A); if (response.ResponseCode != RCODE.NO_ERROR) { throw new DNS_ClientException(response.ResponseCode); } foreach (DNS_rr_A record in response.GetARecords()) { retVal.Add(record.IP); } response = Query(host, QTYPE.AAAA); if (response.ResponseCode != RCODE.NO_ERROR) { throw new DNS_ClientException(response.ResponseCode); } foreach (DNS_rr_AAAA record in response.GetAAAARecords()) { retVal.Add(record.IP); } } return(retVal.ToArray()); }
/// <summary> /// Is called when IPv6 socket has received data. /// </summary> /// <param name="ar">The result of the asynchronous operation.</param> private void IPv6ReceiveCompleted(IAsyncResult ar) { try{ if (m_IsDisposed) { return; } EndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0); int count = m_pIPv6Socket.EndReceiveFrom(ar, ref remoteEP); DnsServerResponse serverResponse = ParseQuery((byte[])ar.AsyncState); DnsTransaction transaction = null; // Pass response to transaction. if (m_pTransactions.TryGetValue(serverResponse.ID, out transaction)) { transaction.ProcessResponse(serverResponse); } // No such transaction or transaction has timed out before answer received. //else{ //} // Cache query. if (m_UseDnsCache && serverResponse.ResponseCode == RCODE.NO_ERROR) { DnsCache.AddToCache(transaction.QName, transaction.QType, serverResponse); } } catch { // Skip receiving socket errors. } try{ StartWaitingIPv6Packet(); } catch { } }
/// <summary> /// Default constructor. /// </summary> /// <param name="answers">Dns answers.</param> /// <param name="addTime">Entry add time.</param> public DnsCacheEntry(DnsServerResponse answers,DateTime addTime) { m_pResponse = answers; m_Time = addTime; }
/// <summary> /// Adds dns records to cache. If old entry exists, it is replaced. /// </summary> /// <param name="qname"></param> /// <param name="qtype"></param> /// <param name="answers"></param> public static void AddToCache(string qname,int qtype,DnsServerResponse answers) { if(answers == null){ return; } try{ lock(m_pCache){ // Remove old cache entry, if any. if(m_pCache.Contains(qname + qtype)){ m_pCache.Remove(qname + qtype); } m_pCache.Add(qname + qtype,new DnsCacheEntry(answers,DateTime.Now)); } } catch{ } }
/// <summary> /// Default constructor. /// </summary> /// <param name="answers">Dns answers.</param> /// <param name="addTime">Entry add time.</param> public DnsCacheEntry(DnsServerResponse answers, DateTime addTime) { m_pResponse = answers; m_Time = addTime; }
/// <summary> /// Sends query to server. /// </summary> /// <param name="timeout">Query timeout in milli seconds.</param> /// <param name="qname">Query text.</param> /// <param name="qtype">Query type.</param> /// <param name="qclass">Query class.</param> /// <returns></returns> private DnsServerResponse QueryServer(int timeout, string qname, QTYPE qtype, int qclass) { if (m_DnsServers == null || m_DnsServers.Length == 0) { throw new Exception("Dns server isn't specified !"); } // See if query is in cache if (m_UseDnsCache) { DnsServerResponse resopnse = DnsCache.GetFromCache(qname, (int)qtype); if (resopnse != null) { return(resopnse); } } int queryID = Dns_Client.ID; byte[] query = CreateQuery(queryID, qname, qtype, qclass); // Create sending UDP socket. Socket udpClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); udpClient.SendTimeout = 500; // Send parallel query to all dns servers and get first answer. DateTime startTime = DateTime.Now; while (startTime.AddMilliseconds(timeout) > DateTime.Now) { foreach (IPAddress dnsServer in m_DnsServers) { try{ udpClient.SendTo(query, new IPEndPoint(dnsServer, 53)); } catch { } } // Wait 10 ms response to arrive, if no response, retransmit query. if (udpClient.Poll(10, SelectMode.SelectRead)) { try{ byte[] retVal = new byte[1024]; int countRecieved = udpClient.Receive(retVal); // If reply is ok, return it DnsServerResponse serverResponse = ParseQuery(retVal, queryID); // Cache query if (m_UseDnsCache && serverResponse.ResponseCode == RCODE.NO_ERROR) { DnsCache.AddToCache(qname, (int)qtype, serverResponse); } return(serverResponse); } catch { } } } udpClient.Close(); // If we reach so far, we probably won't get connection to dsn server return(new DnsServerResponse(false, RCODE.SERVER_FAILURE, new List <DNS_rr_base>(), new List <DNS_rr_base>(), new List <DNS_rr_base>())); }