Dns.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. // System.Net.Dns.cs
  2. //
  3. // Author: Mads Pultz ([email protected])
  4. //
  5. // (C) Mads Pultz, 2001
  6. using System;
  7. using System.Net.Sockets;
  8. using System.Text;
  9. using System.Collections;
  10. using System.Runtime.InteropServices;
  11. namespace System.Net {
  12. public sealed class Dns {
  13. /// <summary>
  14. /// This class conforms to the C structure <c>hostent</c> and is used
  15. /// by the Dns class when doing native calls.
  16. /// </summary>
  17. [StructLayout(LayoutKind.Sequential)]
  18. private unsafe class Hostent {
  19. public string h_name; /* official name */
  20. public byte** h_aliases; /* alias list */
  21. public short h_addrtype; /* address type */
  22. public short h_length; /* address length */
  23. public byte** h_addr_list; /* address list */
  24. }
  25. public static IAsyncResult BeginGetHostByName(string hostName,
  26. AsyncCallback requestCallback,
  27. object stateObject) {
  28. // TODO
  29. throw new NotImplementedException();
  30. }
  31. public static IAsyncResult BeginResolve(string hostName,
  32. AsyncCallback requestCallback,
  33. object stateObject) {
  34. // TODO
  35. throw new NotImplementedException();
  36. }
  37. public static IPHostEntry EndGetHostByName(IAsyncResult asyncResult) {
  38. // TODO
  39. throw new NotImplementedException();
  40. }
  41. public static IPHostEntry EndResolve(IAsyncResult asyncResult) {
  42. // TODO
  43. throw new NotImplementedException();
  44. }
  45. /// <param name=hostName>
  46. /// IP address in network byte order (e.g. Big-Endian).
  47. /// </param>
  48. /// <param name=length>
  49. /// Length of IP address
  50. /// </param>
  51. /// <param name=type>
  52. /// Type (should be 2, equals AF_INET)
  53. /// </param>
  54. [DllImport("cygwin1", EntryPoint="gethostbyaddr")]
  55. private static extern IntPtr _GetHostByAddress(byte[] hostName,
  56. short length,
  57. short type);
  58. /// <param name=address>
  59. /// IP address in network byte order (e.g. Big-Endian).
  60. /// </param>
  61. private static IPHostEntry GetHostByAddress(long address) {
  62. short length = 4;
  63. if (address > uint.MaxValue)
  64. length = 8;
  65. byte[] addr = new byte[length];
  66. for(int i = length - 1, j = 0; i >= 0; --i, ++j) {
  67. byte b = (byte)(address >> i * 8);
  68. Console.WriteLine(b);
  69. addr[j] = b;
  70. }
  71. IntPtr p = _GetHostByAddress(addr, length, 2); // TODO: set type
  72. if (p == IntPtr.Zero)
  73. throw new SocketException(); // TODO: set error code
  74. Hostent h = new Hostent();
  75. System.Runtime.InteropServices.Marshal.PtrToStructure(p, h);
  76. return ToIPHostEntry(h);
  77. }
  78. public static IPHostEntry GetHostByAddress(IPAddress address) {
  79. if (address == null)
  80. throw new ArgumentNullException();
  81. return GetHostByAddress(IPAddress.HostToNetworkOrder(address.Address));
  82. }
  83. public static IPHostEntry GetHostByAddress(string address) {
  84. if (address == null)
  85. throw new ArgumentNullException();
  86. return GetHostByAddress(CreateAddress(address));
  87. }
  88. /*
  89. [DllImport("cygwin1", EntryPoint="h_errno")]
  90. private static extern int _h_errno;
  91. */
  92. [DllImport("cygwin1", EntryPoint="gethostbyname")]
  93. private static extern IntPtr _GetHostByName(string hostName);
  94. public static IPHostEntry GetHostByName(string hostName) {
  95. if (hostName == null)
  96. throw new ArgumentNullException();
  97. IntPtr p = _GetHostByName(hostName);
  98. // int errNo = _h_errno;
  99. if (p == IntPtr.Zero)
  100. throw new SocketException(); // TODO: set error code
  101. Hostent h = new Hostent();
  102. System.Runtime.InteropServices.Marshal.PtrToStructure(p, h);
  103. return ToIPHostEntry(h);
  104. }
  105. /// <summary>
  106. /// This method returns the host name associated with the local host.
  107. /// </summary>
  108. public static string GetHostName() {
  109. IPHostEntry h = GetHostByAddress("127.0.0.1");
  110. return h.HostName;
  111. }
  112. /// <param name=address>
  113. /// IP address in Little-Endian byte order.
  114. /// </param>
  115. /// <returns>
  116. /// IP address in dotted notation form.
  117. /// </returns>
  118. public static string IpToString(int address) {
  119. address = IPAddress.HostToNetworkOrder(address);
  120. StringBuilder res = new StringBuilder();
  121. for(int i = 3; i > 0; --i) {
  122. byte b = (byte)(address >> i * 8);
  123. res.Append(b);
  124. res.Append('.');
  125. }
  126. res.Append((byte)address);
  127. return res.ToString();
  128. }
  129. /// <summary>
  130. /// This method resovles a DNS-style host name or IP
  131. /// address.
  132. /// </summary>
  133. /// <param name=hostName>
  134. /// A string containing either a DNS-style host name (e.g.
  135. /// www.go-mono.com) or IP address (e.g. 193.36.10.10).
  136. /// </param>
  137. public static IPHostEntry Resolve(string hostName) {
  138. if (hostName == null)
  139. throw new ArgumentNullException();
  140. try {
  141. long addr = CreateAddress(hostName);
  142. if (addr > uint.MaxValue)
  143. throw new FormatException("Only IP version 4 addresses are supported");
  144. return GetHostByAddress(addr);
  145. } catch (FormatException) {
  146. return GetHostByName(hostName);
  147. }
  148. }
  149. /// <remarks>
  150. /// Utility method. This method converts a Hostent instance to a
  151. /// IPHostEntry instance.
  152. /// </remarks>
  153. /// <param name=h>
  154. /// Object which should be mapped to a IPHostEntry instance.
  155. /// </param>
  156. private static unsafe IPHostEntry ToIPHostEntry(Hostent h) {
  157. IPHostEntry res = new IPHostEntry();
  158. // Set host name
  159. res.HostName = h.h_name;
  160. // Set IP address list
  161. byte** p = h.h_addr_list;
  162. ArrayList tmp = new ArrayList(1);
  163. while (*p != null) {
  164. tmp.Add(CreateIPAddress(*p, h.h_length));
  165. ++p;
  166. }
  167. IPAddress[] addr_list = new IPAddress[tmp.Count];
  168. for(int i = 0; i < tmp.Count; ++i)
  169. addr_list[i] = (IPAddress)tmp[i];
  170. res.AddressList = addr_list;
  171. // Set IP aliases
  172. p = h.h_aliases;
  173. tmp.Clear();
  174. while (*p != null) {
  175. tmp.Add(new string((sbyte*)*p));
  176. ++p;
  177. }
  178. string[] aliases = new string[tmp.Count];
  179. for(int i = 0; i < tmp.Count; ++i)
  180. aliases[i] = (string)tmp[i];
  181. res.Aliases = aliases;
  182. return res;
  183. }
  184. /// <summary>
  185. /// Utility method. Convert IP address in dotted notation
  186. /// to IP address.
  187. /// </summary>
  188. private static long CreateAddress(string address) {
  189. string[] tokens = address.Split('.');
  190. if (tokens.Length % 4 != 0)
  191. throw new FormatException("IP address has invalid length");
  192. long addr = 0;
  193. for(int i = 0, j = tokens.Length - 1; i < tokens.Length; ++i, --j) {
  194. try {
  195. addr = addr | (((long)byte.Parse(tokens[i])) << j * 8);
  196. } catch (OverflowException) {
  197. throw new FormatException("Invalid IP address format");
  198. }
  199. }
  200. return addr;
  201. }
  202. /// <summary>
  203. /// Utility method. This method creates a IP address.
  204. /// </summary>
  205. /// <param name=addr>
  206. /// IP address in network byte order (e.g. Big-Endian).
  207. /// </param>
  208. /// <param name=length>
  209. /// Length of IP address (4 or 8 bytes).
  210. /// </param>
  211. private static unsafe IPAddress CreateIPAddress(byte* addr, short length) {
  212. byte* p = addr;
  213. long res = 0;
  214. for(int i = 0, j = length - 1; i < length; ++i, --j) {
  215. res += *p << j * 8;
  216. ++p;
  217. }
  218. if (res > uint.MaxValue)
  219. return new IPAddress(IPAddress.NetworkToHostOrder(res));
  220. else
  221. return new IPAddress(IPAddress.NetworkToHostOrder((int)res));
  222. }
  223. }
  224. }