IPAddress.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. //
  2. // System.Net.IPAddress.cs
  3. //
  4. // Author:
  5. // Miguel de Icaza ([email protected])
  6. // Lawrence Pit ([email protected])
  7. //
  8. // (C) Ximian, Inc. http://www.ximian.com
  9. //
  10. //
  11. // Note: the address is stored in host order
  12. using System;
  13. using System.Globalization;
  14. using System.Net.Sockets;
  15. using System.Runtime.InteropServices;
  16. namespace System.Net {
  17. /// <remarks>
  18. /// Encapsulates an IP Address.
  19. /// </remarks>
  20. [Serializable]
  21. public class IPAddress {
  22. // Don't change the name of this field without also
  23. // changing socket-io.c in the runtime
  24. private long address;
  25. public static readonly IPAddress Any = new IPAddress(0);
  26. public static readonly IPAddress Broadcast = IPAddress.Parse ("255.255.255.255");
  27. public static readonly IPAddress Loopback = IPAddress.Parse ("127.0.0.1");
  28. public static readonly IPAddress None = IPAddress.Parse ("255.255.255.255");
  29. private static short SwapShort (short number)
  30. {
  31. return (short) ( ((number >> 8) & 0xFF) + ((number << 8) & 0xFF00) );
  32. }
  33. private static int SwapInt (int number)
  34. {
  35. byte b0 = (byte) ((number >> 24) & 0xFF);
  36. byte b1 = (byte) ((number >> 16) & 0xFF);
  37. byte b2 = (byte) ((number >> 8) & 0xFF);
  38. byte b3 = (byte) (number & 0xFF);
  39. return b0 + (b1 << 8) + (b2 << 16) + (b3 << 24);
  40. }
  41. private static long SwapLong (long number)
  42. {
  43. byte b0 = (byte) ((number >> 56) & 0xFF);
  44. byte b1 = (byte) ((number >> 48) & 0xFF);
  45. byte b2 = (byte) ((number >> 40) & 0xFF);
  46. byte b3 = (byte) ((number >> 32) & 0xFF);
  47. byte b4 = (byte) ((number >> 24) & 0xFF);
  48. byte b5 = (byte) ((number >> 16) & 0xFF);
  49. byte b6 = (byte) ((number >> 8) & 0xFF);
  50. byte b7 = (byte) (number & 0xFF);
  51. return (long) b0 + ((long) b1 << 8) + ((long) b2 << 16) + ((long) b3 << 24) + ((long) b4 << 32) + ((long) b5 << 40) + ((long) b6 << 48) + ((long) b7 << 56);
  52. }
  53. public static short HostToNetworkOrder(short host) {
  54. if (!BitConverter.IsLittleEndian)
  55. return(host);
  56. return SwapShort (host);
  57. }
  58. public static int HostToNetworkOrder(int host) {
  59. if (!BitConverter.IsLittleEndian)
  60. return(host);
  61. return SwapInt (host);
  62. }
  63. public static long HostToNetworkOrder(long host) {
  64. if (!BitConverter.IsLittleEndian)
  65. return(host);
  66. return SwapLong (host);
  67. }
  68. public static short NetworkToHostOrder(short network) {
  69. if (!BitConverter.IsLittleEndian)
  70. return(network);
  71. return SwapShort (network);
  72. }
  73. public static int NetworkToHostOrder(int network) {
  74. if (!BitConverter.IsLittleEndian)
  75. return(network);
  76. return SwapInt (network);
  77. }
  78. public static long NetworkToHostOrder(long network) {
  79. if (!BitConverter.IsLittleEndian)
  80. return(network);
  81. return SwapLong (network);
  82. }
  83. /// <summary>
  84. /// Constructor from a 32-bit constant with its bytes
  85. /// in network order.
  86. /// </summary>
  87. public IPAddress (long addr)
  88. {
  89. Address = addr;
  90. }
  91. public static IPAddress Parse (string ip)
  92. {
  93. if (ip == null)
  94. throw new ArgumentNullException ("null ip string");
  95. if (ip.Length == 0 || ip [0] == ' ')
  96. return new IPAddress (0);
  97. int pos = ip.IndexOf (' ');
  98. if (pos != -1)
  99. ip = ip.Substring (0, pos);
  100. else if (ip [ip.Length - 1] == '.')
  101. throw new FormatException ("An invalid IP address was specified");
  102. string [] ips = ip.Split (new char [] {'.'});
  103. if (ips.Length > 4)
  104. throw new FormatException ("An invalid IP address was specified");
  105. // Make the number in network order
  106. try {
  107. long a = 0;
  108. byte val = 0;
  109. for (int i = 0; i < ips.Length; i++) {
  110. string subnet = ips [i];
  111. if ((3 <= subnet.Length && subnet.Length <= 4) &&
  112. (subnet [0] == '0') &&
  113. (subnet [1] == 'x' || subnet [2] == 'X')) {
  114. if (subnet.Length == 3)
  115. val = (byte) Uri.FromHex (subnet [2]);
  116. else
  117. val = (byte) ((Uri.FromHex (subnet [2]) << 4) | Uri.FromHex (subnet [3]));
  118. } else if (subnet.Length == 0)
  119. val = 0;
  120. else
  121. val = Byte.Parse (subnet, NumberStyles.None);
  122. if (ips.Length < 4 && i == (ips.Length - 1))
  123. i = 3;
  124. a |= (long) val << (i << 3);
  125. }
  126. return (new IPAddress (a));
  127. } catch (Exception) {
  128. throw new FormatException ("An invalid IP address was specified");
  129. }
  130. }
  131. public long Address {
  132. get {
  133. return address;
  134. }
  135. set {
  136. /* no need to do this test, ms.net accepts any value.
  137. if (value < 0 || value > 0x00000000FFFFFFFF)
  138. throw new ArgumentOutOfRangeException (
  139. "the address must be between 0 and 0xFFFFFFFF");
  140. */
  141. address = value;
  142. }
  143. }
  144. public AddressFamily AddressFamily {
  145. get {
  146. return(AddressFamily.InterNetwork);
  147. }
  148. }
  149. /// <summary>
  150. /// Used to tell whether an address is a loopback.
  151. /// All IP addresses of the form 127.X.Y.Z, where X, Y, and Z are in
  152. /// the range 0-255, are loopback addresses.
  153. /// </summary>
  154. /// <param name="addr">Address to compare</param>
  155. /// <returns></returns>
  156. public static bool IsLoopback (IPAddress addr)
  157. {
  158. return (addr.address & 0xFF) == 127;
  159. }
  160. /// <summary>
  161. /// Overrides System.Object.ToString to return
  162. /// this object rendered in a quad-dotted notation
  163. /// </summary>
  164. public override string ToString ()
  165. {
  166. return ToString (address);
  167. }
  168. /// <summary>
  169. /// Returns this object rendered in a quad-dotted notation
  170. /// </summary>
  171. static string ToString (long addr)
  172. {
  173. // addr is in network order
  174. return (addr & 0xff).ToString () + "." +
  175. ((addr >> 8) & 0xff).ToString () + "." +
  176. ((addr >> 16) & 0xff).ToString () + "." +
  177. ((addr >> 24) & 0xff).ToString ();
  178. }
  179. /// <returns>
  180. /// Whether both objects are equal.
  181. /// </returns>
  182. public override bool Equals (object other)
  183. {
  184. if (other is System.Net.IPAddress){
  185. return Address == ((System.Net.IPAddress) other).Address;
  186. }
  187. return false;
  188. }
  189. public override int GetHashCode ()
  190. {
  191. return (int)Address;
  192. }
  193. }
  194. }