示例#1
0
        /// <summary>
        /// Shorthand form to make MX querying easier, essentially wraps up the retreival
        /// of the MX records, and sorts them by preference
        /// </summary>
        /// <param name="domain">domain name to retreive MX RRs for</param>
        /// <param name="port">the port number used by the domain name server.</param>
        /// <param name="ipAddress">the ip address of the domain name server.</param>
        /// <param name="protocolType">the protocol type used by the domain name server.</param>
        /// <param name="useIPv4EndPoint">use only an IPv4 connection and disregard all other address families (IPv6).</param>
        /// <returns>An array of MXRecords</returns>
        internal MXRecord[] MXLookup(string domain, int port,
                                     string ipAddress, Nequeo.Net.Dns.ProtocolType protocolType, bool useIPv4EndPoint)
        {
            // check the inputs
            if (domain == null)
            {
                throw new ArgumentNullException("domain");
            }
            if (port < 1)
            {
                throw new IndexOutOfRangeException("port");
            }

            // create a request for this
            Request request = new Request();

            // add one question - the MX IN lookup for the supplied domain
            request.AddQuestion(new Question(domain, Nequeo.Net.Dns.DnsType.MX, Nequeo.Net.Dns.DnsClass.IN));

            // fire it off
            Response response = Lookup(request, domain, port, ipAddress, protocolType, useIPv4EndPoint);

            // if we didn't get a response, then return null
            if (response == null)
            {
                return(null);
            }

            // create a growable array of MX records
            ArrayList resourceRecords = new ArrayList();

            // add each of the answers to the array
            foreach (Answer answer in response.Answers)
            {
                // if the answer is an MX record
                if (answer.Record.GetType() == typeof(MXRecord))
                {
                    // add it to our array
                    resourceRecords.Add(answer.Record);
                }
            }

            // create array of MX records
            MXRecord[] mxRecords = new MXRecord[resourceRecords.Count];

            // copy from the array list
            resourceRecords.CopyTo(mxRecords);

            // sort into lowest preference order
            Array.Sort(mxRecords);

            // and return
            return(mxRecords);
        }
示例#2
0
        /// <summary>
        /// The principal look up function, which sends a request message to the given
        /// DNS server and collects a response. This implementation re-sends the message
        /// via UDP up to two times in the event of no response/packet loss
        /// </summary>
        /// <param name="request">The logical request to send to the server</param>
        /// <param name="domain">domain name to retreive MX RRs for</param>
        /// <param name="port">the port number used by the domain name server.</param>
        /// <param name="ipAddress">the ip address of the domain name server.</param>
        /// <param name="protocolType">the protocol type used by the domain name server.</param>
        /// <param name="useIPv4EndPoint">use only an IPv4 connection and disregard all other address families (IPv6).</param>
        /// <returns>The logical response from the DNS server or null if no response</returns>
        internal Response Lookup(Request request, string domain, int port,
                                 string ipAddress, Nequeo.Net.Dns.ProtocolType protocolType, bool useIPv4EndPoint)
        {
            // check the inputs
            if (request == null)
            {
                throw new ArgumentNullException("request");
            }
            if (port < 1)
            {
                throw new IndexOutOfRangeException("port");
            }

            // get the message
            byte[] requestMessage = request.GetMessage();

            // send the request and get the response
            byte[] responseMessage = Transfer(domain, port, ipAddress, protocolType, requestMessage, useIPv4EndPoint);

            string ff = Encoding.ASCII.GetString(responseMessage);

            // and populate a response object from that and return it
            return(new Response(responseMessage));
        }
示例#3
0
        /// <summary>
        /// Get the client connection socket.
        /// </summary>
        /// <param name="ipAddress">the ip address of the domain name server.</param>
        /// <param name="port">the port number used by the domain name server.</param>
        /// <param name="protocolType">the protocol type used by the domain name server.</param>
        /// <param name="useIPv4EndPoint">use only an IPv4 connection and disregard all other address families (IPv6).</param>
        /// <returns>The client connection socket.</returns>
        private Socket GetSocket(string ipAddress, int port,
                                 Nequeo.Net.Dns.ProtocolType protocolType, bool useIPv4EndPoint)
        {
            Socket socket = null;

            try
            {
                IPHostEntry hostEntry = null;

                // Get host related information.
                hostEntry = System.Net.Dns.GetHostEntry(ipAddress);

                // Loop through the AddressList to obtain the supported
                // AddressFamily. This is to avoid an exception that
                // occurs when the host IP Address is not compatible
                // with the address family
                // (typical in the IPv6 case).
                foreach (IPAddress address in hostEntry.AddressList)
                {
                    // If the connection used should only be IPv4.
                    if (useIPv4EndPoint && address.AddressFamily == AddressFamily.InterNetworkV6)
                    {
                        continue;
                    }

                    // Get the current server endpoint for
                    // the current address.
                    IPEndPoint endPoint   = new IPEndPoint(address, port);
                    Socket     tempSocket = null;

                    // Get the current socket type.
                    switch (protocolType)
                    {
                    case Nequeo.Net.Dns.ProtocolType.Tcp:
                        // Create a new client socket for the
                        // current endpoint.
                        tempSocket = new Socket(endPoint.AddressFamily,
                                                SocketType.Dgram, System.Net.Sockets.ProtocolType.Tcp);
                        break;

                    case Nequeo.Net.Dns.ProtocolType.Udp:
                        // Create a new client socket for the
                        // current endpoint.
                        tempSocket = new Socket(endPoint.AddressFamily,
                                                SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp);
                        break;
                    }

                    // Connect to the server with the
                    // current end point.
                    try
                    {
                        tempSocket.Connect(endPoint);
                    }
                    catch { }

                    // If this connection succeeded then
                    // asiign the client socket and
                    // break put of the loop.
                    if (tempSocket.Connected)
                    {
                        // A client connection has been found.
                        // Break out of the loop.
                        socket = tempSocket;
                        break;
                    }
                    else
                    {
                        continue;
                    }
                }

                // Return the client socket.
                return(socket);
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
        }
示例#4
0
        /// <summary>
        /// Gets the bytes of data from the domain name server socket connection.
        /// </summary>
        /// <param name="domain">domain name to retreive MX RRs for</param>
        /// <param name="port">the port number used by the domain name server.</param>
        /// <param name="ipAddress">the ip address of the domain name server.</param>
        /// <param name="protocolType">the protocol type used by the domain name server.</param>
        /// <param name="useIPv4EndPoint">use only an IPv4 connection and disregard all other address families (IPv6).</param>
        /// <param name="requestMessage"></param>
        /// <returns>The bytes received from the domain name server.</returns>
        private byte[] Transfer(string domain, int port, string ipAddress,
                                Nequeo.Net.Dns.ProtocolType protocolType, byte[] requestMessage, bool useIPv4EndPoint)
        {
            // UDP can fail - if it does try again keeping track of how many attempts we've made
            int attempts = 0;

            // try repeatedly in case of failure
            while (attempts <= _udpRetryAttempts)
            {
                // firstly, uniquely mark this request with an id
                unchecked
                {
                    // substitute in an id unique to this lookup, the request has no idea about this
                    requestMessage[0] = (byte)(_uniqueId >> 8);
                    requestMessage[1] = (byte)_uniqueId;
                }

                // we'll be send and receiving a UDP packet
                Socket socket = GetSocket(ipAddress, port, protocolType, useIPv4EndPoint);

                // we will wait at most 10 second for a dns reply
                socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 10000);

                // send it off to the server
                socket.Send(requestMessage, requestMessage.Length, SocketFlags.None);


                // RFC1035 states that the maximum size of a UDP datagram is 512 octets (bytes)
                byte[] responseMessage = new byte[512];

                try
                {
                    // wait for a response upto 10 second
                    socket.Receive(responseMessage);

                    // make sure the message returned is ours
                    if (responseMessage[0] == requestMessage[0] &&
                        responseMessage[1] == requestMessage[1])
                    {
                        // its a valid response - return it, this is our successful exit point
                        return(responseMessage);
                    }
                }
                catch (SocketException)
                {
                    // failure - we better try again, but remember how many attempts
                    attempts++;
                }
                finally
                {
                    // increase the unique id
                    _uniqueId++;

                    // close the socket
                    socket.Close();
                }
            }

            // the operation has failed, this is our unsuccessful exit point
            throw new Exception("A connection could not be establised. " +
                                "The server may have actively refused the request.");
        }