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

  1. //------------------------------------------------------------------------------
  2. // <copyright file="IPAddress.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.Net.Sockets;
  18.     using System.Globalization;
  19.     using System.Text;
  20.     using System.Security.Permissions;
  21.    
  22.     /// <devdoc>
  23.     /// <para>Provides an internet protocol (IP) address.</para>
  24.     /// </devdoc>
  25.     [Serializable()]
  26.     public class IPAddress
  27.     {
  28.        
  29.         public static readonly IPAddress Any = new IPAddress(0);
  30.         public static readonly IPAddress Loopback = new IPAddress(16777343);
  31.         public static readonly IPAddress Broadcast = new IPAddress(4294967295u);
  32.         public static readonly IPAddress None = Broadcast;
  33.        
  34.         internal const long LoopbackMask = 127;
  35.         internal const string InaddrNoneString = "255.255.255.255";
  36.         internal const string InaddrNoneStringHex = "0xff.0xff.0xff.0xff";
  37.         internal const string InaddrNoneStringOct = "0377.0377.0377.0377";
  38.        
  39.         //
  40.         // IPv6 Changes: make this internal so other NCL classes that understand about
  41.         // IPv4 and IPv4 can still access it rather than the obsolete property.
  42.         //
  43.         internal long m_Address;
  44.        
  45.         [NonSerialized()]
  46.         internal string m_ToString;
  47.        
  48.         public static readonly IPAddress IPv6Any = new IPAddress(new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  49.         0, 0, 0, 0, 0, 0}, 0);
  50.         public static readonly IPAddress IPv6Loopback = new IPAddress(new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  51.         0, 0, 0, 0, 0, 1}, 0);
  52.         public static readonly IPAddress IPv6None = new IPAddress(new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  53.         0, 0, 0, 0, 0, 0}, 0);
  54.        
  55.         /// <devdoc>
  56.         /// <para>
  57.         /// Default to IPv4 address
  58.         /// </para>
  59.         /// </devdoc>
  60.         private AddressFamily m_Family = AddressFamily.InterNetwork;
  61.         private ushort[] m_Numbers = new ushort[NumberOfLabels];
  62.         private long m_ScopeId = 0;
  63.         // really uint !
  64.         private int m_HashCode = 0;
  65.        
  66.         internal const int IPv4AddressBytes = 4;
  67.         internal const int IPv6AddressBytes = 16;
  68.        
  69.         internal const int NumberOfLabels = IPv6AddressBytes / 2;
  70.        
  71.        
  72.         /// <devdoc>
  73.         /// <para>
  74.         /// Initializes a new instance of the <see cref='System.Net.IPAddress'/>
  75.         /// class with the specified
  76.         /// address.
  77.         /// </para>
  78.         /// </devdoc>
  79.         public IPAddress(long newAddress)
  80.         {
  81.             if (newAddress < 0 || newAddress > 4294967295u) {
  82.                 throw new ArgumentOutOfRangeException("newAddress");
  83.             }
  84.             m_Address = newAddress;
  85.         }
  86.        
  87.        
  88.         /// <devdoc>
  89.         /// <para>
  90.         /// Constructor for an IPv6 Address with a specified Scope.
  91.         /// </para>
  92.         /// </devdoc>
  93.         public IPAddress(byte[] address, long scopeid)
  94.         {
  95.            
  96.             if (address == null) {
  97.                 throw new ArgumentNullException("address");
  98.             }
  99.            
  100.             if (address.Length != IPv6AddressBytes) {
  101.                 throw new ArgumentException(SR.GetString(SR.dns_bad_ip_address), "address");
  102.             }
  103.            
  104.             m_Family = AddressFamily.InterNetworkV6;
  105.            
  106.             for (int i = 0; i < NumberOfLabels; i++) {
  107.                 m_Numbers[i] = (ushort)(address[i * 2] * 256 + address[i * 2 + 1]);
  108.             }
  109.            
  110.             if (scopeid < 0 || scopeid > 4294967295u) {
  111.                 throw new ArgumentOutOfRangeException("scopeid");
  112.             }
  113.            
  114.             m_ScopeId = scopeid;
  115.         }
  116.         //
  117.         private IPAddress(ushort[] address, uint scopeid)
  118.         {
  119.             m_Family = AddressFamily.InterNetworkV6;
  120.             m_Numbers = address;
  121.             m_ScopeId = scopeid;
  122.         }
  123.        
  124.        
  125.         /// <devdoc>
  126.         /// <para>
  127.         /// Constructor for IPv4 and IPv6 Address.
  128.         /// </para>
  129.         /// </devdoc>
  130.         public IPAddress(byte[] address)
  131.         {
  132.             if (address == null) {
  133.                 throw new ArgumentNullException("address");
  134.             }
  135.             if (address.Length != IPv4AddressBytes && address.Length != IPv6AddressBytes) {
  136.                 throw new ArgumentException(SR.GetString(SR.dns_bad_ip_address), "address");
  137.             }
  138.            
  139.             if (address.Length == IPv4AddressBytes) {
  140.                 m_Family = AddressFamily.InterNetwork;
  141.                 m_Address = ((address[3] << 24 | address[2] << 16 | address[1] << 8 | address[0]) & 4294967295u);
  142.             }
  143.             else {
  144.                 m_Family = AddressFamily.InterNetworkV6;
  145.                
  146.                 for (int i = 0; i < NumberOfLabels; i++) {
  147.                     m_Numbers[i] = (ushort)(address[i * 2] * 256 + address[i * 2 + 1]);
  148.                 }
  149.             }
  150.         }
  151.        
  152.         //
  153.         // we need this internally since we need to interface with winsock
  154.         // and winsock only understands Int32
  155.         //
  156.         internal IPAddress(int newAddress)
  157.         {
  158.             m_Address = (long)newAddress & 4294967295u;
  159.         }
  160.        
  161.        
  162.        
  163.         /// <devdoc>
  164.         /// <para>Converts an IP address string to an <see cref='System.Net.IPAddress'/>
  165.         /// instance.</para>
  166.         /// </devdoc>
  167.         public static bool TryParse(string ipString, out IPAddress address)
  168.         {
  169.             address = InternalParse(ipString, true);
  170.             return (address != null);
  171.         }
  172.        
  173.         public static IPAddress Parse(string ipString)
  174.         {
  175.             return InternalParse(ipString, false);
  176.         }
  177.        
  178.         private static IPAddress InternalParse(string ipString, bool tryParse)
  179.         {
  180.             if (ipString == null) {
  181.                 throw new ArgumentNullException("ipString");
  182.             }
  183.            
  184.             //
  185.             // IPv6 Changes: Detect probable IPv6 addresses and use separate
  186.             // parse method.
  187.             //
  188.             if (ipString.IndexOf(':') != -1) {
  189.                
  190.                 // IPv6 addresses not supported for FEATURE_PAL
  191.                 throw new SocketException(SocketError.OperationNotSupported);
  192.             }
  193.             else {
  194.                 // Cannot be an IPv6 address, so use the IPv4 routines to
  195.                 // parse the string representation. First check a heuristic to prevent the p/invoke as much as possible. We
  196.                 // know the first character must be a digit (0 for the "0x" in hex), and the last character must be hex.
  197.                 int address = -1;
  198.                 if (ipString.Length > 0 && ipString[0] >= '0' && ipString[0] <= '9' && ((ipString[ipString.Length - 1] >= '0' && ipString[ipString.Length - 1] <= '9') || (ipString[ipString.Length - 1] >= 'a' && ipString[ipString.Length - 1] <= 'f') || (ipString[ipString.Length - 1] >= 'A' && ipString[ipString.Length - 1] <= 'F'))) {
  199.                     Socket.InitializeSockets();
  200.                     address = UnsafeNclNativeMethods.OSSOCK.inet_addr(ipString);
  201.                 }
  202.                 #if BIGENDIAN
  203.                 // OSSOCK.inet_addr always returns IP address as a byte array converted to int.
  204.                 // thus we need to convert the address into a uniform integer value.
  205.                 address = (int)(((uint)address << 24) | (((uint)address & 65280) << 8) | (((uint)address >> 8) & 65280) | ((uint)address >> 24));
  206.                 #endif
  207.                
  208.                 GlobalLog.Print("IPAddress::Parse() ipString:" + ValidationHelper.ToString(ipString) + " inet_addr() returned address:" + address);
  209.                
  210.                 if (address == -1 && string.Compare(ipString, InaddrNoneString, StringComparison.Ordinal) != 0 && string.Compare(ipString, InaddrNoneStringHex, StringComparison.OrdinalIgnoreCase) != 0 && string.Compare(ipString, InaddrNoneStringOct, StringComparison.Ordinal) != 0) {
  211.                    
  212.                     if (tryParse) {
  213.                         return null;
  214.                     }
  215.                    
  216.                     throw new FormatException(SR.GetString(SR.dns_bad_ip_address));
  217.                 }
  218.                
  219.                 IPAddress returnValue = new IPAddress(address);
  220.                
  221.                 return returnValue;
  222.             }
  223.         }
  224.         // Parse
  225.        
  226.        
  227. /**
  228.         * @deprecated IPAddress.Address is address family dependant, use Equals method for comparison.
  229.         */       
  230.         /// <devdoc>
  231.         /// <para>
  232.         /// Mark this as deprecated.
  233.         /// </para>
  234.         /// </devdoc>
  235.         [Obsolete("This property has been deprecated. It is address family dependent. Please use IPAddress.Equals method to perform comparisons. http://go.microsoft.com/fwlink/?linkid=14202")]
  236.         public long Address {
  237.             get {
  238.                 //
  239.                 // IPv6 Changes: Can't do this for IPv6, so throw an exception.
  240.                 //
  241.                 //
  242.                 if (m_Family == AddressFamily.InterNetworkV6) {
  243.                     throw new SocketException(SocketError.OperationNotSupported);
  244.                 }
  245.                 else {
  246.                     return m_Address;
  247.                 }
  248.             }
  249.             set {
  250.                 //
  251.                 // IPv6 Changes: Can't do this for IPv6 addresses
  252.                 if (m_Family == AddressFamily.InterNetworkV6) {
  253.                     throw new SocketException(SocketError.OperationNotSupported);
  254.                 }
  255.                 else {
  256.                     if (m_Address != value) {
  257.                         m_ToString = null;
  258.                         m_Address = value;
  259.                     }
  260.                 }
  261.             }
  262.         }
  263.        
  264.         /// <devdoc>
  265.         /// <para>
  266.         /// Provides a copy of the IPAddress internals as an array of bytes.
  267.         /// </para>
  268.         /// </devdoc>
  269.         public byte[] GetAddressBytes()
  270.         {
  271.             byte[] bytes;
  272.             if (m_Family == AddressFamily.InterNetworkV6) {
  273.                 bytes = new byte[NumberOfLabels * 2];
  274.                
  275.                 int j = 0;
  276.                 for (int i = 0; i < NumberOfLabels; i++) {
  277.                     bytes[j++] = (byte)((this.m_Numbers[i] >> 8) & 255);
  278.                     bytes[j++] = (byte)((this.m_Numbers[i]) & 255);
  279.                 }
  280.             }
  281.             else {
  282.                 bytes = new byte[IPv4AddressBytes];
  283.                 bytes[0] = (byte)(m_Address);
  284.                 bytes[1] = (byte)(m_Address >> 8);
  285.                 bytes[2] = (byte)(m_Address >> 16);
  286.                 bytes[3] = (byte)(m_Address >> 24);
  287.             }
  288.             return bytes;
  289.         }
  290.        
  291.         public AddressFamily AddressFamily {
  292.             get { return m_Family; }
  293.         }
  294.        
  295.         /// <devdoc>
  296.         /// <para>
  297.         /// IPv6 Scope identifier. This is really a uint32, but that isn't CLS compliant
  298.         /// </para>
  299.         /// </devdoc>
  300.         public long ScopeId {
  301.             get {
  302.                 //
  303.                 // Not valid for IPv4 addresses
  304.                 //
  305.                 if (m_Family == AddressFamily.InterNetwork) {
  306.                     throw new SocketException(SocketError.OperationNotSupported);
  307.                 }
  308.                
  309.                 return m_ScopeId;
  310.             }
  311.             set {
  312.                 //
  313.                 // Not valid for IPv4 addresses
  314.                 //
  315.                 if (m_Family == AddressFamily.InterNetwork) {
  316.                     throw new SocketException(SocketError.OperationNotSupported);
  317.                 }
  318.                
  319.                 if (value < 0 || value > 4294967295u) {
  320.                     throw new ArgumentOutOfRangeException("value");
  321.                 }
  322.                 if (m_ScopeId != value) {
  323.                     m_Address = value;
  324.                     m_ScopeId = value;
  325.                 }
  326.             }
  327.         }
  328.        
  329.         /// <devdoc>
  330.         /// <para>
  331.         /// Converts the Internet address to either standard dotted quad format
  332.         /// or standard IPv6 representation.
  333.         /// </para>
  334.         /// </devdoc>
  335.         public override string ToString()
  336.         {
  337.             if (m_ToString == null) {
  338.                 //
  339.                 // IPv6 Changes: generate the IPV6 representation
  340.                 //
  341.                 if (m_Family == AddressFamily.InterNetworkV6) {
  342.                    
  343.                     // IPv6 addresses not supported for FEATURE_PAL
  344.                     throw new SocketException(SocketError.OperationNotSupported);
  345.                 }
  346.                 else {
  347.                     unsafe {
  348.                         const int MaxSize = 15;
  349.                         int offset = MaxSize;
  350.                         char* addressString = stackalloc char[MaxSize];
  351.                         int number = (int)((m_Address >> 24) & 255);
  352.                         do {
  353.                             addressString[--offset] = (char)('0' + number % 10);
  354.                             number = number / 10;
  355.                         }
  356.                         while (number > 0);
  357.                         addressString[--offset] = '.';
  358.                         number = (int)((m_Address >> 16) & 255);
  359.                         do {
  360.                             addressString[--offset] = (char)('0' + number % 10);
  361.                             number = number / 10;
  362.                         }
  363.                         while (number > 0);
  364.                         addressString[--offset] = '.';
  365.                         number = (int)((m_Address >> 8) & 255);
  366.                         do {
  367.                             addressString[--offset] = (char)('0' + number % 10);
  368.                             number = number / 10;
  369.                         }
  370.                         while (number > 0);
  371.                         addressString[--offset] = '.';
  372.                         number = (int)(m_Address & 255);
  373.                         do {
  374.                             addressString[--offset] = (char)('0' + number % 10);
  375.                             number = number / 10;
  376.                         }
  377.                         while (number > 0);
  378.                         m_ToString = new string(addressString, offset, MaxSize - offset);
  379.                     }
  380.                 }
  381.             }
  382.             return m_ToString;
  383.         }
  384.        
  385.         public static long HostToNetworkOrder(long host)
  386.         {
  387.             #if BIGENDIAN
  388.             return host;
  389.             #else
  390.             return (((long)HostToNetworkOrder((int)host) & 4294967295u) << 32) | ((long)HostToNetworkOrder((int)(host >> 32)) & 4294967295u);
  391.             #endif
  392.         }
  393.         public static int HostToNetworkOrder(int host)
  394.         {
  395.             #if BIGENDIAN
  396.             return host;
  397.             #else
  398.             return (((int)HostToNetworkOrder((short)host) & 65535) << 16) | ((int)HostToNetworkOrder((short)(host >> 16)) & 65535);
  399.             #endif
  400.         }
  401.         public static short HostToNetworkOrder(short host)
  402.         {
  403.             #if BIGENDIAN
  404.             return host;
  405.             #else
  406.             return (short)((((int)host & 255) << 8) | (int)((host >> 8) & 255));
  407.             #endif
  408.         }
  409.         public static long NetworkToHostOrder(long network)
  410.         {
  411.             return HostToNetworkOrder(network);
  412.         }
  413.         public static int NetworkToHostOrder(int network)
  414.         {
  415.             return HostToNetworkOrder(network);
  416.         }
  417.         public static short NetworkToHostOrder(short network)
  418.         {
  419.             return HostToNetworkOrder(network);
  420.         }
  421.        
  422.         public static bool IsLoopback(IPAddress address)
  423.         {
  424.             if (address.m_Family == AddressFamily.InterNetworkV6) {
  425.                 //
  426.                 // Do Equals test for IPv6 addresses
  427.                 //
  428.                 return address.Equals(IPv6Loopback);
  429.             }
  430.             else {
  431.                 return ((address.m_Address & IPAddress.LoopbackMask) == (IPAddress.Loopback.m_Address & IPAddress.LoopbackMask));
  432.             }
  433.         }
  434.        
  435.         internal bool IsBroadcast {
  436.             get {
  437.                 if (m_Family == AddressFamily.InterNetworkV6) {
  438.                     //
  439.                     // No such thing as a broadcast address for IPv6
  440.                     //
  441.                     return false;
  442.                 }
  443.                 else {
  444.                     return m_Address == Broadcast.m_Address;
  445.                 }
  446.             }
  447.         }
  448.        
  449.         /// <devdoc>
  450.         /// <para>
  451.         /// V.Next: Determines if an address is an IPv6 Multicast address
  452.         /// </para>
  453.         /// </devdoc>
  454.         public bool IsIPv6Multicast {
  455.             get { return (m_Family == AddressFamily.InterNetworkV6) && ((this.m_Numbers[0] & 65280) == 65280); }
  456.         }
  457.        
  458.        
  459. /*
  460.         //                         
  461.         internal bool IsIPv6MulticastNodeLocal() {
  462.             return ( IsIPv6Multicast ) &&
  463.                   ( ( this.m_Numbers[0] & 0x000F ) == 1 );
  464.         }
  465.         */       
  466.        
  467.         /// <devdoc>
  468.         /// <para>
  469.         /// V.Next: Determines if an address is an IPv6 Multicast Link local address
  470.         /// </para>
  471.         /// </devdoc>
  472. /*
  473.         //                                   
  474.         internal bool IsIPv6MulticastLinkLocal() {
  475.             return ( IsIPv6Multicast ) &&
  476.                   ( ( this.m_Numbers[0] & 0x000F ) == 0x0002 );
  477.         }
  478.         */       
  479.        
  480. /*
  481.         //                         
  482.         internal bool IsIPv6MulticastSiteLocal() {
  483.             return ( IsIPv6Multicast ) &&
  484.                   ( ( this.m_Numbers[0] & 0x000F ) == 0x0005 );
  485.         }
  486.         */       
  487.        
  488.         /// <devdoc>
  489.         /// <para>
  490.         /// V.Next: Determines if an address is an IPv6 Multicast Org local address
  491.         /// </para>
  492.         /// </devdoc>
  493. /*
  494.         //                                   
  495.         internal bool IsIPv6MulticastOrgLocal() {
  496.             return ( IsIPv6Multicast ) &&
  497.                   ( ( this.m_Numbers[0] & 0x000F ) == 0x0008 );
  498.         }
  499.         */       
  500.        
  501. /*
  502.         //                         
  503.         internal bool IsIPv6MulticastGlobal() {
  504.             return ( IsIPv6Multicast ) &&
  505.                   ( ( this.m_Numbers[0] & 0x000F ) == 0x000E );
  506.         }
  507.         */       
  508.        
  509.         /// <devdoc>
  510.         /// <para>
  511.         /// V.Next: Determines if an address is an IPv6 Link Local address
  512.         /// </para>
  513.         /// </devdoc>
  514.         public bool IsIPv6LinkLocal {
  515.             get { return (m_Family == AddressFamily.InterNetworkV6) && ((this.m_Numbers[0] & 65472) == 65152); }
  516.         }
  517.        
  518.         /// <devdoc>
  519.         /// <para>
  520.         /// V.Next: Determines if an address is an IPv6 Site Local address
  521.         /// </para>
  522.         /// </devdoc>
  523.         public bool IsIPv6SiteLocal {
  524.             get { return (m_Family == AddressFamily.InterNetworkV6) && ((this.m_Numbers[0] & 65472) == 65216); }
  525.         }
  526.        
  527. /*
  528.         //                         
  529.         internal bool IsIPv4Mapped() {
  530.             return ( m_Family == AddressFamily.InterNetworkV6 ) &&
  531.                   ( m_Numbers[0] == 0x0000 ) &&
  532.                   ( m_Numbers[1] == 0x0000 ) &&
  533.                   ( m_Numbers[2] == 0x0000 ) &&
  534.                   ( m_Numbers[3] == 0x0000 ) &&
  535.                   ( m_Numbers[4] == 0x0000 ) &&
  536.                   ( m_Numbers[5] == 0xffff );
  537.         }
  538.         */       
  539.        
  540. /*
  541.         //                         
  542.         internal bool IsIPv4Compatible() {
  543.             return ( m_Family == AddressFamily.InterNetworkV6 ) &&
  544.                   ( m_Numbers[0] == 0x0000 ) &&
  545.                   ( m_Numbers[1] == 0x0000 ) &&
  546.                   ( m_Numbers[2] == 0x0000 ) &&
  547.                   ( m_Numbers[3] == 0x0000 ) &&
  548.                   ( m_Numbers[4] == 0x0000 ) &&
  549.                   ( m_Numbers[5] == 0x0000 ) &&
  550.                   !( ( m_Numbers[6] == 0x0000 )              &&
  551.                       ( ( m_Numbers[7] & 0xFF00 ) == 0x0000 ) &&
  552.                       ( ( ( m_Numbers[7] & 0x00FF ) == 0x0000 ) || ( m_Numbers[7] & 0x00FF ) == 0x0001 ) );
  553.         }
  554.         */       
  555.        
  556.         internal bool Equals(object comparand, bool compareScopeId)
  557.         {
  558.             if (!(comparand is IPAddress)) {
  559.                 return false;
  560.             }
  561.             //
  562.             // Compare families before address representations
  563.             //
  564.             if (m_Family != ((IPAddress)comparand).m_Family) {
  565.                 return false;
  566.             }
  567.             if (m_Family == AddressFamily.InterNetworkV6) {
  568.                 //
  569.                 // For IPv6 addresses, we must compare the full 128bit
  570.                 // representation.
  571.                 //
  572.                 for (int i = 0; i < NumberOfLabels; i++) {
  573.                     if (((IPAddress)comparand).m_Numbers[i] != this.m_Numbers[i])
  574.                         return false;
  575.                 }
  576.                 //
  577.                 // In addition, the scope id's must match as well
  578.                 //
  579.                 if (((IPAddress)comparand).m_ScopeId == this.m_ScopeId)
  580.                     return true;
  581.                 else
  582.                     return (compareScopeId ? false : true);
  583.             }
  584.             else {
  585.                 //
  586.                 // For IPv4 addresses, compare the integer representation.
  587.                 //
  588.                 return ((IPAddress)comparand).m_Address == this.m_Address;
  589.             }
  590.         }
  591.        
  592.         /// <devdoc>
  593.         /// <para>
  594.         /// Compares two IP addresses.
  595.         /// </para>
  596.         /// </devdoc>
  597.         public override bool Equals(object comparand)
  598.         {
  599.             return Equals(comparand, true);
  600.         }
  601.        
  602.         public override int GetHashCode()
  603.         {
  604.             //
  605.             // For IPv6 addresses, we cannot simply return the integer
  606.             // representation as the hashcode. Instead, we calculate
  607.             // the hashcode from the string representation of the address.
  608.             //
  609.             if (m_Family == AddressFamily.InterNetworkV6) {
  610.                 if (m_HashCode == 0)
  611.                     m_HashCode = Uri.CalculateCaseInsensitiveHashCode(ToString());
  612.                
  613.                 return m_HashCode;
  614.             }
  615.             else {
  616.                 //
  617.                 // For IPv4 addresses, we can simply use the integer
  618.                 // representation.
  619.                 //
  620.                 return unchecked((int)m_Address);
  621.             }
  622.         }
  623.        
  624.         // For security, we need to be able to take an IPAddress and make a copy that's immutable and not derived.
  625.         internal IPAddress Snapshot()
  626.         {
  627.             switch (m_Family) {
  628.                 case AddressFamily.InterNetwork:
  629.                     return new IPAddress(m_Address);
  630.                 case AddressFamily.InterNetworkV6:
  631.                    
  632.                     return new IPAddress(m_Numbers, (uint)m_ScopeId);
  633.             }
  634.            
  635.             throw new InternalException();
  636.         }
  637.     }
  638.     // class IPAddress
  639. }
  640. // namespace System.Net

Developer Fusion