DNS.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / whidbey / REDBITS / ndp / fx / src / Net / System / Net / DNS.cs / 1 / DNS.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

 
namespace System.Net { 
    using System.Text;
    using System.Collections; 
    using System.Net.Sockets;
    using System.Runtime.InteropServices;
    using System.Security.Permissions;
    using System.Threading; 
    using System.Security;
    using System.Globalization; 
 
    /// 
    ///    Provides simple 
    ///       domain name resolution functionality.
    /// 

    public static class Dns 
    {
        // 
        // used by GetHostName() to preallocate a buffer for the call to gethostname. 
        //
        private const int HostNameBufferLength = 256; 

        //also used as a lock object
        private static DnsPermission s_DnsPermission = new DnsPermission(PermissionState.Unrestricted);
        // 
        // 
        // ws2_32!gethostbyname does not check the size of the hostname before passing the 
        // buffer down, this causes a heap corruption. we need to check before calling into 
        // ws2_32!gethostbyname.
        // 
        private const int MaxHostName = 126;


        /*++ 

        Routine Description: 
 
            Takes a native pointer (expressed as an int) to a hostent structure,
            and converts the information in their to an IPHostEntry class. This 
            involves walking through an array of native pointers, and a temporary
            ArrayList object is used in doing this.

        Arguments: 

            nativePointer   - Native pointer to hostent structure. 
 

 
        Return Value:

            An IPHostEntry structure.
 
        --*/
 
#if !FEATURE_PAL 
        private static IPHostEntry NativeToHostEntry(IntPtr nativePointer) {
#else 
        internal static IPHostEntry NativeToHostEntry(IntPtr nativePointer) {
#endif
            //
            // marshal pointer to struct 
            //
 
            hostent Host = (hostent)Marshal.PtrToStructure(nativePointer, typeof(hostent)); 
            IPHostEntry HostEntry = new IPHostEntry();
 
            if (Host.h_name != IntPtr.Zero) {
                HostEntry.HostName = Marshal.PtrToStringAnsi(Host.h_name);
                GlobalLog.Print("HostEntry.HostName: " + HostEntry.HostName);
            } 

            // decode h_addr_list to ArrayList of IP addresses. 
            // The h_addr_list field is really a pointer to an array of pointers 
            // to IP addresses. Loop through the array, and while the pointer
            // isn't NULL read the IP address, convert it to an IPAddress class, 
            // and add it to the list.

            ArrayList TempList = new ArrayList();
            int IPAddressToAdd; 
            string AliasToAdd;
            IntPtr currentArrayElement; 
 
            //
            // get the first pointer in the array 
            //
            currentArrayElement = Host.h_addr_list;
            nativePointer = Marshal.ReadIntPtr(currentArrayElement);
 
            while (nativePointer != IntPtr.Zero) {
                // 
                // if it's not null it points to an IPAddress, 
                // read it...
                // 
                IPAddressToAdd = Marshal.ReadInt32(nativePointer);
#if BIGENDIAN
                // IP addresses from native code are always a byte array
                // converted to int.  We need to convert the address into 
                // a uniform integer value.
                IPAddressToAdd = (int)( ((uint)IPAddressToAdd << 24) | 
                                        (((uint)IPAddressToAdd & 0x0000FF00) << 8) | 
                                        (((uint)IPAddressToAdd >> 8) & 0x0000FF00) |
                                        ((uint)IPAddressToAdd >> 24) ); 
#endif

                GlobalLog.Print("currentArrayElement: " + currentArrayElement.ToString() + " nativePointer: " + nativePointer.ToString() + " IPAddressToAdd:" + IPAddressToAdd.ToString());
 
                //
                // ...and add it to the list 
                // 
                TempList.Add(new IPAddress(IPAddressToAdd));
 
                //
                // now get the next pointer in the array and start over
                //
                currentArrayElement = IntPtrHelper.Add(currentArrayElement, IntPtr.Size); 
                nativePointer = Marshal.ReadIntPtr(currentArrayElement);
            } 
 
            HostEntry.AddressList = new IPAddress[TempList.Count];
            TempList.CopyTo(HostEntry.AddressList, 0); 

            //
            // Now do the same thing for the aliases.
            // 

            TempList.Clear(); 
 
            currentArrayElement = Host.h_aliases;
            nativePointer = Marshal.ReadIntPtr(currentArrayElement); 

            while (nativePointer != IntPtr.Zero) {

                GlobalLog.Print("currentArrayElement: " + ((long)currentArrayElement).ToString() + "nativePointer: " + ((long)nativePointer).ToString()); 

                // 
                // if it's not null it points to an Alias, 
                // read it...
                // 
                AliasToAdd = Marshal.PtrToStringAnsi(nativePointer);

                //
                // ...and add it to the list 
                //
                TempList.Add(AliasToAdd); 
 
                //
                // now get the next pointer in the array and start over 
                //
                currentArrayElement = IntPtrHelper.Add(currentArrayElement, IntPtr.Size);
                nativePointer = Marshal.ReadIntPtr(currentArrayElement);
 
            }
 
            HostEntry.Aliases = new string[TempList.Count]; 
            TempList.CopyTo(HostEntry.Aliases, 0);
 
            return HostEntry;

        } // NativeToHostEntry
 
        /*****************************************************************************
         Function :    gethostbyname 
 
         Abstract:     Queries DNS for hostname address
 
         Input Parameters: str (String to query)

         Returns: Void
        ******************************************************************************/ 

        ///  
        /// Retrieves the  
        /// information
        /// corresponding to the DNS name provided in the host 
        /// parameter.
        /// 

 
        [Obsolete("GetHostByName is obsoleted for this type, please use GetHostEntry instead. http://go.microsoft.com/fwlink/?linkid=14202")]
        public static IPHostEntry GetHostByName(string hostName) { 
            if (hostName == null) { 
                throw new ArgumentNullException("hostName");
            } 
            //
            // demand Unrestricted DnsPermission for this call
            //
            s_DnsPermission.Demand(); 
            return InternalGetHostByName(hostName, false);
        } 
        // 

 
        internal static IPHostEntry InternalGetHostByName(string hostName) {
            return InternalGetHostByName(hostName,true);
        }
 
        internal static IPHostEntry InternalGetHostByName(string hostName, bool includeIPv6) {
            if(Logging.On)Logging.Enter(Logging.Sockets, "DNS", "GetHostByName", hostName); 
            IPHostEntry ipHostEntry = null; 

            GlobalLog.Print("Dns.GetHostByName: " + hostName); 

            if (hostName.Length>MaxHostName) {
                throw new ArgumentOutOfRangeException(SR.GetString(SR.net_toolong, "hostName", MaxHostName.ToString(NumberFormatInfo.CurrentInfo)));
            } 

            // 
            // IPv6 Changes: IPv6 requires the use of getaddrinfo() rather 
            //               than the traditional IPv4 gethostbyaddr() / gethostbyname().
            //               getaddrinfo() is also protocol independant in that it will also 
            //               resolve IPv4 names / addresses. As a result, it is the preferred
            //               resolution mechanism on platforms that support it (Windows 5.1+).
            //               If getaddrinfo() is unsupported, IPv6 resolution does not work.
            // 
            // Consider    : If IPv6 is disabled, we could detect IPv6 addresses
            //               and throw an unsupported platform exception. 
            // 
            // Note        : Whilst getaddrinfo is available on WinXP+, we only
            //               use it if IPv6 is enabled (platform is part of that 
            //               decision). This is done to minimize the number of
            //               possible tests that are needed.
            //
            if ( Socket.LegacySupportsIPv6 || (includeIPv6 && ComNetOS.IsPostWin2K)) { 
                //
                // IPv6 enabled: use getaddrinfo() to obtain DNS information. 
                // 
                ipHostEntry = Dns.GetAddrInfo(hostName);
            } 
            else {
                //
                // IPv6 disabled: use gethostbyname() to obtain DNS information.
                // 
                IntPtr nativePointer =
                    UnsafeNclNativeMethods.OSSOCK.gethostbyname( 
                        hostName); 

                if (nativePointer == IntPtr.Zero) { 
                    // This is for compatiblity with NT4/Win2k
                    // Need to do this first since if we wait the last error code might be overwritten.
                    SocketException socketException = new SocketException();
 
                    //This block supresses "unknown error" on NT4 when input is
                    //arbitrary IP address. It simulates same result as on Win2K. 
                    // For Everett compat, we allow this to parse and return IPv6 even when it's disabled. 
                    IPAddress address;
                    if (IPAddress.TryParse(hostName, out address)) 
                    {
                        ipHostEntry = new IPHostEntry();
                        ipHostEntry.HostName = address.ToString();
                        ipHostEntry.Aliases = new string[0]; 
                        ipHostEntry.AddressList = new IPAddress[] { address };
                        if(Logging.On)Logging.Exit(Logging.Sockets, "DNS", "GetHostByName", ipHostEntry); 
                        return ipHostEntry; 
                    }
 
                    throw socketException;
                }
                ipHostEntry = NativeToHostEntry(nativePointer);
            } 

            if(Logging.On)Logging.Exit(Logging.Sockets, "DNS", "GetHostByName", ipHostEntry); 
            return ipHostEntry; 

        } // GetHostByName 



        /***************************************************************************** 
         Function :    gethostbyaddr
 
         Abstract:     Queries IP address string and tries to match with a host name 

         Input Parameters: str (String to query) 

         Returns: IPHostEntry
        ******************************************************************************/
 
        /// 
        /// Creates an  
        /// instance from an IP dotted address. 
        /// 
 
        [Obsolete("GetHostByAddress is obsoleted for this type, please use GetHostEntry instead. http://go.microsoft.com/fwlink/?linkid=14202")]
        public static IPHostEntry GetHostByAddress(string address) {
            if(Logging.On)Logging.Enter(Logging.Sockets, "DNS", "GetHostByAddress", address);
            // 
            // demand Unrestricted DnsPermission for this call
            // 
            s_DnsPermission.Demand(); 

            if (address == null) { 
                throw new ArgumentNullException("address");
            }

            GlobalLog.Print("Dns.GetHostByAddress: " + address); 

            IPHostEntry ipHostEntry = InternalGetHostByAddress(IPAddress.Parse(address), false, true); 
            if(Logging.On)Logging.Exit(Logging.Sockets, "DNS", "GetHostByAddress", ipHostEntry); 
            return ipHostEntry;
        } // GetHostByAddress 

        /******************************************************************************
         Function :    gethostbyaddr
 
         Abstract:     Queries IP address and tries to match with a host name
 
         Input Parameters: address (address to query) 

         Returns: IPHostEntry 
        ******************************************************************************/

        /// 
        /// Creates an  instance from an  
        /// instance.
        ///  
 
        [Obsolete("GetHostByAddress is obsoleted for this type, please use GetHostEntry instead. http://go.microsoft.com/fwlink/?linkid=14202")]
        public static IPHostEntry GetHostByAddress(IPAddress address) { 
            if(Logging.On)Logging.Enter(Logging.Sockets, "DNS", "GetHostByAddress", "");
            //
            // demand Unrestricted DnsPermission for this call
            // 
            s_DnsPermission.Demand();
 
            if (address == null) { 
                throw new ArgumentNullException("address");
            } 

            IPHostEntry ipHostEntry = InternalGetHostByAddress(address, false, true);
            if(Logging.On)Logging.Exit(Logging.Sockets, "DNS", "GetHostByAddress", ipHostEntry);
            return ipHostEntry; 
        } // GetHostByAddress
 
        internal static IPHostEntry InternalGetHostByAddress(IPAddress address, bool includeIPv6, bool throwOnFailure) 
        {
            GlobalLog.Print("Dns.InternalGetHostByAddress: " + address.ToString()); 
            //
            // IPv6 Changes: We need to use the new getnameinfo / getaddrinfo functions
            //               for resolution of IPv6 addresses.
            // 

            SocketError errorCode = SocketError.Success; 
            Exception exception = null; 
            if ( Socket.LegacySupportsIPv6 || (includeIPv6 && ComNetOS.IsPostWin2K)) {
                // 
                // Try to get the data for the host from it's address
                //
                // we need to call getnameinfo first, because getaddrinfo w/ the ipaddress string
                //will only return that address and not the full list. 

                string name = TryGetNameInfo(address,out errorCode); 
                if(errorCode == SocketError.Success){ 
                    return GetAddrInfo(name);   //presumably this is fast because of local caching
                } 
                exception = new SocketException();
            }

            // 
            // If IPv6 is not enabled (maybe config switch) but we've been
            // given an IPv6 address then we need to bail out now. 
            // 
            else {
                if ( address.AddressFamily == AddressFamily.InterNetworkV6 ) { 
                    //
                    // Protocol not supported
                    //
                    throw new SocketException(SocketError.ProtocolNotSupported); 
                }
                // 
                // Use gethostbyaddr() to try to resolve the IP address 
                //
                // End IPv6 Changes 
                //
                int addressAsInt = unchecked((int)address.m_Address);

    #if BIGENDIAN 
                addressAsInt = (int)( ((uint)addressAsInt << 24) | (((uint)addressAsInt & 0x0000FF00) << 8) |
                    (((uint)addressAsInt >> 8) & 0x0000FF00) | ((uint)addressAsInt >> 24) ); 
    #endif 

                IntPtr nativePointer = 
                    UnsafeNclNativeMethods.OSSOCK.gethostbyaddr(
                        ref addressAsInt,
                        Marshal.SizeOf(typeof(int)),
                        ProtocolFamily.InterNetwork); 

 
                if (nativePointer != IntPtr.Zero) { 
                    return NativeToHostEntry(nativePointer);
                } 
                exception = new SocketException();
            }

            if(throwOnFailure){ 
                throw exception;
            } 
 
            IPHostEntry ipHostEntry = new IPHostEntry();
 
            try{
                ipHostEntry.HostName    = address.ToString();
                ipHostEntry.Aliases     = new string[0];
                ipHostEntry.AddressList = new IPAddress[] { address }; 
            }
            catch{ 
                throw exception;   //throw the original exception 
            }
            return ipHostEntry; 
        } // InternalGetHostByAddress


        /***************************************************************************** 
         Function :    gethostname
 
         Abstract:     Queries the hostname from DNS 

         Input Parameters: 

         Returns: String
        ******************************************************************************/
 
        /// 
        ///    Gets the host name of the local machine. 
        ///  
        // UEUE: note that this method is not threadsafe!!
        public static string GetHostName() { 
            //
            // demand Unrestricted DnsPermission for this call
            //
            s_DnsPermission.Demand(); 

            GlobalLog.Print("Dns.GetHostName"); 
 
            //
            // note that we could cache the result ourselves since you 
            // wouldn't expect the hostname of the machine to change during
            // execution, but this might still happen and we would want to
            // react to that change.
            // 

            Socket.InitializeSockets(); 
            StringBuilder sb = new StringBuilder(HostNameBufferLength); 
            SocketError errorCode =
                UnsafeNclNativeMethods.OSSOCK.gethostname( 
                    sb,
                    HostNameBufferLength);

            // 
            // if the call failed throw a SocketException()
            // 
            if (errorCode!=SocketError.Success) { 
                throw new SocketException();
            } 
            return sb.ToString();
        }

 
        /******************************************************************************
         Function :    resolve 
 
         Abstract:     Converts IP/hostnames to IP numerical address using DNS
                       Additional methods provided for convenience 
                       (These methods will resolve strings and hostnames. In case of
                       multiple IP addresses, the address returned is chosen arbitrarily.)

         Input Parameters: host/IP 

         Returns: IPAddress 
        ******************************************************************************/ 

        ///  
        /// Creates an 
        /// instance from a DNS hostname.
        /// 
        // UEUE 

 
        [Obsolete("Resolve is obsoleted for this type, please use GetHostEntry instead. http://go.microsoft.com/fwlink/?linkid=14202")] 
        public static IPHostEntry Resolve(string hostName) {
            if(Logging.On)Logging.Enter(Logging.Sockets, "DNS", "Resolve", hostName); 
            //
            // demand Unrestricted DnsPermission for this call
            //
            s_DnsPermission.Demand(); 

            if (hostName == null) { 
                throw new ArgumentNullException("hostName"); 
            }
 
            // See if it's an IP Address.
            IPAddress address;
            IPHostEntry ipHostEntry;
 
            // Everett Compat (#497786).
            // Everett.Resolve() returns the IPv6 address, even when IPv6 is off.  Everett.GetHostByAddress() throws.  So 
            // if IPv6 is off and they passed one in, call InternalGetHostByName which (also for compat) just returns it. 
            if (TryParseAsIP(hostName, out address) && (address.AddressFamily != AddressFamily.InterNetworkV6 || Socket.LegacySupportsIPv6))
            { 
                ipHostEntry = InternalGetHostByAddress(address, false, false);
            }
            else
            { 
                ipHostEntry = InternalGetHostByName(hostName, false);
            } 
 
            if (Logging.On) Logging.Exit(Logging.Sockets, "DNS", "Resolve", ipHostEntry);
            return ipHostEntry; 
        }


        //Caution, this will return ipv6 addresses if the OS supports it.  This shouldn't be called by the public apis. 
        internal static IPHostEntry InternalResolveFast(string hostName, int timeout, out bool timedOut) {
            GlobalLog.Assert(hostName != null, "hostName == null"); 
            GlobalLog.Print("Dns.InternalResolveFase: " + hostName); 

            // 
            // the differences between this method and the previous InternalResolve() are:
            //
            // 1) we don't throw any exceptions
            // 2) we don't do a reverse lookup for address strings, we just use them 
            //
            // IPv6 Changes: It is not practical to embed the code for GetAddrInfo here, instead 
            //               we call it and catch any exceptions. 
            //
            // Timeout: Supports a timeout by offloading work to another thread if necessary. 
            //

            // We can't abort a DNS lookup so if we think might need to, run it on another thread.
            // According to MSDN the max time is 17 seconds.  Use 18 and say 20. 
            // Also: MSDN describes how one lookup can result in a string of queries.  It's unclear whether
            // those would be run in series, extending the possible time this will take, or whether it will always 
            // give up after 17 seconds.  For now assume that 17 seconds is the absolute max. 
            bool mightTimeOut = 18000 >= (uint) timeout && timeout != Timeout.Infinite;
            timedOut = false; 

            if (hostName.Length > 0 && hostName.Length <= MaxHostName)
            {
                // IP Address? 
                IPAddress address;
                if (TryParseAsIP(hostName, out address)) 
                { 
                    IPHostEntry ipHostEntry = new IPHostEntry();
                    ipHostEntry.HostName    = address.ToString(); 
                    ipHostEntry.Aliases     = new string[0];
                    ipHostEntry.AddressList = new IPAddress[] { address };

                    GlobalLog.Print("Dns::InternalResolveFast() returned address:" + address.ToString()); 
                    return ipHostEntry;
                } 
 
                // Looks like a hostname (or failed address parsing)
                if (Socket.OSSupportsIPv6) 
                {
                    try
                    {
                       // we will no longer offload to a thread, due to the consequence of having a threadpool thread 
                       //block on another threadpool thread.  In addition, even w/ the DNS server functioning, we run
                       // the risk of having too many of these queued up, causing requests to fail w/ an unable to resolve 
                       //exception. 

                       //I'm leaving the code commented out to possibly reuse in our async case. 

                       // if (!mightTimeOut)
                       // {
                            return GetAddrInfo(hostName); 
                       // }
                       /* else 
                        { 
                            AsyncDnsContext dnsContext = new AsyncDnsContext(hostName);
                            dnsContext.Offload(new WaitCallback(OffloadedGetAddrInfo)); 
                            return (IPHostEntry) dnsContext.Wait(timeout, out timedOut);
                        }
                        */
                    } 
                    catch ( Exception e )
                    { 
                        GlobalLog.Print("Dns::InternalResolveFast() GetAddrInfo() threw: " + e.Message); 
                    }
                } 
                else {
                    //
                    // we duplicate the code in GetHostByName() to avoid
                    // having to catch the thrown exception 
                    //
                    IntPtr nativePointer; 
                    //if (!mightTimeOut) 
                    //{
                        nativePointer = UnsafeNclNativeMethods.OSSOCK.gethostbyname(hostName); 
                    //}
                    /*
                    else
                    { 
                        AsyncDnsContext dnsContext = new AsyncDnsContext(hostName);
                        dnsContext.Offload(new WaitCallback(OffloadedGetHostByName)); 
                        object result = dnsContext.Wait(timeout, out timedOut); 
                        nativePointer = result == null ? IntPtr.Zero : (IntPtr) result;
                    } 
                    */
                    if (nativePointer != IntPtr.Zero) {
                        GlobalLog.Print("Dns::InternalResolveFast() gethostbyname() returned nativePointer:" + nativePointer.ToString());
                        return NativeToHostEntry(nativePointer); 
                    }
                } 
            } 

            GlobalLog.Print("Dns::InternalResolveFast() returning null"); 
            if(Logging.On)Logging.Exit(Logging.Sockets, "DNS", "InternalResolveFast", null);
            return null;
        }
 

        private static WaitCallback resolveCallback = new WaitCallback(ResolveCallback); 
 
        private class ResolveAsyncResult : ContextAwareResult
        { 
            internal ResolveAsyncResult(string hostName, object myObject, bool includeIPv6, object myState, AsyncCallback myCallBack) :
                base(myObject, myState, myCallBack)
            {
                this.hostName = hostName; 
                this.includeIPv6 = includeIPv6;
            } 
 

            internal ResolveAsyncResult(IPAddress address, object myObject, bool includeIPv6, object myState, AsyncCallback myCallBack) : 
                base(myObject, myState, myCallBack)
            {
                this.includeIPv6 = includeIPv6;
                this.address = address; 
            }
 
            internal readonly string hostName; 
            internal bool includeIPv6;
            internal IPAddress address; 
        }

        private static void ResolveCallback(object context)
        { 
            ResolveAsyncResult result = (ResolveAsyncResult)context;
            IPHostEntry hostEntry; 
            try 
            {
                if(result.address != null){ 
                    hostEntry = InternalGetHostByAddress(result.address, result.includeIPv6, false);
                }
                else{
                    hostEntry = InternalGetHostByName(result.hostName, result.includeIPv6); 
                }
            } 
            catch (Exception exception) 
            {
                if (exception is OutOfMemoryException || exception is ThreadAbortException || exception is StackOverflowException) 
                    throw;

                result.InvokeCallback(exception);
                return; 
            }
 
            result.InvokeCallback(hostEntry); 
        }
 

        // Helpers for async GetHostByName, ResolveToAddresses, and Resolve - they're almost identical

        private static IAsyncResult HostResolutionBeginHelper(string hostName, bool useGetHostByName, bool flowContext, bool includeIPv6, bool throwOnIPAny, AsyncCallback requestCallback, object state) 
        {
            // 
            // demand Unrestricted DnsPermission for this call 
            //
 
            s_DnsPermission.Demand();

            if (hostName == null) {
                throw new ArgumentNullException("hostName"); 
            }
 
            GlobalLog.Print("Dns.HostResolutionBeginHelper: " + hostName); 

            // See if it's an IP Address. 
            IPAddress address;
            ResolveAsyncResult asyncResult;
            if (TryParseAsIP(hostName, out address))
            { 
                if (throwOnIPAny && (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any)))
                { 
                    throw new ArgumentException(SR.GetString(SR.net_invalid_ip_addr), "hostNameOrAddress"); 
                }
 
                asyncResult = new ResolveAsyncResult(address, null, includeIPv6, state, requestCallback);

                if (useGetHostByName)
                { 
                    IPHostEntry hostEntry = new IPHostEntry();
                    hostEntry.AddressList = new IPAddress[] { address }; 
                    hostEntry.Aliases = new string[0]; 
                    hostEntry.HostName = address.ToString();
                    asyncResult.StartPostingAsyncOp(false); 
                    asyncResult.InvokeCallback(hostEntry);
                    asyncResult.FinishPostingAsyncOp();
                    return asyncResult;
                } 
            }
            else 
            { 
                asyncResult = new ResolveAsyncResult(hostName, null, includeIPv6, state, requestCallback);
            } 

            // Set up the context, possibly flow.
            if (flowContext)
            { 
                asyncResult.StartPostingAsyncOp(false);
            } 
 
            // Start the resolve.
            ThreadPool.UnsafeQueueUserWorkItem(resolveCallback, asyncResult); 

            // Finish the flowing, maybe it completed?  This does nothing if we didn't initiate the flowing above.
            asyncResult.FinishPostingAsyncOp();
            return asyncResult; 
        }
 
 
        private static IAsyncResult HostResolutionBeginHelper(IPAddress address, bool flowContext, bool includeIPv6, AsyncCallback requestCallback, object state)
        { 
            //
            // demand Unrestricted DnsPermission for this call
            //
 
            s_DnsPermission.Demand();
 
            if (address == null) { 
                throw new ArgumentNullException("address");
            } 

            if (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any))
            {
                throw new ArgumentException(SR.GetString(SR.net_invalid_ip_addr), "address"); 
            }
 
            GlobalLog.Print("Dns.HostResolutionBeginHelper: " + address); 

            // Set up the context, possibly flow. 
            ResolveAsyncResult asyncResult = new ResolveAsyncResult(address, null, includeIPv6, state, requestCallback);
            if (flowContext)
            {
                asyncResult.StartPostingAsyncOp(false); 
            }
 
            // Start the resolve. 
            ThreadPool.UnsafeQueueUserWorkItem(resolveCallback, asyncResult);
 
            // Finish the flowing, maybe it completed?  This does nothing if we didn't initiate the flowing above.
            asyncResult.FinishPostingAsyncOp();
            return asyncResult;
        } 

 
        private static IPHostEntry HostResolutionEndHelper(IAsyncResult asyncResult) 
        {
            // 
            // parameter validation
            //
            if (asyncResult == null) {
                throw new ArgumentNullException("asyncResult"); 
            }
            ResolveAsyncResult castedResult = asyncResult as ResolveAsyncResult; 
            if (castedResult == null) 
            {
                throw new ArgumentException(SR.GetString(SR.net_io_invalidasyncresult), "asyncResult"); 
            }
            if (castedResult.EndCalled)
            {
                throw new InvalidOperationException(SR.GetString(SR.net_io_invalidendcall, "EndResolve")); 
            }
 
            GlobalLog.Print("Dns.HostResolutionEndHelper"); 

            castedResult.InternalWaitForCompletion(); 
            castedResult.EndCalled = true;

            Exception exception = castedResult.Result as Exception;
            if (exception != null) 
            {
                throw exception; 
            } 

            return (IPHostEntry) castedResult.Result; 
        }

        /// 
        ///    [To be supplied.] 
        /// 
        [HostProtection(ExternalThreading=true)] 
        [Obsolete("BeginGetHostByName is obsoleted for this type, please use BeginGetHostEntry instead. http://go.microsoft.com/fwlink/?linkid=14202")] 
        public static IAsyncResult BeginGetHostByName(string hostName, AsyncCallback requestCallback, object stateObject) {
            if(Logging.On)Logging.Enter(Logging.Sockets, "DNS", "BeginGetHostByName", hostName); 

            IAsyncResult asyncResult = HostResolutionBeginHelper(hostName, true, true, false, false, requestCallback, stateObject);

            if(Logging.On)Logging.Exit(Logging.Sockets, "DNS", "BeginGetHostByName", asyncResult); 
            return asyncResult;
        } // BeginGetHostByName 
 
/* Uncomment when needed.
        internal static IAsyncResult UnsafeBeginGetHostByName(string hostName, AsyncCallback requestCallback, object stateObject) 
        {
            if(Logging.On)Logging.Enter(Logging.Sockets, "DNS", "BeginGetHostByName", hostName);

            IAsyncResult asyncResult = HostResolutionBeginHelper(hostName, true, false, false, false, requestCallback, stateObject); 

            if(Logging.On)Logging.Exit(Logging.Sockets, "DNS", "BeginGetHostByName", asyncResult); 
            return asyncResult; 
        } // UnsafeBeginResolve
*/ 

        /// 
        ///    [To be supplied.]
        ///  

 
        [Obsolete("EndGetHostByName is obsoleted for this type, please use EndGetHostEntry instead. http://go.microsoft.com/fwlink/?linkid=14202")] 
        public static IPHostEntry EndGetHostByName(IAsyncResult asyncResult) {
            if(Logging.On)Logging.Enter(Logging.Sockets, "DNS", "EndGetHostByName", asyncResult); 

            IPHostEntry ipHostEntry = HostResolutionEndHelper(asyncResult);

            if(Logging.On)Logging.Exit(Logging.Sockets, "DNS", "EndGetHostByName", ipHostEntry); 
            return ipHostEntry;
        } // EndGetHostByName() 
 

 
        //************************************************************************
        //*************   New Whidbey Apis  *************************************
        //***********************************************************************
 

 
        public static IPHostEntry GetHostEntry(string hostNameOrAddress) { 
            if(Logging.On)Logging.Enter(Logging.Sockets, "DNS", "GetHostEntry", hostNameOrAddress);
            // 
            // demand Unrestricted DnsPermission for this call
            //
            s_DnsPermission.Demand();
 
            if (hostNameOrAddress == null) {
                throw new ArgumentNullException("hostNameOrAddress"); 
            } 

            // See if it's an IP Address. 
            IPAddress address;
            IPHostEntry ipHostEntry;
            if (TryParseAsIP(hostNameOrAddress, out address))
            { 
                if (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any))
                { 
                    throw new ArgumentException(SR.GetString(SR.net_invalid_ip_addr), "hostNameOrAddress"); 
                }
 
                ipHostEntry = InternalGetHostByAddress(address, true, false);
            }
            else
            { 
                ipHostEntry = InternalGetHostByName(hostNameOrAddress, true);
            } 
 
            if (Logging.On) Logging.Exit(Logging.Sockets, "DNS", "GetHostEntry", ipHostEntry);
            return ipHostEntry; 
        }


        public static IPHostEntry GetHostEntry(IPAddress address) { 
            if(Logging.On)Logging.Enter(Logging.Sockets, "DNS", "GetHostEntry", "");
 
            // 
            // demand Unrestricted DnsPermission for this call
            // 
            s_DnsPermission.Demand();

            if (address == null) {
                throw new ArgumentNullException("address"); 
            }
 
            if (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any)) 
            {
                throw new ArgumentException(SR.GetString(SR.net_invalid_ip_addr), "address"); 
            }

            IPHostEntry ipHostEntry = InternalGetHostByAddress(address, true, false);
            if(Logging.On)Logging.Exit(Logging.Sockets, "DNS", "GetHostEntry", ipHostEntry); 
            return ipHostEntry;
        } // GetHostByAddress 
 

 
        public static IPAddress[] GetHostAddresses(string hostNameOrAddress) {
            if(Logging.On)Logging.Enter(Logging.Sockets, "DNS", "GetHostAddresses", hostNameOrAddress);
            //
            // demand Unrestricted DnsPermission for this call 
            //
            s_DnsPermission.Demand(); 
 
            if (hostNameOrAddress == null) {
                throw new ArgumentNullException("hostNameOrAddress"); 
            }

            // See if it's an IP Address.
            IPAddress address; 
            IPAddress[] addresses;
            if (TryParseAsIP(hostNameOrAddress, out address)) 
            { 
                if (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any))
                { 
                    throw new ArgumentException(SR.GetString(SR.net_invalid_ip_addr), "hostNameOrAddress");
                }

                addresses = new IPAddress[] { address }; 
            }
            else 
            { 
                // InternalGetHostByName works with IP addresses (and avoids a reverse-lookup), but we need
                // explicit handling in order to do the ArgumentException and guarantee the behavior. 
                addresses = InternalGetHostByName(hostNameOrAddress, true).AddressList;
            }

            if(Logging.On)Logging.Exit(Logging.Sockets, "DNS", "GetHostAddresses", addresses); 
            return addresses;
        } 
 

        [HostProtection(ExternalThreading=true)] 
        public static IAsyncResult BeginGetHostEntry(string hostNameOrAddress, AsyncCallback requestCallback, object stateObject) {
            if(Logging.On)Logging.Enter(Logging.Sockets, "DNS", "BeginGetHostEntry", hostNameOrAddress);

            IAsyncResult asyncResult = HostResolutionBeginHelper(hostNameOrAddress, false, true, true, true, requestCallback, stateObject); 

            if(Logging.On)Logging.Exit(Logging.Sockets, "DNS", "BeginGetHostEntry", asyncResult); 
            return asyncResult; 
        } // BeginResolve
 


        [HostProtection(ExternalThreading=true)]
        public static IAsyncResult BeginGetHostEntry(IPAddress address, AsyncCallback requestCallback, object stateObject) { 
            if(Logging.On)Logging.Enter(Logging.Sockets, "DNS", "BeginGetHostEntry", address);
 
            IAsyncResult asyncResult = HostResolutionBeginHelper(address, true, true, requestCallback, stateObject); 

            if(Logging.On)Logging.Exit(Logging.Sockets, "DNS", "BeginGetHostEntry", asyncResult); 
            return asyncResult;
        } // BeginResolve

 
        public static IPHostEntry EndGetHostEntry(IAsyncResult asyncResult) {
            if(Logging.On)Logging.Enter(Logging.Sockets, "DNS", "EndGetHostEntry", asyncResult); 
 
            IPHostEntry ipHostEntry = HostResolutionEndHelper(asyncResult);
 
            if(Logging.On)Logging.Exit(Logging.Sockets, "DNS", "EndGetHostEntry", ipHostEntry);
            return ipHostEntry;
        } // EndResolve()
 

        [HostProtection(ExternalThreading=true)] 
        public static IAsyncResult BeginGetHostAddresses(string hostNameOrAddress, AsyncCallback requestCallback, object state) { 
            if(Logging.On)Logging.Enter(Logging.Sockets, "DNS", "BeginGetHostAddresses", hostNameOrAddress);
 
            IAsyncResult asyncResult = HostResolutionBeginHelper(hostNameOrAddress, true, true, true, true, requestCallback, state);

            if(Logging.On)Logging.Exit(Logging.Sockets, "DNS", "BeginGetHostAddresses", asyncResult);
            return asyncResult; 
        } // BeginResolve
 
 
        public static IPAddress[] EndGetHostAddresses(IAsyncResult asyncResult) {
            if(Logging.On)Logging.Enter(Logging.Sockets, "DNS", "EndGetHostAddresses", asyncResult); 

            IPHostEntry ipHostEntry = HostResolutionEndHelper(asyncResult);

            if(Logging.On)Logging.Exit(Logging.Sockets, "DNS", "EndGetHostAddresses", ipHostEntry); 
            return ipHostEntry.AddressList;
        } // EndResolveToAddresses 
 

        internal static IAsyncResult UnsafeBeginGetHostAddresses(string hostName, AsyncCallback requestCallback, object state) 
        {
            if(Logging.On)Logging.Enter(Logging.Sockets, "DNS", "UnsafeBeginGetHostAddresses", hostName);

            IAsyncResult asyncResult = HostResolutionBeginHelper(hostName, true, false, true, true, requestCallback, state); 

            if(Logging.On)Logging.Exit(Logging.Sockets, "DNS", "UnsafeBeginGetHostAddresses", asyncResult); 
            return asyncResult; 
        } // UnsafeBeginResolveToAddresses
 

        /// 
        ///    [To be supplied.]
        ///  
        [HostProtection(ExternalThreading=true)]
        [Obsolete("BeginResolve is obsoleted for this type, please use BeginGetHostEntry instead. http://go.microsoft.com/fwlink/?linkid=14202")] 
        public static IAsyncResult BeginResolve(string hostName, AsyncCallback requestCallback, object stateObject) 
        {
            if(Logging.On)Logging.Enter(Logging.Sockets, "DNS", "BeginResolve", hostName); 

            IAsyncResult asyncResult = HostResolutionBeginHelper(hostName, false, true, false, false, requestCallback, stateObject);

            if(Logging.On)Logging.Exit(Logging.Sockets, "DNS", "BeginResolve", asyncResult); 
            return asyncResult;
        } // BeginResolve 
 

        [Obsolete("EndResolve is obsoleted for this type, please use EndGetHostEntry instead. http://go.microsoft.com/fwlink/?linkid=14202")] 
        public static IPHostEntry EndResolve(IAsyncResult asyncResult)
        {
            if(Logging.On)Logging.Enter(Logging.Sockets, "DNS", "EndResolve", asyncResult);
 
            IPHostEntry ipHostEntry = HostResolutionEndHelper(asyncResult);
 
            if(Logging.On)Logging.Exit(Logging.Sockets, "DNS", "EndResolve", ipHostEntry); 
            return ipHostEntry;
        } // EndResolve() 

        /* Uncomment when needed.
                internal static IAsyncResult UnsafeBeginResolve(string hostName, AsyncCallback requestCallback, object stateObject)
                { 
                    if(Logging.On)Logging.Enter(Logging.Sockets, "DNS", "BeginResolve", hostName);
 
                    IAsyncResult asyncResult = HostResolutionBeginHelper(hostName, false, false, true, false, requestCallback, stateObject); 

                    if(Logging.On)Logging.Exit(Logging.Sockets, "DNS", "BeginResolve", asyncResult); 
                    return asyncResult;
                } // UnsafeBeginResolve
        */
 
        //
        // IPv6 Changes: Add getaddrinfo and getnameinfo methods. 
        // 
        private unsafe static IPHostEntry GetAddrInfo(string name) {
            // 
            // Use SocketException here to show operation not supported
            // if, by some nefarious means, this method is called on an
            // unsupported platform.
            // 
#if FEATURE_PAL
            throw new SocketException(SocketError.OperationNotSupported); 
#else 
            if ( !ComNetOS.IsPostWin2K ) {
                throw new SocketException(SocketError.OperationNotSupported); 
            }

            SafeFreeAddrInfo root = null;
            ArrayList addresses = new ArrayList(); 
            string canonicalname = null;
 
            AddressInfo hints = new AddressInfo(); 
            hints.ai_flags = AddressInfoHints.AI_CANONNAME;// gets the resolved name
            hints.ai_family = AddressFamily.Unspecified;   // gets all address families 
            //
            // Use try / finally so we always get a shot at freeaddrinfo
            //
            try { 
                int errorCode = SafeFreeAddrInfo.GetAddrInfo(name, null, ref hints, out root);
                if (errorCode!=0) { 
                    throw new SocketException(); 
                }
 
                AddressInfo* pAddressInfo = (AddressInfo*)root.DangerousGetHandle();
                //
                // Process the results
                // 
                while (pAddressInfo!=null) {
                    SocketAddress sockaddr; 
                    // 
                    // Retrieve the canonical name for the host - only appears in the first AddressInfo
                    // entry in the returned array. 
                    //
                    if (canonicalname==null && pAddressInfo->ai_canonname!=null) {
                        canonicalname = new string(pAddressInfo->ai_canonname);
                    } 
                    //
                    // Only process IPv4 or IPv6 Addresses. Note that it's unlikely that we'll 
                    // ever get any other address families, but better to be safe than sorry. 
                    // We also filter based on whether IPv4 and IPv6 are supported on the current
                    // platform / machine. 
                    //
                    if ( ( pAddressInfo->ai_family == AddressFamily.InterNetwork   && Socket.SupportsIPv4 ) ||
                        (pAddressInfo->ai_family == AddressFamily.InterNetworkV6 && Socket.OSSupportsIPv6))
                    { 
                        sockaddr = new SocketAddress(pAddressInfo->ai_family, pAddressInfo->ai_addrlen);
                        // 
                        // Push address data into the socket address buffer 
                        //
                        for (int d = 0; d < pAddressInfo->ai_addrlen; d++) { 
                            sockaddr.m_Buffer[d] = *(pAddressInfo->ai_addr + d);
                        }
                        //
                        // NOTE: We need an IPAddress now, the only way to create it from a 
                        //       SocketAddress is via IPEndPoint. This ought to be simpler.
                        // 
                        if ( pAddressInfo->ai_family == AddressFamily.InterNetwork ) { 
                            addresses.Add( ((IPEndPoint)IPEndPoint.Any.Create(sockaddr)).Address );
                        } 
                        else {
                            addresses.Add( ((IPEndPoint)IPEndPoint.IPv6Any.Create(sockaddr)).Address );
                        }
                    } 
                    //
                    // Next addressinfo entry 
                    // 
                    pAddressInfo = pAddressInfo->ai_next;
                } 
            }
            finally {
                if (root != null) {
                    root.Close(); 
                }
            } 
 
            //
            // Finally, put together the IPHostEntry 
            //
            IPHostEntry hostinfo = new IPHostEntry();

            hostinfo.HostName = canonicalname!=null ? canonicalname : name; 
            hostinfo.Aliases = new string[0];
            hostinfo.AddressList = new IPAddress[addresses.Count]; 
            addresses.CopyTo(hostinfo.AddressList); 

            return hostinfo; 
#endif // FEATURE_PAL
        }

        internal static string TryGetNameInfo(IPAddress addr, out SocketError errorCode) { 
            //
            // Use SocketException here to show operation not supported 
            // if, by some nefarious means, this method is called on an 
            // unsupported platform.
            // 
#if FEATURE_PAL
            throw new SocketException(SocketError.OperationNotSupported);
#else
            if ( !ComNetOS.IsPostWin2K ) { 
                throw new SocketException(SocketError.OperationNotSupported);
            } 
 
            SocketAddress address  = (new IPEndPoint(addr,0)).Serialize();
            StringBuilder hostname = new StringBuilder(1025); // NI_MAXHOST 

            Socket.InitializeSockets();
            errorCode =
                UnsafeNclNativeMethods.OSSOCK.getnameinfo( 
                    address.m_Buffer,
                    address.m_Size, 
                    hostname, 
                    hostname.Capacity,
                    null, // We don't want a service name 
                    0, // so no need for buffer or length
                    (int)NameInfoFlags.NI_NAMEREQD);

            if (errorCode!=SocketError.Success) { 
                return null;
            } 
 
            return hostname.ToString();
#endif // FEATURE_PAL 
        }

        private static bool TryParseAsIP(string address, out IPAddress ip)
        { 
            return IPAddress.TryParse(address, out ip) &&
                ((ip.AddressFamily == AddressFamily.InterNetwork && Socket.SupportsIPv4) || 
                (ip.AddressFamily == AddressFamily.InterNetworkV6 && Socket.OSSupportsIPv6)); 
        }
    } 
}
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK