2006-02-16 Dick Porter <dick@ximian.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                 private delegate IPHostEntry GetHostByNameCallback (string hostName);
52                 private delegate IPHostEntry ResolveCallback (string hostName);
53
54                 public static IAsyncResult BeginGetHostByName (string hostName,
55                         AsyncCallback requestCallback, object stateObject)
56                 {
57                         if (hostName == null)
58                                 throw new ArgumentNullException ("hostName");
59
60                         GetHostByNameCallback c = new GetHostByNameCallback (GetHostByName);
61                         return c.BeginInvoke (hostName, requestCallback, stateObject);
62                 }
63
64                 public static IAsyncResult BeginResolve (string hostName,
65                         AsyncCallback requestCallback, object stateObject)
66                 {
67                         if (hostName == null)
68                                 throw new ArgumentNullException ("hostName");
69
70                         ResolveCallback c = new ResolveCallback (Resolve);
71                         return c.BeginInvoke (hostName, requestCallback, stateObject);
72                 }
73
74                 public static IPHostEntry EndGetHostByName (IAsyncResult asyncResult) 
75                 {
76                         if (asyncResult == null)
77                                 throw new ArgumentNullException ("asyncResult");
78
79                         AsyncResult async = (AsyncResult) asyncResult;
80                         GetHostByNameCallback cb = (GetHostByNameCallback) async.AsyncDelegate;
81                         return cb.EndInvoke(asyncResult);
82                 }
83
84                 public static IPHostEntry EndResolve (IAsyncResult asyncResult) 
85                 {
86                         if (asyncResult == null)
87                                 throw new ArgumentNullException ("asyncResult");
88                         AsyncResult async = (AsyncResult) asyncResult;
89                         ResolveCallback cb = (ResolveCallback) async.AsyncDelegate;
90                         return cb.EndInvoke(asyncResult);
91                 }
92
93                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
94                 private extern static bool GetHostByName_internal(string host, out string h_name, out string[] h_aliases, out string[] h_addr_list);
95
96                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
97                 private extern static bool GetHostByAddr_internal(string addr, out string h_name, out string[] h_aliases, out string[] h_addr_list);
98
99                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
100                 private extern static bool GetHostName_internal(out string h_name);
101                 
102                 private static IPHostEntry hostent_to_IPHostEntry(string h_name, string[] h_aliases, string[] h_addrlist) 
103                 {
104                         IPHostEntry he = new IPHostEntry();
105                         ArrayList addrlist = new ArrayList();
106
107                         he.HostName = h_name;
108                         he.Aliases = h_aliases;
109                         for(int i=0; i<h_addrlist.Length; i++) {
110                                 try {
111                                         IPAddress newAddress = IPAddress.Parse(h_addrlist[i]);
112
113                                         if( (Socket.SupportsIPv6 && newAddress.AddressFamily == AddressFamily.InterNetworkV6) ||
114                                             (Socket.SupportsIPv4 && newAddress.AddressFamily == AddressFamily.InterNetwork) )
115                                                 addrlist.Add(newAddress);
116                                 } catch (ArgumentNullException) {
117                                         /* Ignore this, as the
118                                          * internal call might have
119                                          * left some blank entries at
120                                          * the end of the array
121                                          */
122                                 }
123                         }
124
125                         if(addrlist.Count == 0)
126                                 throw new SocketException(11001);
127
128                         he.AddressList = addrlist.ToArray(typeof(IPAddress)) as IPAddress[];
129                         return he;
130                 }
131
132                 public static IPHostEntry GetHostByAddress(IPAddress address)
133                 {
134                         if (address == null)
135                                 throw new ArgumentNullException ("address");
136
137                         return GetHostByAddressFromString (address.ToString (), false);
138                 }
139
140                 public static IPHostEntry GetHostByAddress(string address)
141                 {
142                         if (address == null)
143                                 throw new ArgumentNullException ("address");
144
145                         return GetHostByAddressFromString (address, true);
146                 }
147
148                 static IPHostEntry GetHostByAddressFromString (string address, bool parse)
149                 {
150                         // Undocumented MS behavior: when called with IF_ANY,
151                         // this should return the local host
152                         if (address.Equals ("0.0.0.0")) {
153                                 address = "127.0.0.1";
154                                 parse = false;
155                         }
156
157                         // Must check the IP format, might send an exception if invalid string.
158                         if (parse)
159                                 IPAddress.Parse(address);
160
161                         string h_name;
162                         string[] h_aliases, h_addrlist;
163
164                         bool ret = GetHostByAddr_internal(address, out h_name, out h_aliases, out h_addrlist);
165                         if (!ret)
166                                 throw new SocketException(11001);
167
168                         return (hostent_to_IPHostEntry (h_name, h_aliases, h_addrlist));
169                 }
170
171 #if NET_2_0
172                 [MonoTODO]
173                 public static IPHostEntry GetHostEntry (string hostNameOrAddress)
174                 {
175                         if (hostNameOrAddress == null)
176                                 throw new ArgumentNullException ("hostNameOrAddress");
177
178                         return Resolve (hostNameOrAddress);
179                 }
180 #endif
181                 public static IPHostEntry GetHostByName(string hostName) 
182                 {
183                         if (hostName == null)
184                                 throw new ArgumentNullException();
185
186                         string h_name;
187                         string[] h_aliases, h_addrlist;
188
189                         bool ret = GetHostByName_internal(hostName, out h_name,
190                                 out h_aliases,
191                                 out h_addrlist);
192                         if (ret == false)
193                                 throw new SocketException(11001);
194
195                         return(hostent_to_IPHostEntry(h_name, h_aliases,
196                                 h_addrlist));
197                 }
198
199                 public static string GetHostName() 
200                 {
201                         string hostName;
202
203                         bool ret = GetHostName_internal(out hostName);
204
205                         if (ret == false)
206                                 throw new SocketException(11001);
207
208                         return hostName;
209                 }
210
211                 public static IPHostEntry Resolve(string hostName) 
212                 {
213                         if (hostName == null)
214                                 throw new ArgumentNullException ("hostName");
215
216                         IPHostEntry ret = null;
217
218                         try {
219                                 ret =  GetHostByAddress(hostName);
220                         }
221                         catch{}
222
223                         if(ret == null)
224                                 ret =  GetHostByName(hostName);
225
226                         return ret;
227                 }
228         }
229 }
230