2009-02-07 Gonzalo Paniagua Javier <gonzalo@novell.com>
[mono.git] / mcs / class / System / System.Net / Dns.cs
1 // System.Net.Dns.cs
2 //
3 // Author: Mads Pultz (mpultz@diku.dk)
4 // Author: Lawrence Pit (loz@cable.a2000.nl)
5 //
6 // (C) Mads Pultz, 2001
7
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System;
30 using System.Net.Sockets;
31 using System.Text;
32 using System.Collections;
33 using System.Threading;
34 using System.Runtime.CompilerServices;
35 using System.Runtime.Remoting.Messaging;
36
37 namespace System.Net {
38 #if NET_2_0
39         public static class Dns {
40 #else
41         public sealed class Dns {
42
43                 private Dns () {}
44 #endif
45
46                 static Dns ()
47                 {
48                         System.Net.Sockets.Socket.CheckProtocolSupport();
49                 }
50
51 #if !NET_2_1 // global remove of async methods
52
53                 private delegate IPHostEntry GetHostByNameCallback (string hostName);
54                 private delegate IPHostEntry ResolveCallback (string hostName);
55 #if NET_2_0
56                 private delegate IPHostEntry GetHostEntryNameCallback (string hostName);
57                 private delegate IPHostEntry GetHostEntryIPCallback (IPAddress hostAddress);
58                 private delegate IPAddress [] GetHostAddressesCallback (string hostName);
59 #endif
60
61 #if NET_2_0
62                 [Obsolete ("Use BeginGetHostEntry instead")]
63 #endif
64                 public static IAsyncResult BeginGetHostByName (string hostName,
65                         AsyncCallback requestCallback, object stateObject)
66                 {
67                         if (hostName == null)
68                                 throw new ArgumentNullException ("hostName");
69
70                         GetHostByNameCallback c = new GetHostByNameCallback (GetHostByName);
71                         return c.BeginInvoke (hostName, requestCallback, stateObject);
72                 }
73
74 #if NET_2_0
75                 [Obsolete ("Use BeginGetHostEntry instead")]
76 #endif
77                 public static IAsyncResult BeginResolve (string hostName,
78                         AsyncCallback requestCallback, object stateObject)
79                 {
80                         if (hostName == null)
81                                 throw new ArgumentNullException ("hostName");
82
83                         ResolveCallback c = new ResolveCallback (Resolve);
84                         return c.BeginInvoke (hostName, requestCallback, stateObject);
85                 }
86
87 #if NET_2_0
88                 public static IAsyncResult BeginGetHostAddresses (string hostName,
89                         AsyncCallback requestCallback, object stateObject)
90                 {
91                         if (hostName == null)
92                                 throw new ArgumentNullException ("hostName");
93
94                         GetHostAddressesCallback c = new GetHostAddressesCallback (GetHostAddresses);
95                         return c.BeginInvoke (hostName, requestCallback, stateObject);
96                 }
97
98                 public static IAsyncResult BeginGetHostEntry (string hostNameOrAddress,
99                         AsyncCallback requestCallback, object stateObject)
100                 {
101                         if (hostNameOrAddress == null)
102                                 throw new ArgumentNullException ("hostNameOrAddress");
103
104                         GetHostEntryNameCallback c = new GetHostEntryNameCallback (GetHostEntry);
105                         return c.BeginInvoke (hostNameOrAddress, requestCallback, stateObject);
106                 }
107
108                 public static IAsyncResult BeginGetHostEntry (IPAddress hostAddress,
109                         AsyncCallback requestCallback, object stateObject)
110                 {
111                         if (hostAddress == null)
112                                 throw new ArgumentNullException ("hostAddress");
113
114                         GetHostEntryIPCallback c = new GetHostEntryIPCallback (GetHostEntry);
115                         return c.BeginInvoke (hostAddress, requestCallback, stateObject);
116                 }
117 #endif
118
119 #if NET_2_0
120                 [Obsolete ("Use EndGetHostEntry instead")]
121 #endif
122                 public static IPHostEntry EndGetHostByName (IAsyncResult asyncResult) 
123                 {
124                         if (asyncResult == null)
125                                 throw new ArgumentNullException ("asyncResult");
126
127                         AsyncResult async = (AsyncResult) asyncResult;
128                         GetHostByNameCallback cb = (GetHostByNameCallback) async.AsyncDelegate;
129                         return cb.EndInvoke(asyncResult);
130                 }
131
132 #if NET_2_0
133                 [Obsolete ("Use EndGetHostEntry instead")]
134 #endif
135                 public static IPHostEntry EndResolve (IAsyncResult asyncResult) 
136                 {
137                         if (asyncResult == null)
138                                 throw new ArgumentNullException ("asyncResult");
139                         AsyncResult async = (AsyncResult) asyncResult;
140                         ResolveCallback cb = (ResolveCallback) async.AsyncDelegate;
141                         return cb.EndInvoke(asyncResult);
142                 }
143
144 #if NET_2_0
145
146                 public static IPAddress [] EndGetHostAddresses (IAsyncResult asyncResult) 
147                 {
148                         if (asyncResult == null)
149                                 throw new ArgumentNullException ("asyncResult");
150
151                         AsyncResult async = (AsyncResult) asyncResult;
152                         GetHostAddressesCallback cb = (GetHostAddressesCallback) async.AsyncDelegate;
153                         return cb.EndInvoke(asyncResult);
154                 }
155
156                 public static IPHostEntry EndGetHostEntry (IAsyncResult asyncResult) 
157                 {
158                         if (asyncResult == null)
159                                 throw new ArgumentNullException ("asyncResult");
160                         AsyncResult async = (AsyncResult) asyncResult;
161 #if NET_2_0
162                         if (async.AsyncDelegate is GetHostEntryIPCallback)
163                                 return ((GetHostEntryIPCallback) async.AsyncDelegate).EndInvoke (asyncResult);
164 #endif
165                         GetHostEntryNameCallback cb = (GetHostEntryNameCallback) async.AsyncDelegate;
166                         return cb.EndInvoke(asyncResult);
167                 }
168 #endif
169                 
170 #endif // !NET_2_1: global remove of async methods
171
172 #if !TARGET_JVM
173                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
174                 private extern static bool GetHostByName_internal(string host, out string h_name, out string[] h_aliases, out string[] h_addr_list);
175
176                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
177                 private extern static bool GetHostByAddr_internal(string addr, out string h_name, out string[] h_aliases, out string[] h_addr_list);
178
179                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
180                 private extern static bool GetHostName_internal(out string h_name);
181 #endif  
182
183                 private static IPHostEntry hostent_to_IPHostEntry(string h_name, string[] h_aliases, string[] h_addrlist) 
184                 {
185                         IPHostEntry he = new IPHostEntry();
186                         ArrayList addrlist = new ArrayList();
187
188                         he.HostName = h_name;
189                         he.Aliases = h_aliases;
190                         for(int i=0; i<h_addrlist.Length; i++) {
191                                 try {
192                                         IPAddress newAddress = IPAddress.Parse(h_addrlist[i]);
193
194                                         if( (Socket.SupportsIPv6 && newAddress.AddressFamily == AddressFamily.InterNetworkV6) ||
195                                             (Socket.SupportsIPv4 && newAddress.AddressFamily == AddressFamily.InterNetwork) )
196                                                 addrlist.Add(newAddress);
197                                 } catch (ArgumentNullException) {
198                                         /* Ignore this, as the
199                                          * internal call might have
200                                          * left some blank entries at
201                                          * the end of the array
202                                          */
203                                 }
204                         }
205
206                         if(addrlist.Count == 0)
207                                 throw new SocketException(11001);
208
209                         he.AddressList = addrlist.ToArray(typeof(IPAddress)) as IPAddress[];
210                         return he;
211                 }
212
213 #if NET_2_0
214                 [Obsolete ("Use GetHostEntry instead")]
215 #endif
216                 public static IPHostEntry GetHostByAddress(IPAddress address)
217                 {
218                         if (address == null)
219                                 throw new ArgumentNullException ("address");
220
221                         return GetHostByAddressFromString (address.ToString (), false);
222                 }
223
224 #if NET_2_0
225                 [Obsolete ("Use GetHostEntry instead")]
226 #endif
227                 public static IPHostEntry GetHostByAddress(string address)
228                 {
229                         if (address == null)
230                                 throw new ArgumentNullException ("address");
231
232                         return GetHostByAddressFromString (address, true);
233                 }
234
235                 static IPHostEntry GetHostByAddressFromString (string address, bool parse)
236                 {
237                         // Undocumented MS behavior: when called with IF_ANY,
238                         // this should return the local host
239                         if (address.Equals ("0.0.0.0")) {
240                                 address = "127.0.0.1";
241                                 parse = false;
242                         }
243
244                         // Must check the IP format, might send an exception if invalid string.
245                         if (parse)
246                                 IPAddress.Parse (address);
247
248                         string h_name;
249                         string[] h_aliases, h_addrlist;
250 #if TARGET_JVM
251                         h_name = null;
252                         h_aliases = null;
253                         h_addrlist = null;
254                         try {
255                                 java.net.InetAddress[] iaArr = 
256                                         java.net.InetAddress.getAllByName(address);
257                                 if (iaArr != null && iaArr.Length > 0)
258                                     h_name = iaArr[0].getHostName();
259                                 if (iaArr != null && iaArr.Length > 0)
260                                 {
261                                     h_addrlist = new String[iaArr.Length];
262                                     for (int i = 0; i < h_addrlist.Length; i++)
263                                         h_addrlist[i] = iaArr[i].getHostAddress();
264                                 }
265                         } catch (java.net.UnknownHostException jUHE) {
266                                 throw new SocketException((int)SocketError.HostNotFound, jUHE.Message);
267                         }
268 #else
269                         bool ret = GetHostByAddr_internal(address, out h_name, out h_aliases, out h_addrlist);
270                         if (!ret)
271                                 throw new SocketException(11001);
272 #endif
273                         return (hostent_to_IPHostEntry (h_name, h_aliases, h_addrlist));
274                         
275                 }
276
277 #if NET_2_0
278                 public static IPHostEntry GetHostEntry (string hostNameOrAddress)
279                 {
280                         if (hostNameOrAddress == null)
281                                 throw new ArgumentNullException ("hostNameOrAddress");
282
283                         if (hostNameOrAddress == "0.0.0.0")
284                                 hostNameOrAddress = "";
285                         IPAddress addr;
286                         if (hostNameOrAddress.Length > 0 && IPAddress.TryParse (hostNameOrAddress, out addr))
287                                 return GetHostEntry (addr);
288
289                         return GetHostByName (hostNameOrAddress);
290                 }
291
292                 public static IPHostEntry GetHostEntry (IPAddress address)
293                 {
294                         if (address == null)
295                                 throw new ArgumentNullException ("address");
296
297                         return GetHostByAddressFromString (address.ToString (), false);
298                 }
299
300                 public static IPAddress [] GetHostAddresses (string hostNameOrAddress)
301                 {
302                         if (hostNameOrAddress == null)
303                                 throw new ArgumentNullException ("hostNameOrAddress");
304
305                         if (hostNameOrAddress == "0.0.0.0")
306                                 hostNameOrAddress = "";
307
308                         IPAddress addr;
309                         if (hostNameOrAddress.Length > 0 && IPAddress.TryParse (hostNameOrAddress, out addr))
310                                 return new IPAddress[1] { addr };
311
312                         return GetHostEntry (hostNameOrAddress).AddressList;
313                 }
314 #endif
315
316 #if NET_2_0
317                 [Obsolete ("Use GetHostEntry instead")]
318 #endif
319                 public static IPHostEntry GetHostByName (string hostName)
320                 {
321                         if (hostName == null)
322                                 throw new ArgumentNullException ();
323 #if TARGET_JVM
324                         if (hostName.Length == 0)
325                                 hostName = "localhost";
326                         try {
327                                 java.net.InetAddress[] iaArr = java.net.InetAddress.getAllByName(hostName);
328                                 IPHostEntry host = new IPHostEntry();
329                                 if (iaArr != null && iaArr.Length > 0)
330                                 {
331                                         host.HostName = iaArr[0].getHostName();
332                                         IPAddress[] ipArr = new IPAddress[iaArr.Length];
333                                         for (int i = 0; i < iaArr.Length; i++)
334                                                 ipArr[i] = IPAddress.Parse(iaArr[i].getHostAddress());
335
336                                         host.AddressList = ipArr;
337                                 }
338                                 return host;
339                         } catch (java.net.UnknownHostException jUHE) {
340                                 throw new SocketException((int)SocketError.HostNotFound, jUHE.Message);
341                         }
342 #else
343                         string h_name;
344                         string[] h_aliases, h_addrlist;
345
346                         bool ret = GetHostByName_internal(hostName, out h_name, out h_aliases, out h_addrlist);
347                         if (ret == false)
348                                 throw new SocketException(11001);
349
350                         return(hostent_to_IPHostEntry(h_name, h_aliases, h_addrlist));
351 #endif
352                 }
353
354                 public static string GetHostName ()
355                 {
356 #if TARGET_JVM
357                         return java.net.InetAddress.getLocalHost ().getHostName ();
358 #else
359                         string hostName;
360
361                         bool ret = GetHostName_internal(out hostName);
362
363                         if (ret == false)
364                                 throw new SocketException(11001);
365
366                         return hostName;
367 #endif
368                 }
369
370 #if NET_2_0
371                 [Obsolete ("Use GetHostEntry instead")]
372 #endif
373                 public static IPHostEntry Resolve(string hostName) 
374                 {
375                         if (hostName == null)
376                                 throw new ArgumentNullException ("hostName");
377
378                         IPHostEntry ret = null;
379
380                         try {
381                                 ret =  GetHostByAddress(hostName);
382                         }
383                         catch{}
384
385                         if(ret == null)
386                                 ret =  GetHostByName(hostName);
387
388                         return ret;
389                 }
390         }
391 }
392