3 // Author: Mads Pultz (mpultz@diku.dk)
5 // (C) Mads Pultz, 2001
8 using System.Net.Sockets;
10 using System.Collections;
11 using System.Runtime.InteropServices;
13 namespace System.Net {
15 public sealed class Dns {
18 /// This class conforms to the C structure <c>hostent</c> and is used
19 /// by the Dns class when doing native calls.
21 [StructLayout(LayoutKind.Sequential)]
22 private unsafe class Hostent {
23 public string h_name; /* official name */
24 public byte** h_aliases; /* alias list */
25 public short h_addrtype; /* address type */
26 public short h_length; /* address length */
27 public byte** h_addr_list; /* address list */
30 public static IAsyncResult BeginGetHostByName(string hostName,
31 AsyncCallback requestCallback,
34 throw new NotImplementedException();
37 public static IAsyncResult BeginResolve(string hostName,
38 AsyncCallback requestCallback,
41 throw new NotImplementedException();
44 public static IPHostEntry EndGetHostByName(IAsyncResult asyncResult) {
46 throw new NotImplementedException();
49 public static IPHostEntry EndResolve(IAsyncResult asyncResult) {
51 throw new NotImplementedException();
54 /// <param name=hostName>
55 /// IP address in network byte order (e.g. Big-Endian).
57 /// <param name=length>
58 /// Length of IP address
61 /// Type (should be 2, equals AF_INET)
63 [DllImport("cygwin1", EntryPoint="gethostbyaddr")]
64 private static extern IntPtr _GetHostByAddress(byte[] hostName,
68 /// <param name=address>
69 /// IP address in network byte order (e.g. Big-Endian).
71 private static IPHostEntry GetHostByAddress(long address) {
73 if (address > uint.MaxValue)
75 byte[] addr = new byte[length];
76 for(int i = length - 1, j = 0; i >= 0; --i, ++j) {
77 byte b = (byte)(address >> i * 8);
78 // Console.WriteLine(b);
81 IntPtr p = _GetHostByAddress(addr, length, 2); // TODO: set type
83 throw new SocketException(); // TODO: set error code
84 Hostent h = new Hostent();
85 System.Runtime.InteropServices.Marshal.PtrToStructure(p, h);
86 return ToIPHostEntry(h);
89 public static IPHostEntry GetHostByAddress(IPAddress address) {
91 throw new ArgumentNullException();
92 return GetHostByAddress(IPAddress.HostToNetworkOrder(address.Address));
95 public static IPHostEntry GetHostByAddress(string address) {
97 throw new ArgumentNullException();
98 return GetHostByAddress(CreateAddress(address));
102 [DllImport("cygwin1", EntryPoint="h_errno")]
103 private static extern int _h_errno;
106 [DllImport("cygwin1", EntryPoint="gethostbyname")]
107 private static extern IntPtr _GetHostByName(string hostName);
109 public static IPHostEntry GetHostByName(string hostName) {
110 if (hostName == null)
111 throw new ArgumentNullException();
112 IntPtr p = _GetHostByName(hostName);
113 // int errNo = _h_errno;
114 if (p == IntPtr.Zero)
115 throw new SocketException(); // TODO: set error code
116 Hostent h = new Hostent();
117 System.Runtime.InteropServices.Marshal.PtrToStructure(p, h);
118 return ToIPHostEntry(h);
122 /// This method returns the host name associated with the local host.
124 public static string GetHostName() {
125 IPHostEntry h = GetHostByAddress("127.0.0.1");
129 /// <param name=address>
130 /// IP address in Little-Endian byte order.
133 /// IP address in dotted notation form.
135 public static string IpToString(int address) {
136 address = IPAddress.HostToNetworkOrder(address);
137 StringBuilder res = new StringBuilder();
138 for(int i = 3; i > 0; --i) {
139 byte b = (byte)(address >> i * 8);
143 res.Append((byte)address);
144 return res.ToString();
148 /// This method resovles a DNS-style host name or IP
151 /// <param name=hostName>
152 /// A string containing either a DNS-style host name (e.g.
153 /// www.go-mono.com) or IP address (e.g. 129.250.184.233).
155 public static IPHostEntry Resolve(string hostName) {
156 if (hostName == null)
157 throw new ArgumentNullException();
159 long addr = CreateAddress(hostName);
160 if (addr > uint.MaxValue)
161 throw new FormatException("Only IP version 4 addresses are supported");
162 return GetHostByAddress(addr);
163 } catch (FormatException) {
164 return GetHostByName(hostName);
169 /// Utility method. This method converts a Hostent instance to a
170 /// IPHostEntry instance.
173 /// Object which should be mapped to a IPHostEntry instance.
175 private static unsafe IPHostEntry ToIPHostEntry(Hostent h) {
176 IPHostEntry res = new IPHostEntry();
179 res.HostName = h.h_name;
181 // Set IP address list
182 byte** p = h.h_addr_list;
183 ArrayList tmp = new ArrayList(1);
185 tmp.Add(CreateIPAddress(*p, h.h_length));
188 IPAddress[] addr_list = new IPAddress[tmp.Count];
189 for(int i = 0; i < tmp.Count; ++i)
190 addr_list[i] = (IPAddress)tmp[i];
191 res.AddressList = addr_list;
197 tmp.Add(new string((sbyte*)*p));
200 string[] aliases = new string[tmp.Count];
201 for(int i = 0; i < tmp.Count; ++i)
202 aliases[i] = (string)tmp[i];
203 res.Aliases = aliases;
209 /// Utility method. Convert IP address in dotted notation
212 private static long CreateAddress(string address) {
213 string[] tokens = address.Split('.');
214 if (tokens.Length % 4 != 0)
215 throw new FormatException("IP address has invalid length");
217 for(int i = 0, j = tokens.Length - 1; i < tokens.Length; ++i, --j) {
219 addr = addr | (((long)byte.Parse(tokens[i])) << j * 8);
220 } catch (OverflowException) {
221 throw new FormatException("Invalid IP address format");
228 /// Utility method. This method creates a IP address.
230 /// <param name=addr>
231 /// IP address in network byte order (e.g. Big-Endian).
233 /// <param name=length>
234 /// Length of IP address (4 or 8 bytes).
236 private static unsafe IPAddress CreateIPAddress(byte* addr, short length) {
239 for(int i = 0, j = length - 1; i < length; ++i, --j) {
243 if (res > uint.MaxValue)
244 return new IPAddress(IPAddress.NetworkToHostOrder(res));
246 return new IPAddress(IPAddress.NetworkToHostOrder((int)res));