The Labs \ Source Viewer \ SSCLI \ System.Net \ Dns

  1. //------------------------------------------------------------------------------
  2. // <copyright file="DNS.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. namespace System.Net
  16. {
  17.     using System.Text;
  18.     using System.Collections;
  19.     using System.Net.Sockets;
  20.     using System.Runtime.InteropServices;
  21.     using System.Security.Permissions;
  22.     using System.Threading;
  23.     using System.Security;
  24.     using System.Globalization;
  25.    
  26.     /// <devdoc>
  27.     /// <para>Provides simple
  28.     /// domain name resolution functionality.</para>
  29.     /// </devdoc>
  30.    
  31.     public static class Dns
  32.     {
  33.         //
  34.         // used by GetHostName() to preallocate a buffer for the call to gethostname.
  35.         //
  36.         private const int HostNameBufferLength = 256;
  37.        
  38.         //also used as a lock object
  39.         private static DnsPermission s_DnsPermission = new DnsPermission(PermissionState.Unrestricted);
  40.         //
  41.         //
  42.         private const int MaxHostName = 126;
  43.        
  44.        
  45. /*++
  46.         Routine Description:
  47.             Takes a native pointer (expressed as an int) to a hostent structure,
  48.             and converts the information in their to an IPHostEntry class. This
  49.             involves walking through an array of native pointers, and a temporary
  50.             ArrayList object is used in doing this.
  51.         Arguments:
  52.             nativePointer  - Native pointer to hostent structure.
  53.         Return Value:
  54.             An IPHostEntry structure.
  55.         --*/       
  56.        
  57.         static internal IPHostEntry NativeToHostEntry(IntPtr nativePointer)
  58.         {
  59.             //
  60.             // marshal pointer to struct
  61.             //
  62.            
  63.             hostent Host = (hostent)Marshal.PtrToStructure(nativePointer, typeof(hostent));
  64.             IPHostEntry HostEntry = new IPHostEntry();
  65.            
  66.             if (Host.h_name != IntPtr.Zero) {
  67.                 HostEntry.HostName = Marshal.PtrToStringAnsi(Host.h_name);
  68.                 GlobalLog.Print("HostEntry.HostName: " + HostEntry.HostName);
  69.             }
  70.            
  71.             // decode h_addr_list to ArrayList of IP addresses.
  72.             // The h_addr_list field is really a pointer to an array of pointers
  73.             // to IP addresses. Loop through the array, and while the pointer
  74.             // isn't NULL read the IP address, convert it to an IPAddress class,
  75.             // and add it to the list.
  76.            
  77.             ArrayList TempList = new ArrayList();
  78.             int IPAddressToAdd;
  79.             string AliasToAdd;
  80.             IntPtr currentArrayElement;
  81.            
  82.             //
  83.             // get the first pointer in the array
  84.             //
  85.             currentArrayElement = Host.h_addr_list;
  86.             nativePointer = Marshal.ReadIntPtr(currentArrayElement);
  87.            
  88.             while (nativePointer != IntPtr.Zero) {
  89.                 //
  90.                 // if it's not null it points to an IPAddress,
  91.                 // read it...
  92.                 //
  93.                 IPAddressToAdd = Marshal.ReadInt32(nativePointer);
  94.                 #if BIGENDIAN
  95.                 // IP addresses from native code are always a byte array
  96.                 // converted to int. We need to convert the address into
  97.                 // a uniform integer value.
  98.                 IPAddressToAdd = (int)(((uint)IPAddressToAdd << 24) | (((uint)IPAddressToAdd & 65280) << 8) | (((uint)IPAddressToAdd >> 8) & 65280) | ((uint)IPAddressToAdd >> 24));
  99.                 #endif
  100.                
  101.                 GlobalLog.Print("currentArrayElement: " + currentArrayElement.ToString() + " nativePointer: " + nativePointer.ToString() + " IPAddressToAdd:" + IPAddressToAdd.ToString());
  102.                
  103.                 //
  104.                 // ...and add it to the list
  105.                 //
  106.                 TempList.Add(new IPAddress(IPAddressToAdd));
  107.                
  108.                 //
  109.                 // now get the next pointer in the array and start over
  110.                 //
  111.                 currentArrayElement = IntPtrHelper.Add(currentArrayElement, IntPtr.Size);
  112.                 nativePointer = Marshal.ReadIntPtr(currentArrayElement);
  113.             }
  114.            
  115.             HostEntry.AddressList = new IPAddress[TempList.Count];
  116.             TempList.CopyTo(HostEntry.AddressList, 0);
  117.            
  118.             //
  119.             // Now do the same thing for the aliases.
  120.             //
  121.            
  122.             TempList.Clear();
  123.            
  124.             currentArrayElement = Host.h_aliases;
  125.             nativePointer = Marshal.ReadIntPtr(currentArrayElement);
  126.            
  127.             while (nativePointer != IntPtr.Zero) {
  128.                
  129.                 GlobalLog.Print("currentArrayElement: " + ((long)currentArrayElement).ToString() + "nativePointer: " + ((long)nativePointer).ToString());
  130.                
  131.                 //
  132.                 // if it's not null it points to an Alias,
  133.                 // read it...
  134.                 //
  135.                 AliasToAdd = Marshal.PtrToStringAnsi(nativePointer);
  136.                
  137.                 //
  138.                 // ...and add it to the list
  139.                 //
  140.                 TempList.Add(AliasToAdd);
  141.                
  142.                 //
  143.                 // now get the next pointer in the array and start over
  144.                 //
  145.                 currentArrayElement = IntPtrHelper.Add(currentArrayElement, IntPtr.Size);
  146.                 nativePointer = Marshal.ReadIntPtr(currentArrayElement);
  147.                
  148.             }
  149.            
  150.             HostEntry.Aliases = new string[TempList.Count];
  151.             TempList.CopyTo(HostEntry.Aliases, 0);
  152.            
  153.             return HostEntry;
  154.            
  155.         }
  156.         // NativeToHostEntry
  157. /*****************************************************************************
  158.         Function :    gethostbyname
  159.         Abstract:    Queries DNS for hostname address
  160.         Input Parameters: str (String to query)
  161.         Returns: Void
  162.         ******************************************************************************/       
  163.        
  164.         /// <devdoc>
  165.         /// <para>Retrieves the <see cref='System.Net.IPHostEntry'/>
  166.         /// information
  167.         /// corresponding to the DNS name provided in the host
  168.         /// parameter.</para>
  169.         /// </devdoc>
  170.        
  171.        
  172.         [Obsolete("GetHostByName is obsoleted for this type, please use GetHostEntry instead. http://go.microsoft.com/fwlink/?linkid=14202")]
  173.         public static IPHostEntry GetHostByName(string hostName)
  174.         {
  175.             if (hostName == null) {
  176.                 throw new ArgumentNullException("hostName");
  177.             }
  178.             //
  179.             // demand Unrestricted DnsPermission for this call
  180.             //
  181.             s_DnsPermission.Demand();
  182.             return InternalGetHostByName(hostName, false);
  183.         }
  184.         //
  185.        
  186.        
  187.         static internal IPHostEntry InternalGetHostByName(string hostName)
  188.         {
  189.             return InternalGetHostByName(hostName, true);
  190.         }
  191.        
  192.         static internal IPHostEntry InternalGetHostByName(string hostName, bool includeIPv6)
  193.         {
  194.             if (Logging.On)
  195.                 Logging.Enter(Logging.Sockets, "DNS", "GetHostByName", hostName);
  196.             IPHostEntry ipHostEntry = null;
  197.            
  198.             GlobalLog.Print("Dns.GetHostByName: " + hostName);
  199.            
  200.             if (hostName.Length > MaxHostName) {
  201.                 throw new ArgumentOutOfRangeException(SR.GetString(SR.net_toolong, "hostName", MaxHostName.ToString(NumberFormatInfo.CurrentInfo)));
  202.             }
  203.            
  204.             {
  205.                 //
  206.                 // IPv6 disabled: use gethostbyname() to obtain DNS information.
  207.                 //
  208.                 IntPtr nativePointer = UnsafeNclNativeMethods.OSSOCK.gethostbyname(hostName);
  209.                
  210.                 if (nativePointer == IntPtr.Zero) {
  211.                     // This is for compatiblity with NT4/Win2k
  212.                     // Need to do this first since if we wait the last error code might be overwritten.
  213.                     SocketException socketException = new SocketException();
  214.                    
  215.                     IPAddress address;
  216.                     if (IPAddress.TryParse(hostName, out address)) {
  217.                         ipHostEntry = new IPHostEntry();
  218.                         ipHostEntry.HostName = address.ToString();
  219.                         ipHostEntry.Aliases = new string[0];
  220.                         ipHostEntry.AddressList = new IPAddress[] {address};
  221.                         if (Logging.On)
  222.                             Logging.Exit(Logging.Sockets, "DNS", "GetHostByName", ipHostEntry);
  223.                         return ipHostEntry;
  224.                     }
  225.                    
  226.                     throw socketException;
  227.                 }
  228.                 ipHostEntry = NativeToHostEntry(nativePointer);
  229.             }
  230.            
  231.             if (Logging.On)
  232.                 Logging.Exit(Logging.Sockets, "DNS", "GetHostByName", ipHostEntry);
  233.             return ipHostEntry;
  234.            
  235.         }
  236.         // GetHostByName
  237.        
  238.        
  239. /*****************************************************************************
  240.         Function :    gethostbyaddr
  241.         Abstract:    Queries IP address string and tries to match with a host name
  242.         Input Parameters: str (String to query)
  243.         Returns: IPHostEntry
  244.         ******************************************************************************/       
  245.        
  246.         /// <devdoc>
  247.         /// <para>Creates an <see cref='System.Net.IPHostEntry'/>
  248.         /// instance from an IP dotted address.</para>
  249.         /// </devdoc>
  250.        
  251.         [Obsolete("GetHostByAddress is obsoleted for this type, please use GetHostEntry instead. http://go.microsoft.com/fwlink/?linkid=14202")]
  252.         public static IPHostEntry GetHostByAddress(string address)
  253.         {
  254.             if (Logging.On)
  255.                 Logging.Enter(Logging.Sockets, "DNS", "GetHostByAddress", address);
  256.             //
  257.             // demand Unrestricted DnsPermission for this call
  258.             //
  259.             s_DnsPermission.Demand();
  260.            
  261.             if (address == null) {
  262.                 throw new ArgumentNullException("address");
  263.             }
  264.            
  265.             GlobalLog.Print("Dns.GetHostByAddress: " + address);
  266.            
  267.             IPHostEntry ipHostEntry = InternalGetHostByAddress(IPAddress.Parse(address), false, true);
  268.             if (Logging.On)
  269.                 Logging.Exit(Logging.Sockets, "DNS", "GetHostByAddress", ipHostEntry);
  270.             return ipHostEntry;
  271.         }
  272.         // GetHostByAddress
  273. /*****************************************************************************
  274.         Function :    gethostbyaddr
  275.         Abstract:    Queries IP address and tries to match with a host name
  276.         Input Parameters: address (address to query)
  277.         Returns: IPHostEntry
  278.         ******************************************************************************/       
  279.        
  280.         /// <devdoc>
  281.         /// <para>Creates an <see cref='System.Net.IPHostEntry'/> instance from an <see cref='System.Net.IPAddress'/>
  282.         /// instance.</para>
  283.         /// </devdoc>
  284.        
  285.         [Obsolete("GetHostByAddress is obsoleted for this type, please use GetHostEntry instead. http://go.microsoft.com/fwlink/?linkid=14202")]
  286.         public static IPHostEntry GetHostByAddress(IPAddress address)
  287.         {
  288.             if (Logging.On)
  289.                 Logging.Enter(Logging.Sockets, "DNS", "GetHostByAddress", "");
  290.             //
  291.             // demand Unrestricted DnsPermission for this call
  292.             //
  293.             s_DnsPermission.Demand();
  294.            
  295.             if (address == null) {
  296.                 throw new ArgumentNullException("address");
  297.             }
  298.            
  299.             IPHostEntry ipHostEntry = InternalGetHostByAddress(address, false, true);
  300.             if (Logging.On)
  301.                 Logging.Exit(Logging.Sockets, "DNS", "GetHostByAddress", ipHostEntry);
  302.             return ipHostEntry;
  303.         }
  304.         // GetHostByAddress
  305.         static internal IPHostEntry InternalGetHostByAddress(IPAddress address, bool includeIPv6, bool throwOnFailure)
  306.         {
  307.             GlobalLog.Print("Dns.InternalGetHostByAddress: " + address.ToString());
  308.            
  309.             Exception exception = null;
  310.            
  311.            
  312.             //
  313.             // If IPv6 is not enabled (maybe config switch) but we've been
  314.             // given an IPv6 address then we need to bail out now.
  315.             //
  316.             {
  317.                 if (address.AddressFamily == AddressFamily.InterNetworkV6) {
  318.                     //
  319.                     // Protocol not supported
  320.                     //
  321.                     throw new SocketException(SocketError.ProtocolNotSupported);
  322.                 }
  323.                 //
  324.                 // Use gethostbyaddr() to try to resolve the IP address
  325.                 //
  326.                 // End IPv6 Changes
  327.                 //
  328.                 int addressAsInt = unchecked((int)address.m_Address);
  329.                
  330.                 #if BIGENDIAN
  331.                 addressAsInt = (int)(((uint)addressAsInt << 24) | (((uint)addressAsInt & 65280) << 8) | (((uint)addressAsInt >> 8) & 65280) | ((uint)addressAsInt >> 24));
  332.                 #endif
  333.                
  334.                 IntPtr nativePointer = UnsafeNclNativeMethods.OSSOCK.gethostbyaddr(ref addressAsInt, Marshal.SizeOf(typeof(int)), ProtocolFamily.InterNetwork);
  335.                
  336.                
  337.                 if (nativePointer != IntPtr.Zero) {
  338.                     return NativeToHostEntry(nativePointer);
  339.                 }
  340.                 exception = new SocketException();
  341.             }
  342.            
  343.             if (throwOnFailure) {
  344.                 throw exception;
  345.             }
  346.            
  347.             IPHostEntry ipHostEntry = new IPHostEntry();
  348.            
  349.             try {
  350.                 ipHostEntry.HostName = address.ToString();
  351.                 ipHostEntry.Aliases = new string[0];
  352.                 ipHostEntry.AddressList = new IPAddress[] {address};
  353.             }
  354.             catch {
  355.                 throw exception;
  356.                 //throw the original exception
  357.             }
  358.             return ipHostEntry;
  359.         }
  360.         // InternalGetHostByAddress
  361.        
  362. /*****************************************************************************
  363.         Function :    gethostname
  364.         Abstract:    Queries the hostname from DNS
  365.         Input Parameters:
  366.         Returns: String
  367.         ******************************************************************************/       
  368.        
  369.         /// <devdoc>
  370.         /// <para>Gets the host name of the local machine.</para>
  371.         /// </devdoc>
  372.         // UEUE: note that this method is not threadsafe!!
  373.         public static string GetHostName()
  374.         {
  375.             //
  376.             // demand Unrestricted DnsPermission for this call
  377.             //
  378.             s_DnsPermission.Demand();
  379.            
  380.             GlobalLog.Print("Dns.GetHostName");
  381.            
  382.             //
  383.             // note that we could cache the result ourselves since you
  384.             // wouldn't expect the hostname of the machine to change during
  385.             // execution, but this might still happen and we would want to
  386.             // react to that change.
  387.             //
  388.            
  389.             Socket.InitializeSockets();
  390.             StringBuilder sb = new StringBuilder(HostNameBufferLength);
  391.             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.gethostname(sb, HostNameBufferLength);
  392.            
  393.             //
  394.             // if the call failed throw a SocketException()
  395.             //
  396.             if (errorCode != SocketError.Success) {
  397.                 throw new SocketException();
  398.             }
  399.             return sb.ToString();
  400.         }
  401.        
  402.        
  403. /*****************************************************************************
  404.         Function :    resolve
  405.         Abstract:    Converts IP/hostnames to IP numerical address using DNS
  406.                       Additional methods provided for convenience
  407.                       (These methods will resolve strings and hostnames. In case of
  408.                       multiple IP addresses, the address returned is chosen arbitrarily.)
  409.         Input Parameters: host/IP
  410.         Returns: IPAddress
  411.         ******************************************************************************/       
  412.        
  413.         /// <devdoc>
  414.         /// <para>Creates an <see cref='System.Net.IPAddress'/>
  415.         /// instance from a DNS hostname.</para>
  416.         /// </devdoc>
  417.         // UEUE
  418.        
  419.        
  420.         [Obsolete("Resolve is obsoleted for this type, please use GetHostEntry instead. http://go.microsoft.com/fwlink/?linkid=14202")]
  421.         public static IPHostEntry Resolve(string hostName)
  422.         {
  423.             if (Logging.On)
  424.                 Logging.Enter(Logging.Sockets, "DNS", "Resolve", hostName);
  425.             //
  426.             // demand Unrestricted DnsPermission for this call
  427.             //
  428.             s_DnsPermission.Demand();
  429.            
  430.             if (hostName == null) {
  431.                 throw new ArgumentNullException("hostName");
  432.             }
  433.            
  434.             // See if it's an IP Address.
  435.             IPAddress address;
  436.             IPHostEntry ipHostEntry;
  437.            
  438.             if (TryParseAsIP(hostName, out address) && (address.AddressFamily != AddressFamily.InterNetworkV6 || Socket.LegacySupportsIPv6)) {
  439.                 ipHostEntry = InternalGetHostByAddress(address, false, false);
  440.             }
  441.             else {
  442.                 ipHostEntry = InternalGetHostByName(hostName, false);
  443.             }
  444.            
  445.             if (Logging.On)
  446.                 Logging.Exit(Logging.Sockets, "DNS", "Resolve", ipHostEntry);
  447.             return ipHostEntry;
  448.         }
  449.        
  450.        
  451.         //Caution, this will return ipv6 addresses if the OS supports it. This shouldn't be called by the public apis.
  452.         static internal IPHostEntry InternalResolveFast(string hostName, int timeout, out bool timedOut)
  453.         {
  454.             GlobalLog.Assert(hostName != null, "hostName == null");
  455.             GlobalLog.Print("Dns.InternalResolveFase: " + hostName);
  456.            
  457.             //
  458.             // the differences between this method and the previous InternalResolve() are:
  459.             //
  460.             // 1) we don't throw any exceptions
  461.             // 2) we don't do a reverse lookup for address strings, we just use them
  462.             //
  463.             // IPv6 Changes: It is not practical to embed the code for GetAddrInfo here, instead
  464.             // we call it and catch any exceptions.
  465.             //
  466.             // Timeout: Supports a timeout by offloading work to another thread if necessary.
  467.             //
  468.            
  469.             // We can't abort a DNS lookup so if we think might need to, run it on another thread.
  470.             // According to MSDN the max time is 17 seconds. Use 18 and say 20.
  471.             // Also: MSDN describes how one lookup can result in a string of queries. It's unclear whether
  472.             // those would be run in series, extending the possible time this will take, or whether it will always
  473.             // give up after 17 seconds. For now assume that 17 seconds is the absolute max.
  474.             bool mightTimeOut = 18000 >= (uint)timeout && timeout != Timeout.Infinite;
  475.             timedOut = false;
  476.            
  477.             if (hostName.Length > 0 && hostName.Length <= MaxHostName) {
  478.                 // IP Address?
  479.                 IPAddress address;
  480.                 if (TryParseAsIP(hostName, out address)) {
  481.                     IPHostEntry ipHostEntry = new IPHostEntry();
  482.                     ipHostEntry.HostName = address.ToString();
  483.                     ipHostEntry.Aliases = new string[0];
  484.                     ipHostEntry.AddressList = new IPAddress[] {address};
  485.                    
  486.                     GlobalLog.Print("Dns::InternalResolveFast() returned address:" + address.ToString());
  487.                     return ipHostEntry;
  488.                 }
  489.                
  490.                 // Looks like a hostname (or failed address parsing)
  491.                 if (Socket.OSSupportsIPv6) {
  492.                     try {
  493.                         // we will no longer offload to a thread, due to the consequence of having a threadpool thread
  494.                         //block on another threadpool thread. In addition, even w/ the DNS server functioning, we run
  495.                         // the risk of having too many of these queued up, causing requests to fail w/ an unable to resolve
  496.                         //exception.
  497.                        
  498.                         //I'm leaving the code commented out to possibly reuse in our async case.
  499.                        
  500.                         // if (!mightTimeOut)
  501.                         // {
  502.                         return GetAddrInfo(hostName);
  503.                         // }
  504.                         /* else
  505.                         {
  506.                             AsyncDnsContext dnsContext = new AsyncDnsContext(hostName);
  507.                             dnsContext.Offload(new WaitCallback(OffloadedGetAddrInfo));
  508.                             return (IPHostEntry) dnsContext.Wait(timeout, out timedOut);
  509.                         }
  510.                         */                       
  511.                     }
  512.                     catch (Exception e) {
  513.                         GlobalLog.Print("Dns::InternalResolveFast() GetAddrInfo() threw: " + e.Message);
  514.                     }
  515.                 }
  516.                 else {
  517.                     //
  518.                     // we duplicate the code in GetHostByName() to avoid
  519.                     // having to catch the thrown exception
  520.                     //
  521.                     IntPtr nativePointer;
  522.                     //if (!mightTimeOut)
  523.                     //{
  524.                     nativePointer = UnsafeNclNativeMethods.OSSOCK.gethostbyname(hostName);
  525.                     //}
  526.                     /*
  527.                     else
  528.                     {
  529.                         AsyncDnsContext dnsContext = new AsyncDnsContext(hostName);
  530.                         dnsContext.Offload(new WaitCallback(OffloadedGetHostByName));
  531.                         object result = dnsContext.Wait(timeout, out timedOut);
  532.                         nativePointer = result == null ? IntPtr.Zero : (IntPtr) result;
  533.                     }
  534.                     */                   
  535. if (nativePointer != IntPtr.Zero) {
  536.                         GlobalLog.Print("Dns::InternalResolveFast() gethostbyname() returned nativePointer:" + nativePointer.ToString());
  537.                         return NativeToHostEntry(nativePointer);
  538.                     }
  539.                 }
  540.             }
  541.            
  542.             GlobalLog.Print("Dns::InternalResolveFast() returning null");
  543.             if (Logging.On)
  544.                 Logging.Exit(Logging.Sockets, "DNS", "InternalResolveFast", null);
  545.             return null;
  546.         }
  547.        
  548.        
  549.         private static WaitCallback resolveCallback = new WaitCallback(ResolveCallback);
  550.        
  551.         private class ResolveAsyncResult : ContextAwareResult
  552.         {
  553.             internal ResolveAsyncResult(string hostName, object myObject, bool includeIPv6, object myState, AsyncCallback myCallBack) : base(myObject, myState, myCallBack)
  554.             {
  555.                 this.hostName = hostName;
  556.                 this.includeIPv6 = includeIPv6;
  557.             }
  558.            
  559.            
  560.             internal ResolveAsyncResult(IPAddress address, object myObject, bool includeIPv6, object myState, AsyncCallback myCallBack) : base(myObject, myState, myCallBack)
  561.             {
  562.                 this.includeIPv6 = includeIPv6;
  563.                 this.address = address;
  564.             }
  565.            
  566.             internal readonly string hostName;
  567.             internal bool includeIPv6;
  568.             internal IPAddress address;
  569.         }
  570.        
  571.         private static void ResolveCallback(object context)
  572.         {
  573.             ResolveAsyncResult result = (ResolveAsyncResult)context;
  574.             IPHostEntry hostEntry;
  575.             try {
  576.                 if (result.address != null) {
  577.                     hostEntry = InternalGetHostByAddress(result.address, result.includeIPv6, false);
  578.                 }
  579.                 else {
  580.                     hostEntry = InternalGetHostByName(result.hostName, result.includeIPv6);
  581.                 }
  582.             }
  583.             catch (Exception exception) {
  584.                 if (exception is OutOfMemoryException || exception is ThreadAbortException || exception is StackOverflowException)
  585.                     throw;
  586.                
  587.                 result.InvokeCallback(exception);
  588.                 return;
  589.             }
  590.            
  591.             result.InvokeCallback(hostEntry);
  592.         }
  593.        
  594.        
  595.         // Helpers for async GetHostByName, ResolveToAddresses, and Resolve - they're almost identical
  596.        
  597.         private static IAsyncResult HostResolutionBeginHelper(string hostName, bool useGetHostByName, bool flowContext, bool includeIPv6, bool throwOnIPAny, AsyncCallback requestCallback, object state)
  598.         {
  599.             s_DnsPermission.Demand();
  600.            
  601.             if (hostName == null) {
  602.                 throw new ArgumentNullException("hostName");
  603.             }
  604.            
  605.             GlobalLog.Print("Dns.HostResolutionBeginHelper: " + hostName);
  606.            
  607.             // See if it's an IP Address.
  608.             IPAddress address;
  609.             ResolveAsyncResult asyncResult;
  610.             if (TryParseAsIP(hostName, out address)) {
  611.                 if (throwOnIPAny && (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any))) {
  612.                     throw new ArgumentException(SR.GetString(SR.net_invalid_ip_addr), "hostNameOrAddress");
  613.                 }
  614.                
  615.                 asyncResult = new ResolveAsyncResult(address, null, includeIPv6, state, requestCallback);
  616.                
  617.                 if (useGetHostByName) {
  618.                     IPHostEntry hostEntry = new IPHostEntry();
  619.                     hostEntry.AddressList = new IPAddress[] {address};
  620.                     hostEntry.Aliases = new string[0];
  621.                     hostEntry.HostName = address.ToString();
  622.                     asyncResult.StartPostingAsyncOp(false);
  623.                     asyncResult.InvokeCallback(hostEntry);
  624.                     asyncResult.FinishPostingAsyncOp();
  625.                     return asyncResult;
  626.                 }
  627.             }
  628.             else {
  629.                 asyncResult = new ResolveAsyncResult(hostName, null, includeIPv6, state, requestCallback);
  630.             }
  631.            
  632.             // Set up the context, possibly flow.
  633.             if (flowContext) {
  634.                 asyncResult.StartPostingAsyncOp(false);
  635.             }
  636.            
  637.             // Start the resolve.
  638.             ThreadPool.UnsafeQueueUserWorkItem(resolveCallback, asyncResult);
  639.            
  640.             // Finish the flowing, maybe it completed? This does nothing if we didn't initiate the flowing above.
  641.             asyncResult.FinishPostingAsyncOp();
  642.             return asyncResult;
  643.         }
  644.        
  645.        
  646.         private static IAsyncResult HostResolutionBeginHelper(IPAddress address, bool flowContext, bool includeIPv6, AsyncCallback requestCallback, object state)
  647.         {
  648.             s_DnsPermission.Demand();
  649.            
  650.             if (address == null) {
  651.                 throw new ArgumentNullException("address");
  652.             }
  653.            
  654.             if (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any)) {
  655.                 throw new ArgumentException(SR.GetString(SR.net_invalid_ip_addr), "address");
  656.             }
  657.            
  658.             GlobalLog.Print("Dns.HostResolutionBeginHelper: " + address);
  659.            
  660.             // Set up the context, possibly flow.
  661.             ResolveAsyncResult asyncResult = new ResolveAsyncResult(address, null, includeIPv6, state, requestCallback);
  662.             if (flowContext) {
  663.                 asyncResult.StartPostingAsyncOp(false);
  664.             }
  665.            
  666.             // Start the resolve.
  667.             ThreadPool.UnsafeQueueUserWorkItem(resolveCallback, asyncResult);
  668.            
  669.             // Finish the flowing, maybe it completed? This does nothing if we didn't initiate the flowing above.
  670.             asyncResult.FinishPostingAsyncOp();
  671.             return asyncResult;
  672.         }
  673.        
  674.        
  675.         private static IPHostEntry HostResolutionEndHelper(IAsyncResult asyncResult)
  676.         {
  677.             //
  678.             // parameter validation
  679.             //
  680.             if (asyncResult == null) {
  681.                 throw new ArgumentNullException("asyncResult");
  682.             }
  683.             ResolveAsyncResult castedResult = asyncResult as ResolveAsyncResult;
  684.             if (castedResult == null) {
  685.                 throw new ArgumentException(SR.GetString(SR.net_io_invalidasyncresult), "asyncResult");
  686.             }
  687.             if (castedResult.EndCalled) {
  688.                 throw new InvalidOperationException(SR.GetString(SR.net_io_invalidendcall, "EndResolve"));
  689.             }
  690.            
  691.             GlobalLog.Print("Dns.HostResolutionEndHelper");
  692.            
  693.             castedResult.InternalWaitForCompletion();
  694.             castedResult.EndCalled = true;
  695.            
  696.             Exception exception = castedResult.Result as Exception;
  697.             if (exception != null) {
  698.                 throw exception;
  699.             }
  700.            
  701.             return (IPHostEntry)castedResult.Result;
  702.         }
  703.        
  704.         /// <devdoc>
  705.         /// <para>[To be supplied.]</para>
  706.         /// </devdoc>
  707.         [HostProtection(ExternalThreading = true)]
  708.         [Obsolete("BeginGetHostByName is obsoleted for this type, please use BeginGetHostEntry instead. http://go.microsoft.com/fwlink/?linkid=14202")]
  709.         public static IAsyncResult BeginGetHostByName(string hostName, AsyncCallback requestCallback, object stateObject)
  710.         {
  711.             if (Logging.On)
  712.                 Logging.Enter(Logging.Sockets, "DNS", "BeginGetHostByName", hostName);
  713.            
  714.             IAsyncResult asyncResult = HostResolutionBeginHelper(hostName, true, true, false, false, requestCallback, stateObject);
  715.            
  716.             if (Logging.On)
  717.                 Logging.Exit(Logging.Sockets, "DNS", "BeginGetHostByName", asyncResult);
  718.             return asyncResult;
  719.         }
  720.         // BeginGetHostByName
  721. /* Uncomment when needed.
  722.         internal static IAsyncResult UnsafeBeginGetHostByName(string hostName, AsyncCallback requestCallback, object stateObject)
  723.         {
  724.             if(Logging.On)Logging.Enter(Logging.Sockets, "DNS", "BeginGetHostByName", hostName);
  725.             IAsyncResult asyncResult = HostResolutionBeginHelper(hostName, true, false, false, false, requestCallback, stateObject);
  726.             if(Logging.On)Logging.Exit(Logging.Sockets, "DNS", "BeginGetHostByName", asyncResult);
  727.             return asyncResult;
  728.         } // UnsafeBeginResolve
  729. */       
  730.        
  731.         /// <devdoc>
  732.         /// <para>[To be supplied.]</para>
  733.         /// </devdoc>
  734.        
  735.        
  736.         [Obsolete("EndGetHostByName is obsoleted for this type, please use EndGetHostEntry instead. http://go.microsoft.com/fwlink/?linkid=14202")]
  737.         public static IPHostEntry EndGetHostByName(IAsyncResult asyncResult)
  738.         {
  739.             if (Logging.On)
  740.                 Logging.Enter(Logging.Sockets, "DNS", "EndGetHostByName", asyncResult);
  741.            
  742.             IPHostEntry ipHostEntry = HostResolutionEndHelper(asyncResult);
  743.            
  744.             if (Logging.On)
  745.                 Logging.Exit(Logging.Sockets, "DNS", "EndGetHostByName", ipHostEntry);
  746.             return ipHostEntry;
  747.         }
  748.        
  749.        
  750.        
  751.        
  752.        
  753.        
  754.         public static IPHostEntry GetHostEntry(string hostNameOrAddress)
  755.         {
  756.             if (Logging.On)
  757.                 Logging.Enter(Logging.Sockets, "DNS", "GetHostEntry", hostNameOrAddress);
  758.             //
  759.             // demand Unrestricted DnsPermission for this call
  760.             //
  761.             s_DnsPermission.Demand();
  762.            
  763.             if (hostNameOrAddress == null) {
  764.                 throw new ArgumentNullException("hostNameOrAddress");
  765.             }
  766.            
  767.             // See if it's an IP Address.
  768.             IPAddress address;
  769.             IPHostEntry ipHostEntry;
  770.             if (TryParseAsIP(hostNameOrAddress, out address)) {
  771.                 if (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any)) {
  772.                     throw new ArgumentException(SR.GetString(SR.net_invalid_ip_addr), "hostNameOrAddress");
  773.                 }
  774.                
  775.                 ipHostEntry = InternalGetHostByAddress(address, true, false);
  776.             }
  777.             else {
  778.                 ipHostEntry = InternalGetHostByName(hostNameOrAddress, true);
  779.             }
  780.            
  781.             if (Logging.On)
  782.                 Logging.Exit(Logging.Sockets, "DNS", "GetHostEntry", ipHostEntry);
  783.             return ipHostEntry;
  784.         }
  785.        
  786.        
  787.         public static IPHostEntry GetHostEntry(IPAddress address)
  788.         {
  789.             if (Logging.On)
  790.                 Logging.Enter(Logging.Sockets, "DNS", "GetHostEntry", "");
  791.            
  792.             //
  793.             // demand Unrestricted DnsPermission for this call
  794.             //
  795.             s_DnsPermission.Demand();
  796.            
  797.             if (address == null) {
  798.                 throw new ArgumentNullException("address");
  799.             }
  800.            
  801.             if (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any)) {
  802.                 throw new ArgumentException(SR.GetString(SR.net_invalid_ip_addr), "address");
  803.             }
  804.            
  805.             IPHostEntry ipHostEntry = InternalGetHostByAddress(address, true, false);
  806.             if (Logging.On)
  807.                 Logging.Exit(Logging.Sockets, "DNS", "GetHostEntry", ipHostEntry);
  808.             return ipHostEntry;
  809.         }
  810.         // GetHostByAddress
  811.        
  812.        
  813.         public static IPAddress[] GetHostAddresses(string hostNameOrAddress)
  814.         {
  815.             if (Logging.On)
  816.                 Logging.Enter(Logging.Sockets, "DNS", "GetHostAddresses", hostNameOrAddress);
  817.             //
  818.             // demand Unrestricted DnsPermission for this call
  819.             //
  820.             s_DnsPermission.Demand();
  821.            
  822.             if (hostNameOrAddress == null) {
  823.                 throw new ArgumentNullException("hostNameOrAddress");
  824.             }
  825.            
  826.             // See if it's an IP Address.
  827.             IPAddress address;
  828.             IPAddress[] addresses;
  829.             if (TryParseAsIP(hostNameOrAddress, out address)) {
  830.                 if (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any)) {
  831.                     throw new ArgumentException(SR.GetString(SR.net_invalid_ip_addr), "hostNameOrAddress");
  832.                 }
  833.                
  834.                 addresses = new IPAddress[] {address};
  835.             }
  836.             else {
  837.                 // InternalGetHostByName works with IP addresses (and avoids a reverse-lookup), but we need
  838.                 // explicit handling in order to do the ArgumentException and guarantee the behavior.
  839.                 addresses = InternalGetHostByName(hostNameOrAddress, true).AddressList;
  840.             }
  841.            
  842.             if (Logging.On)
  843.                 Logging.Exit(Logging.Sockets, "DNS", "GetHostAddresses", addresses);
  844.             return addresses;
  845.         }
  846.        
  847.        
  848.         [HostProtection(ExternalThreading = true)]
  849.         public static IAsyncResult BeginGetHostEntry(string hostNameOrAddress, AsyncCallback requestCallback, object stateObject)
  850.         {
  851.             if (Logging.On)
  852.                 Logging.Enter(Logging.Sockets, "DNS", "BeginGetHostEntry", hostNameOrAddress);
  853.            
  854.             IAsyncResult asyncResult = HostResolutionBeginHelper(hostNameOrAddress, false, true, true, true, requestCallback, stateObject);
  855.            
  856.             if (Logging.On)
  857.                 Logging.Exit(Logging.Sockets, "DNS", "BeginGetHostEntry", asyncResult);
  858.             return asyncResult;
  859.         }
  860.         // BeginResolve
  861.        
  862.        
  863.         [HostProtection(ExternalThreading = true)]
  864.         public static IAsyncResult BeginGetHostEntry(IPAddress address, AsyncCallback requestCallback, object stateObject)
  865.         {
  866.             if (Logging.On)
  867.                 Logging.Enter(Logging.Sockets, "DNS", "BeginGetHostEntry", address);
  868.            
  869.             IAsyncResult asyncResult = HostResolutionBeginHelper(address, true, true, requestCallback, stateObject);
  870.            
  871.             if (Logging.On)
  872.                 Logging.Exit(Logging.Sockets, "DNS", "BeginGetHostEntry", asyncResult);
  873.             return asyncResult;
  874.         }
  875.         // BeginResolve
  876.        
  877.         public static IPHostEntry EndGetHostEntry(IAsyncResult asyncResult)
  878.         {
  879.             if (Logging.On)
  880.                 Logging.Enter(Logging.Sockets, "DNS", "EndGetHostEntry", asyncResult);
  881.            
  882.             IPHostEntry ipHostEntry = HostResolutionEndHelper(asyncResult);
  883.            
  884.             if (Logging.On)
  885.                 Logging.Exit(Logging.Sockets, "DNS", "EndGetHostEntry", ipHostEntry);
  886.             return ipHostEntry;
  887.         }
  888.         // EndResolve()
  889.        
  890.         [HostProtection(ExternalThreading = true)]
  891.         public static IAsyncResult BeginGetHostAddresses(string hostNameOrAddress, AsyncCallback requestCallback, object state)
  892.         {
  893.             if (Logging.On)
  894.                 Logging.Enter(Logging.Sockets, "DNS", "BeginGetHostAddresses", hostNameOrAddress);
  895.            
  896.             IAsyncResult asyncResult = HostResolutionBeginHelper(hostNameOrAddress, true, true, true, true, requestCallback, state);
  897.            
  898.             if (Logging.On)
  899.                 Logging.Exit(Logging.Sockets, "DNS", "BeginGetHostAddresses", asyncResult);
  900.             return asyncResult;
  901.         }
  902.         // BeginResolve
  903.        
  904.         public static IPAddress[] EndGetHostAddresses(IAsyncResult asyncResult)
  905.         {
  906.             if (Logging.On)
  907.                 Logging.Enter(Logging.Sockets, "DNS", "EndGetHostAddresses", asyncResult);
  908.            
  909.             IPHostEntry ipHostEntry = HostResolutionEndHelper(asyncResult);
  910.            
  911.             if (Logging.On)
  912.                 Logging.Exit(Logging.Sockets, "DNS", "EndGetHostAddresses", ipHostEntry);
  913.             return ipHostEntry.AddressList;
  914.         }
  915.         // EndResolveToAddresses
  916.        
  917.         static internal IAsyncResult UnsafeBeginGetHostAddresses(string hostName, AsyncCallback requestCallback, object state)
  918.         {
  919.             if (Logging.On)
  920.                 Logging.Enter(Logging.Sockets, "DNS", "UnsafeBeginGetHostAddresses", hostName);
  921.            
  922.             IAsyncResult asyncResult = HostResolutionBeginHelper(hostName, true, false, true, true, requestCallback, state);
  923.            
  924.             if (Logging.On)
  925.                 Logging.Exit(Logging.Sockets, "DNS", "UnsafeBeginGetHostAddresses", asyncResult);
  926.             return asyncResult;
  927.         }
  928.         // UnsafeBeginResolveToAddresses
  929.        
  930.         /// <devdoc>
  931.         /// <para>[To be supplied.]</para>
  932.         /// </devdoc>
  933.         [HostProtection(ExternalThreading = true)]
  934.         [Obsolete("BeginResolve is obsoleted for this type, please use BeginGetHostEntry instead. http://go.microsoft.com/fwlink/?linkid=14202")]
  935.         public static IAsyncResult BeginResolve(string hostName, AsyncCallback requestCallback, object stateObject)
  936.         {
  937.             if (Logging.On)
  938.                 Logging.Enter(Logging.Sockets, "DNS", "BeginResolve", hostName);
  939.            
  940.             IAsyncResult asyncResult = HostResolutionBeginHelper(hostName, false, true, false, false, requestCallback, stateObject);
  941.            
  942.             if (Logging.On)
  943.                 Logging.Exit(Logging.Sockets, "DNS", "BeginResolve", asyncResult);
  944.             return asyncResult;
  945.         }
  946.         // BeginResolve
  947.        
  948.         [Obsolete("EndResolve is obsoleted for this type, please use EndGetHostEntry instead. http://go.microsoft.com/fwlink/?linkid=14202")]
  949.         public static IPHostEntry EndResolve(IAsyncResult asyncResult)
  950.         {
  951.             if (Logging.On)
  952.                 Logging.Enter(Logging.Sockets, "DNS", "EndResolve", asyncResult);
  953.            
  954.             IPHostEntry ipHostEntry = HostResolutionEndHelper(asyncResult);
  955.            
  956.             if (Logging.On)
  957.                 Logging.Exit(Logging.Sockets, "DNS", "EndResolve", ipHostEntry);
  958.             return ipHostEntry;
  959.         }
  960.         // EndResolve()
  961. /* Uncomment when needed.
  962.                 internal static IAsyncResult UnsafeBeginResolve(string hostName, AsyncCallback requestCallback, object stateObject)
  963.                 {
  964.                     if(Logging.On)Logging.Enter(Logging.Sockets, "DNS", "BeginResolve", hostName);
  965.        
  966.                     IAsyncResult asyncResult = HostResolutionBeginHelper(hostName, false, false, true, false, requestCallback, stateObject);
  967.        
  968.                     if(Logging.On)Logging.Exit(Logging.Sockets, "DNS", "BeginResolve", asyncResult);
  969.                     return asyncResult;
  970.                 } // UnsafeBeginResolve
  971.         */       
  972.        
  973.         //
  974.         // IPv6 Changes: Add getaddrinfo and getnameinfo methods.
  975.         //
  976.         unsafe private static IPHostEntry GetAddrInfo(string name)
  977.         {
  978.             //
  979.             // Use SocketException here to show operation not supported
  980.             // if, by some nefarious means, this method is called on an
  981.             // unsupported platform.
  982.             //
  983.             throw new SocketException(SocketError.OperationNotSupported);
  984.         }
  985.        
  986.         static internal string TryGetNameInfo(IPAddress addr, out SocketError errorCode)
  987.         {
  988.             //
  989.             // Use SocketException here to show operation not supported
  990.             // if, by some nefarious means, this method is called on an
  991.             // unsupported platform.
  992.             //
  993.             throw new SocketException(SocketError.OperationNotSupported);
  994.         }
  995.        
  996.         private static bool TryParseAsIP(string address, out IPAddress ip)
  997.         {
  998.             return IPAddress.TryParse(address, out ip) && ((ip.AddressFamily == AddressFamily.InterNetwork && Socket.SupportsIPv4) || (ip.AddressFamily == AddressFamily.InterNetworkV6 && Socket.OSSupportsIPv6));
  999.         }
  1000.     }
  1001. }

Developer Fusion